flatronka
flatronka

Reputation: 1081

x86 IMUL result is correct, why?

    MOV EAX,0XB504F333
    MOV ECX,0XB504F333
    ;EAX = B504F333
    ;ECX = B504F333
    IMUL ECX ;RESULT=
------------------------------
    ;EDX = 15F61998 ;it is incorrect the correct value is 7FFFFFFF
    ;EAX = 9EA1DC29 ;it is correct 
    ;Carry flag = 1
    ;Overflow flag = 1
    ;Sign flag = 0

It's no way to overflow because:

7FFFFFFFFFFFFFFF = 9223372036854775807 => sqrt(9223372036854775807) = 3037000499 = 0xB504F333
0xB504F333 * 0xB504F333 < 7FFFFFFFFFFFFFFF (EDX:EAX)

Why overflow?

Thanks the replies.

Upvotes: 0

Views: 2384

Answers (1)

Alexey Frunze
Alexey Frunze

Reputation: 62106

MOV EAX,0xB504F333
MOV ECX,0xB504F333
IMUL ECX

Must indeed produce 0x15F61998 in EDX and 0x9EA1DC29 in EAX. That's because IMUL treats its operands as signed.

In other words, since 0xB504F333 represents a negative value in 2's complement code (because its most significant bit is set), the instruction actually multiplies 0xB504F333-0x100000000=-1257966797 instead of 0xB504F333=3037000499 by itself.

And so the correct result is 0x15F619989EA1DC29=1582480462354439209 instead of 0x7FFFFFFF9EA1DC29=9223372030926249001.

Since the 64-bit signed product in EDX:EAX is not the sign extended value of EAX, which means that the signed product doesn't fit into 32 bits, IMUL sets the carry and overflow flags to 1. This all is explained in the Intel and AMD CPU manuals.

If you use MUL ECX instead of IMUL ECX, you will get 0x7FFFFFFF9EA1DC29=9223372030926249001 in EDX:EAX and the overflow and carry flags will be set again because the now unsigned product still doesn't fit into 32 bits.

Upvotes: 6

Related Questions