Previous Section Table of Contents Next Section

Multiply Two Numbers Using Shifts

This function multiplies two numbers using shift and add operations.

The parameters are passed on the stack. The procedure stores the two parameters in the word registers bx and dx, and accumulates the result in eax, providing 16 bit ¥ 16 bit = 32-bit multiplication. For each bit that is on in dx, it adds the value "bx shifted left the appropriate number of bits" to eax. When it has checked every bit in dx, the correct result will be in eax, which is where the procedure is defined to return it.

The procedure does preserve the passed-in value of registers, and is responsible for popping parameters off the stack. Note that the two numbers are pushed on the stack as words, not dwords.

The test instruction sets the flags as if it were a logical and, without actually modifying the value of the operands.

Source Code


 1.     multiply:

 2.         ; save registers we use

 3.         push ebp

 4.         mov ebp, esp

 5.         push ebx

 6.         push edx

 7.

 8.         xor ebx, ebx     ; ensure high 16 bits are zeroed out

 9.         mov dx, [ebp+8]  ; second parameter

10.         mov bx, [ebp+10] ; first parameter

11.

12.         ; eax accumulates the result

13.         mov eax, 0

14.

15.     mainloop:

16.         cmp dx, 0

17.         je done           ; no bits left in ax

18.

19.         test dx, 1

20.         jz noton          ; this bit is not on, so don't add

21.         add eax, ebx

22.         shl ebx, 1        ; ebx = ebx * 2

23.     noton:

24.         shr dx, 1         ; try the next bit

25.         jmp mainloop

26.

27.     done:

28.         ; restore saved values

29.         pop edx

30.         pop ebx

31.         pop ebp

32.

33.         ret 4             ; pop 2 word parameters


Suggestions

  1. What is the goal of the first iteration through mainloop on lines 15-25?

  2. What is an input that causes mainloop to iterate exactly once?

  3. The two numbers to be multiplied are stored in bx and dx. How come it is necessary to clear the high 16 bits of ebx (on line 8) but not of edx?

  4. Does the program save/restore registers properly and access the pushed parameters at the correct offset from ebp?

Hints

Walk through the procedure with the following two words pushed on the stack (the current stack location is at the bottom; numbers are shown in binary for convenience):

  1. Only one bit on in the second number:

    101

    1

  2. Same scenario in reverse:

    1

    101

  3. Two bits in each word:

    11

    11

  4. The high bit is on in each number:

    1000000000000000

    1000000000000000

Explanation of the Bug

The code on line 22 to shift ebx to the left


shl ebx, 1        ; ebx = ebx * 2


must be executed each time through mainloop, not only in cases where the low bit of dx was on. It should be moved down one line to be after the noton label. Otherwise, the program works incorrectly unless the second parameter (the one stored in dx) is one less than a power of 2, which means its binary representation looks like 1, 11, 111, etc. For numbers like that, the missed shifts won't affect the final result.

This could be an F.location error, but it is more likely an A.logic error.

    Previous Section Table of Contents Next Section