x86 IMUL结果是对的,为什么?

时间:2012-01-08 09:03:46

标签: assembly x86

    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

没有办法溢出因为:

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

为何溢出?

感谢回复。

1 个答案:

答案 0 :(得分:6)

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

确实必须在0x15F61998EDX 0x9EA1DC29中生成EAX。那是因为IMUL将其操作数视为签名。

换句话说,由于0xB504F333表示2的补码中的负值(因为其最高有效位已设置),因此该指令实际上将0xB504F333-0x100000000=-1257966797而不是0xB504F333=3037000499相乘。

所以正确的结果是0x15F619989EA1DC29=1582480462354439209而不是0x7FFFFFFF9EA1DC29=9223372030926249001

由于EDX:EAX中的64位签名产品不是EAX的符号扩展值,这意味着签名产品不适合32位,IMUL设置进位和溢出标志为1.这一点在Intel和AMD CPU手册中有解释。

如果您使用MUL ECX代替IMUL ECX,您将在0x7FFFFFFF9EA1DC29=9223372030926249001中获得EDX:EAX,并且将再次设置溢出和进位标记,因为现在未签名的产品仍然没有不适合32位。