如何使用进位和溢出标志来计算x86中的乘法

时间:2016-12-16 22:34:04

标签: assembly x86

当两个乘以的数字溢出寄存器时,两个标志如何用于正确计算答案?

E.g。如果al持有0xff并且乘以0x2,导致溢出到ax,那么这些标志如何帮助解决这个问题?

2 个答案:

答案 0 :(得分:3)

使用一个操作数形式时,x86 / x64上的乘法永远不会溢出 这是因为mul及其兄弟imul产生的输出是其操作数 1 的两倍。
在您的示例中,乘以al会在ax中生成输出,并且不会生成溢出。

当结果无法适合操作数大小时,CFOF会被设置。
这可用于执行与饱和度的乘法,例如:

;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做什么应该是微不足道的。您可以在发布此处之前制作此实验,遍历每个操作数组合并查看标记为每个操作组执行的操作。