当两个乘以的数字溢出寄存器时,两个标志如何用于正确计算答案?
E.g。如果al
持有0xff
并且乘以0x2
,导致溢出到ax
,那么这些标志如何帮助解决这个问题?
答案 0 :(得分:3)
使用一个操作数形式时,x86 / x64上的乘法永远不会溢出
这是因为mul及其兄弟imul产生的输出是其操作数 1 的两倍。
在您的示例中,乘以al
会在ax
中生成输出,并且不会生成溢出。
当结果无法适合操作数大小时,CF
和OF
会被设置。
这可用于执行与饱和度的乘法,例如:
;Unsigned
mul ebx
sbb edx, edx ;EDX = CF replicated along all the 32 bits
or eax, edx ;EAX = 0ff..ffh if overflow, EAX*EBX otherwise
;Signed
imul ebx
cmovc eax, 7fffffffh ;Signed positive max if overflow
and edx, 80000000h ;Keep only the sign of the result
or eax, edx ;If no overflow bit 31 of EAX = bit 31 of EDX
;and this is a nop, otherwise set EAX to negative max
;if the result was negative
然而,要实现多精度乘法,比如说64x64位,那些标志是不需要的,事实上,用2 32 表示 k 我们有:< / p>
(a· k + b)×(c· k + d)= a·c· k 2 < / sup> +(a·d + b·c)· k + b·d
其中32位产品生成64位结果,如下所示
.----.----.
| b·d |
'----'----'
+
.----.----.
| a·d+b·c |
'----'----'
+
.----.----.
| a·c |
'----'----'
=
.----.----.----.----.
| 128-bit result |
'----'----'----'----'
1 这足以防止溢出。
答案 1 :(得分:1)
回答这类问题的最佳方法是阅读手册。
现在我要回到80188/186的纸质副本(我不知道我的8088/8086编程手册在哪里)。但就在那时,就像人们所说的那样。文字说
如果源是一个字节,则它乘以寄存器AL,并在AH和AL中返回双倍长度结果。
这一切都很好:正如人们所说,你不能溢出,但人们通常不会编写使用两倍于操作数大小的结果的高级语言代码。它进一步说:
如果结果的上半部分为非零,则设置CF和OF;否则他们会被清除。
所以你去了:如果你正在进行8位操作并且结果不适合8位(0xFF * 2 = 0x1FE),那么CF和OF都会被置位。至少,他们是20年前。做一个实验来看看你当前的x86做什么应该是微不足道的。您可以在发布此处之前制作此实验,遍历每个操作数组合并查看标记为每个操作组执行的操作。