tags:

views:

464

answers:

4

I'm learning 80386 from PC Assembly by paul caurter

  mul source
  • If the operand is byte sized, it is multiplied by the byte in the AL register and the result is stored in the 16 bits of AX.

fine.

  • If the source is 16-bit, it is multiplied by the word in AX and the 32-bit result is stored in DX:AX.

Q1: Why DX:AX ? Why can't it store in EAX / EDX?

imul is really confusing

imul dest, source1
imul dest, source1, source2

alt text

I've problem in understanding the table.

Q2: in the 2nd entry of the table. Again, why DX:AX. Why not EAX or EDX?

Now consider following code snippet:

imul eax ; edx:eax = eax * eax
mov ebx, eax ; save answer in ebx
mov eax, square_msg ; square_msg db "Square of input is ", 0
call print_string ; prints the string eax
mov eax, ebx 
call print_int ;  prints the int stored in eax
call print_nl ; prints new line

Q3: Its previsously said that The notation EDX:EAX means to think of the EDX and EAX registers as one 64 bit register with the upper 32 bits in EDX and the lower bits in EAX. So the answer is also stored in edx, right? in the above code we didn't consider any EDX we are just referring to EAX How is this still working?

Q4: I've problem with rest of all entries in the table. worst case multiplication result of two n bit numbers(n = 8/16/32 bits) is 2n bits. How come its storing the result of two 16/32 bit multiplication result in register of same size itself?

+3  A: 

Q1/Q2: The x86 instruction set maintains its 16-bit history. When doing a 16-bit multiply, the answer is stored in DX:AX. That's just the way it is, because that's how it was in 16-bit land.

Q3: The code you showed has a bug if you try to compute the square of a number larger than 2^16, because the code ignores the high 32 bits of the result stored in edx.

Q4: I think you may be misreading the table. 8-bit multiplications are stored in a 16-bit result; 16-bit multiplications are stored in a 32-bit result; 32-bit multiplications are stored in a 64-bit result. Which line are you referring to specifically?

Greg Hewgill
@Q3: I knew it. this is the code from that book by paul carter. Can you tell me how the code should be? I'm confused how to print the result.
claws
The code as given is just an example; the text should mention somewhere that it won't calculate the square properly if the input is outside the expected range. Since you're calling a `print_int` function to print a 32-bit integer, see if you can find a `print_int64` function to print a 64-bit integer.
Greg Hewgill
claws
I see what you mean. The "dest" register is indicating the size of a *single* register in the result; so a 32-bit result goes into *two* 16-bit registers. Similarly, a 64-bit result goes into *two* 32-bit registers. That is a bit confusing, but I think you've got it.
Greg Hewgill
A: 

Q1/Q2: I think the reason is historical. Before 32-bit was an option, there was no eax or edx. The 32-bit functionality was added to be reverse compatible.

Q3: The low order bits are going to be in eax. Those are the only ones you care about unless there's overflow into the high bits.

Q4: Definitely an odd table. I think you get it though.

Ken Aspeslagh
A: 

A1: mul was originally present on the 8086/8088/80186/80286 processors, which didn't have the E** (E for extended, i.e. 32-bit) registers.

A2: See A1.

As my work as an assembly language programmer moved to the Motorola 680x0 family before those 32-bit Intels became commonplace, I'll stop there :-)

NickFitz
I was loving 680x0 processor, i found them easier to program than X86 :)
Patrick
+1  A: 

Oh well..

There are lots of different variations of the imul instruction. And to make things worse they work different if you write 16 bit code vs. 32 bit code.

The variant you've stumbled upon is a 16 bit multiplication. It multiplies the AX register with whatever you pass as the argument to imul and stores the result in DX:AX.

One 32 bit variant works like the 16 bit multiplication but writes the register into EDX:EAX. To use this variant all you have to do is to use a 32 bit argument.

E.g:

  ; a 16 bit multiplication:
  mov ax, factor1
  mov bx, factor2
  imul bx  ; result in DX:AX

  ; a 32 bit multiplication:
  mov eax, factor1
  mov ebx, factor2 
  imul ebx ; result in EDX:EAX

In 32 bit code, you can also write an imul in the three operand form. That makes it much more flexible and easier to work with. In this variant you can choose the destination register and the arguments freely but the result will only be 32 bits long. This variant of imul does not exist for 16 bit code btw...

  mov eax, factor1
  mov ebx, factor2
  imul ecx, eax, ebx  ; result in ecx
Nils Pipenbrinck
can you please show how would you print the result of EDX:EAX `; a 32 bit multiplication:`.
claws