在Kip Irvine的书中,他谈到了设置溢出标志的机制,他写道:
CPU使用一种有趣的机制来确定加减运算后溢出标志的状态。进位标志与结果的高位进行异或运算。结果值被置于溢出标志中。
我写了一个简单的程序,说明在al寄存器中将5加到127会设置溢出标志:
0111 1111 + 0000 0101 = 1000 0100 carry flag = 0, high bit = 1, overflow = 1
但是,在al寄存器中将5加到255并不会设置溢出标志:
1111 1111 + 0000 0101 = 0000 0100 carry flag = 1, high bit = 0, overflow = 0
为什么在第二个例子中没有设置溢出标志?条件语句不满足?进位标志= 1且高位= 0?
3条答案
按热度按时间mm9b1k5b1#
在第二个示例
255 + 5
中没有设置溢出标志的原因是因为它涉及到有符号算术。您将-1 + 5
相加,得到4。没有溢出:结果是正确的。正如@杰斯特评论的那样,你的书中一定有错误。我的8086书是这样描述Overflow标志的:
如果位6至位7(符号位)之间存在内部进位且没有外部进位,则该位将被置位。如果位6至位7之间没有内部进位且存在外部进位,则该位也将被置位。
编辑
该段继续说:
对于有技术头脑的读者来说,溢出标志是通过对第7位(符号位)的进位输入和进位输出进行异或来设置的。
在第二个例子中,执行1(到进位标志),并且因为所有的位都被置位,所以在内部加法期间必定存在内部进位输入,即使结果b7是0。
kxxlusnw2#
您可以编写一个简单的程序来检查该逻辑如何处理3位加法/减法。
给予
因此,对于加法,您将有一个如下所示的标志(根据定义,有符号溢出标志用于将位解释为有符号位时)
所以1 + 3(001 + 011)=位模式100,其在三位二进制补码世界中具有值-4,因此1 + 3 = -4,这是错误的,因此有符号溢出,我们不能用3位来表示+4。在x86上,这相当于127+1的8位加法(0x 7 F +0x 01),基本上所有的正数组合,结果是128(或更大),126+2,125+3,124+4等等,都有这个问题。
我做了加法和减法,减法在逻辑上来自于二进制补码,取反和加1,所以减法
c = a - b
用c = a + (-b)
代替,从二进制补码我们知道这意味着c = a + ((~b)+1)
或c = a + ~b + 1
,加法是c = a + b + 0
,后面的1或0是lsbit的进位。现在把这一步进一步相加
c = a + b + cin
,减法c = a + ~b + ~cin
。您反转第二个操作数和进位输入。但这是特定于处理器的,因为某些处理器会反转进位输出(我认为x86是一个),使它成为一个“借位”,而不是“进位”的减法。然后,如果你有这些指令,那就搞砸了进位加或借位减的概念(这些逻辑不会简单地反转sbb上的cin)我用三种不同的方法(真的吗?)计算了溢出标志。
就像你正在阅读的文本中的一样,如果进入加法器的符号相同,那么溢出将与结果的msbit执行异或。
ovx是与msbit的进位输出相比的溢出进位输入的定义
如果你想找出溢出,但没有N+1位寄存器,ovy是一个快捷方式(在一种看不到进位的语言中,你如何使用32位变量找出溢出?我在代码中展示了许多方法,但简单地检查msbits也可以)。
如果结果不符合可用的位数,则表示溢出。对于无符号,为true(随身携带)并签署因为这是关于溢出的,所以这是关于有符号的数,所以对于我的三位系统,你只能得到从-4到+3的任何大于+3或小于-4不合适,打印输出末尾的X显示了这一点,因此这是在此简化示例中显示溢出的第四种方式。
同样,上面的输出是通用逻辑将如何执行此操作,然后您会看到处理器系列与进位输出标志的细微差别,一些处理器将进位输出反转以使其成为借位,而一些处理器在执行减法时则不这样做。真正的真实的逻辑将级联一串3个输入(两个操作数和进位输入)两个输出(结果和进位)加法器一起,尽管在HDL语言中你可以使用一个加号运算符来解决这个问题(在那些语言中还需要一个这样的快捷方式,即不检查carry in与carry)
如果你使用布尔方程,你应该能够发现计算溢出的三种方法是等效的,不仅仅是实验上的,而是数学上的。
2nc8po8w3#
我在你的数字中看到的一件事是数字是“0111 1111”+“0000 0101”都是正数,因为左边的第一个数字是0,但在第二个例子中,第一个数字是“1111 1111”,这意味着它是负数,第二个数字是“0000 0101”,这也意味着它是正数!记住:OF(溢出标志),当要设置时,两个数字具有相同的符号。在第二个数字中,由于两个数字的符号不同,OF = 0;