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

fla*_*nka 0 x86 assembly

    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
Run Code Online (Sandbox Code Playgroud)

它没有办法溢出因为:

7FFFFFFFFFFFFFFF = 9223372036854775807 => sqrt(9223372036854775807) = 3037000499 = 0xB504F333
0xB504F333 * 0xB504F333 < 7FFFFFFFFFFFFFFF (EDX:EAX)
Run Code Online (Sandbox Code Playgroud)

为何溢出?

谢谢你的回复.

Ale*_*nze 6

MOV EAX,0xB504F333
MOV ECX,0xB504F333
IMUL ECX
Run Code Online (Sandbox Code Playgroud)

的确应该产生0x15F61998EDX0x9EA1DC29EAX.那是因为IMUL将其操作数视为签名.

换句话说,因为0xB504F333在2的补码中表示负值(因为其最高有效位被设置),所以指令实际上是倍增0xB504F333-0x100000000=-1257966797而不是0xB504F333=3037000499自身.

所以正确的结果是0x15F619989EA1DC29=1582480462354439209代替0x7FFFFFFF9EA1DC29=9223372030926249001.

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

如果你使用MUL ECX的不是IMUL ECX,你会得到0x7FFFFFFF9EA1DC29=9223372030926249001EDX:EAX,溢出和进位标志将被重新设定,因为现在的无符号的产品还是不适合32位.