我不明白为什么imul在下面的指令中设置OF
imul
OF
mov al, 48 mov bl, 4 imul bl ; AX = 00C0h, OF = 1
但在以下说明中不
mov ax, 48 mov bx, 4 imul bx ; DX:AX = 000000C0h, OF = 0
kjthegm61#
IMUL在结果的低半部分(解释为适当大小的有符号整数)不等于两个输入数相乘的数学结果时设置溢出标志。48乘以4的数学结果是192。AL中imul bl后面的值是C0h。作为一个有符号的8位整数,它代表数字-64。从数学上讲,192和-64不是同一个数字,因此必须设置溢出。在imul bx之后,AX中剩下的值是00C0h。作为一个有符号的16位整数,它表示数字192。因此,未设置溢出标志。同样,如果对低半部分进行符号扩展将产生与全积不同的值,则设置溢出标志。当对8位值C0h进行符号扩展到16位时,将得到FFC0h,它不等于00C0h,因此设置溢出。当对16位值00C0h进行符号扩展到32位时,将得到000000C0h。其等于实际的32位结果,因此不设置overflow。等价地,只有当结果的高半部分的每一位都等于低半部分的符号位时,溢出标志才被清除。8位值C0h的符号位是1,但高半部分不是FFh,而是00 h,因此设置溢出。16位值00C0h的符号位是0,高半部分是0000h。因此溢出被清除。
IMUL
imul bl
C0h
imul bx
00C0h
FFC0h
000000C0h
0000h
brc7rcf02#
OF告诉您是否可以在不更改其值的情况下将双宽度完整结果截断回输入宽度。(对于imul 1,解释为2的补码整数;对于mul,解释为无符号二进制整数。)0xC0是负8位数的位模式,但0x00C0是正16位数。如果您将imul或mul用作add等其他8位或16位运算序列的一部分,而 * 没有 * 计划使用结果的高半部分,那么您需要知道的就是这些。(Or如果窄精度版本的速度足够快,值得进行分支,则回退到处理较宽大小的扩展精度版本可能会很有用。)如果你已经打算使用输出的全宽度,不要选中OF/CF;扩展乘法不会溢出而丢失任何输出位。两个N位数的乘积总是可以用2N位表示。
mul
0xC0
0x00C0
add
脚注1:包括2和3操作数形式,如imul cx, dx, 123,它不会在任何地方写入高半部分。通常情况下,您会将该形式用于非扩展的有符号或无符号数学运算,但如果您想检测无符号乘法何时换行,最好的办法是只使用mul,即使这会迫使您使用EAX,并将输出保存在EDX:EAX中。请参阅imulq and unsigned long long overflow detection in C and asm
imul cx, dx, 123
2条答案
按热度按时间kjthegm61#
IMUL
在结果的低半部分(解释为适当大小的有符号整数)不等于两个输入数相乘的数学结果时设置溢出标志。48乘以4的数学结果是192。AL中
imul bl
后面的值是C0h
。作为一个有符号的8位整数,它代表数字-64。从数学上讲,192和-64不是同一个数字,因此必须设置溢出。在
imul bx
之后,AX中剩下的值是00C0h
。作为一个有符号的16位整数,它表示数字192。因此,未设置溢出标志。同样,如果对低半部分进行符号扩展将产生与全积不同的值,则设置溢出标志。当对8位值
C0h
进行符号扩展到16位时,将得到FFC0h
,它不等于00C0h
,因此设置溢出。当对16位值00C0h
进行符号扩展到32位时,将得到000000C0h
。其等于实际的32位结果,因此不设置overflow。等价地,只有当结果的高半部分的每一位都等于低半部分的符号位时,溢出标志才被清除。8位值
C0h
的符号位是1,但高半部分不是FFh,而是00 h,因此设置溢出。16位值00C0h
的符号位是0,高半部分是0000h
。因此溢出被清除。brc7rcf02#
OF
告诉您是否可以在不更改其值的情况下将双宽度完整结果截断回输入宽度。(对于imul
1,解释为2的补码整数;对于mul
,解释为无符号二进制整数。)0xC0
是负8位数的位模式,但0x00C0
是正16位数。如果您将
imul
或mul
用作add
等其他8位或16位运算序列的一部分,而 * 没有 * 计划使用结果的高半部分,那么您需要知道的就是这些。(Or如果窄精度版本的速度足够快,值得进行分支,则回退到处理较宽大小的扩展精度版本可能会很有用。)
如果你已经打算使用输出的全宽度,不要选中OF/CF;扩展乘法不会溢出而丢失任何输出位。两个N位数的乘积总是可以用2N位表示。
脚注1:包括2和3操作数形式,如
imul cx, dx, 123
,它不会在任何地方写入高半部分。通常情况下,您会将该形式用于非扩展的有符号或无符号数学运算,但如果您想检测无符号乘法何时换行,最好的办法是只使用mul
,即使这会迫使您使用EAX,并将输出保存在EDX:EAX中。请参阅imulq and unsigned long long overflow detection in C and asm