简体   繁体   English

如何在x86中将进位和溢出标志用于计算乘法

[英]How are the carry and overflow flags used to calculate multiplication in x86

How are the two flags used to correctly calculate the answer when two numbers that are multiplied overflow the register? 当两个数字相乘溢出寄存器时,如何使用这两个标志正确计算答案?

Eg if al holds 0xff and is multiplied by 0x2 , causing an overflow into ax , how do the flags help with this? 例如,如果al持有0xff并乘以0x2 ,导致ax溢出,这些标志如何帮助呢?

Multiplication on x86/x64 never overflows when using the one operand form. 使用一个操作数形式时,x86 / x64上的乘法永远不会溢出。
This is because mul and its sibling imul produce an output twice as wide as their operands 1 . 这是因为mul及其同级imul产生的输出是其操作数1的两倍。
In your example, multiplying by al produces an output in ax and no overflow is generated. 在您的示例中,乘以al产生ax的输出,并且不会产生溢出。

The CF and OF are set when the result cannot fit in the operands size. 当结果不适合操作数大小时OF设置CFOF
This can be used to perform multiplication with saturation, for example: 这可用于执行饱和相乘,例如:

;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

However to implement a multi-precision multiplication, say 64x64-bit, those flags are not needed, in fact, denoting with 2 32 with k we have: 但是,要实现多精度乘法(例如64x64位),则不需要这些标志,实际上,用k表示2 32 ,我们有:

(a· k +b) × (c· k +d) = a·c· k 2 + (a·d+b·c)· k + b·d (a· k + b)×(c· k + d)= a·c· k 2 +(a·d + b·c)· k + b·d

where the 32-bit products produce 64-bit results that are added as below 32位乘积产生64位结果的结果如下所示

.----.----.
|   b·d   |
'----'----'
       +
     .----.----.
     | a·d+b·c |
     '----'----'
            +
          .----.----.
          |   a·c   |
          '----'----'

 =

.----.----.----.----.
|    128-bit result |
'----'----'----'----' 

1 And this suffices to prevent overflow. 1这足以防止溢出。

The best way to answer questions like this is to read the manual. 回答此类问题的最佳方法是阅读手册。

Now I am going back to my paper copy of an 80188/186 (I don't know where my 8088/8086 programming manual is). 现在,我要返回80188/186的纸质副本(我不知道8088/8086编程手册在哪里)。 But even back then, it is like folks are saying. 但是即使在那时,这就像人们在说。 The text says 文字说

If the source is a byte, then it is multiplied by register AL, and the double length result is returned in AH and AL. 如果源是一个字节,则将其与寄存器AL相乘,并将双倍长度的结果返回到AH和AL中。

And that is all fine: you can't overflow, as folks are saying, but folks don't normally write high-level language code that uses a result twice the size of the operands. 没关系,正如人们所说的那样,您不会溢出,但是人们通常不会编写使用结果是操作数大小两倍的高级语言代码。 It goes further to say: 进一步说:

If the upper half of the result is non-zero CF and OF are set; 如果结果的上半部分非零,则设置CF和OF;否则,设置为0。 otherwise they are cleared. 否则,它们将被清除。

So there you go: if you are doing an 8-bit operation and the result does not fit in 8 bits (0xFF * 2 = 0x1FE), then both CF and OF are set. 这样就可以了:如果您正在执行8位运算,而结果不适合8位(0xFF * 2 = 0x1FE),则CF和OF都将置位。 At least, they were 20 years ago. 至少他们是20年前。 It should be quite trivial to do an experiment to see what your current x86 does. 进行实验以查看当前x86的功能应该很简单。 You could have crafted this experiment before posting here, walk through every combination of operands and see what the flags do for each. 您可能已经精心制作了这个实验,然后再在此处发布,遍历每个操作数的组合并查看这些标志的作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM