在Kip Irvine的书中,他谈到了设置溢出标志的机制,他写道:
CPU使用一种有趣的机制来确定加法或减法运算后Over fl ow fl ag的状态。 Carry fl ag与结果的高位进行异或运算。结果值放在Over fl ow fl ag。
我写了一个简单的程序,显示在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
为什么第二个例子中设置的溢出标志不是满足的条件语句ie;进位标志= 1,高位= 0?
答案 0 :(得分:7)
在第二个示例255 + 5
中未设置溢出标志的原因是因为它涉及有符号算术。您正在添加-1 + 5
,它给出了4.没有溢出:结果是正确的。正如@Jester评论的那样,你的书中一定有错误。
我的8086书中提到了溢出标志:
如果从第6位到第7位(内部进位)有内部进位,则会置位 标志位)并且没有外部携带。它也将在何时设置 从第6位到第7位没有内部进位,并且有一个 外部携带。
修改强>
该段继续:
对于具有技术意识的读者,溢出标志设置为 对第7位(符号位)的进位和进位进行异或。
在第二个例子中,执行1(到进位标志),并且因为所有位都已设置,所以在内部加法期间必须有内部进位,即使结果b7为0。 / p>
答案 1 :(得分:4)
你可以制作一个简单的程序来检查逻辑对3位加法/减法的作用。
#include <stdio.h>
int main ( void )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
unsigned int rd;
unsigned int re;
unsigned int cy;
unsigned int ov;
unsigned int ovx;
unsigned int ovy;
int sa;
int sb;
int sc;
int sd;
for(ra=0;ra<8;ra++)
{
for(rb=0;rb<8;rb++)
{
printf("%u%u%u",(ra>>2)&1,(ra>>1)&1,(ra>>0)&1);
printf(" + ");
printf("%u%u%u",(rb>>2)&1,(rb>>1)&1,(rb>>0)&1);
printf(" :");
if(ra&4) sa=(ra|((-1)<<3)); else sa=ra;
if(rb&4) sb=(rb|((-1)<<3)); else sb=rb;
sc = sa + sb;
//printf("%u(%2d) + %u(%2d)",ra,sa,rb,sb);
printf("%2d + %2d = %2d",sa,sb,sc);
printf(" :");
rc=rb;
printf("%u%u%u",(ra>>2)&1,(ra>>1)&1,(ra>>0)&1);
printf(" + ");
printf("%u%u%u",(rc>>2)&1,(rc>>1)&1,(rc>>0)&1);
printf(" + 0 = ");
rd=ra+rc+0;
if(rd&4) sd=(rd|((-1)<<3)); else sd=rd;
re=(ra&3)+(rc&3)+0;
ov=0;
if((ra&4)==(rc&4)) ov = ((rd>>3)&1) ^ ((rd>>2)&1);
ovy=0;
if((ra&4)==(rc&4)) if((rd&4) != (ra&4)) ovy=1;
ovx = ((rd>>3)&1) ^ ((re>>2)&1);
printf("%u%u%u",(rd>>2)&1,(rd>>1)&1,(rd>>0)&1);
printf(" C %u O %u %u %u ",(rd>>3)&1,ov,ovx,ovy);
if(sc>3) printf("X");
if(sc<(-4)) printf("X");
printf("\n");
}
}
for(ra=0;ra<8;ra++)
{
for(rb=0;rb<8;rb++)
{
printf("%u%u%u",(ra>>2)&1,(ra>>1)&1,(ra>>0)&1);
printf(" - ");
printf("%u%u%u",(rb>>2)&1,(rb>>1)&1,(rb>>0)&1);
printf(" :");
if(ra&4) sa=(ra|((-1)<<3)); else sa=ra;
if(rb&4) sb=(rb|((-1)<<3)); else sb=rb;
sc = sa - sb;
//printf("%u(%2d) - %u(%2d)",ra,sa,rb,sb);
printf("%2d - %2d = %2d",sa,sb,sc);
printf(" : ");
rc=(~rb)&7;
printf("%u%u%u",(ra>>2)&1,(ra>>1)&1,(ra>>0)&1);
printf(" + ");
printf("%u%u%u",(rc>>2)&1,(rc>>1)&1,(rc>>0)&1);
printf(" + 1 = ");
rd=ra+rc+1;
if(rd&4) sd=(rd|((-1)<<3)); else sd=rd;
re=(ra&3)+(rc&3)+1;
ov=0;
if((ra&4)==(rc&4)) ov = ((rd>>3)&1) ^ ((rd>>2)&1);
ovx = ((rd>>3)&1) ^ ((re>>2)&1);
ovy=0;
if((ra&4)==(rc&4)) if((rd&4) != (ra&4)) ovy=1;
printf("%u%u%u",(rd>>2)&1,(rd>>1)&1,(rd>>0)&1);
printf(" C %u O %u %u %u ",(rd>>3)&1,ov,ovx,ovy);
sc = sa - sb;
if(sc>3) printf("X");
if(sc<(-4)) printf("X");
printf("\n");
}
}
}
给
000 + 000 : 0 + 0 = 0 :000 + 000 + 0 = 000 C 0 O 0 0 0
000 + 001 : 0 + 1 = 1 :000 + 001 + 0 = 001 C 0 O 0 0 0
000 + 010 : 0 + 2 = 2 :000 + 010 + 0 = 010 C 0 O 0 0 0
000 + 011 : 0 + 3 = 3 :000 + 011 + 0 = 011 C 0 O 0 0 0
000 + 100 : 0 + -4 = -4 :000 + 100 + 0 = 100 C 0 O 0 0 0
000 + 101 : 0 + -3 = -3 :000 + 101 + 0 = 101 C 0 O 0 0 0
000 + 110 : 0 + -2 = -2 :000 + 110 + 0 = 110 C 0 O 0 0 0
000 + 111 : 0 + -1 = -1 :000 + 111 + 0 = 111 C 0 O 0 0 0
001 + 000 : 1 + 0 = 1 :001 + 000 + 0 = 001 C 0 O 0 0 0
001 + 001 : 1 + 1 = 2 :001 + 001 + 0 = 010 C 0 O 0 0 0
001 + 010 : 1 + 2 = 3 :001 + 010 + 0 = 011 C 0 O 0 0 0
001 + 011 : 1 + 3 = 4 :001 + 011 + 0 = 100 C 0 O 1 1 1 X
001 + 100 : 1 + -4 = -3 :001 + 100 + 0 = 101 C 0 O 0 0 0
001 + 101 : 1 + -3 = -2 :001 + 101 + 0 = 110 C 0 O 0 0 0
001 + 110 : 1 + -2 = -1 :001 + 110 + 0 = 111 C 0 O 0 0 0
001 + 111 : 1 + -1 = 0 :001 + 111 + 0 = 000 C 1 O 0 0 0
010 + 000 : 2 + 0 = 2 :010 + 000 + 0 = 010 C 0 O 0 0 0
010 + 001 : 2 + 1 = 3 :010 + 001 + 0 = 011 C 0 O 0 0 0
010 + 010 : 2 + 2 = 4 :010 + 010 + 0 = 100 C 0 O 1 1 1 X
010 + 011 : 2 + 3 = 5 :010 + 011 + 0 = 101 C 0 O 1 1 1 X
010 + 100 : 2 + -4 = -2 :010 + 100 + 0 = 110 C 0 O 0 0 0
010 + 101 : 2 + -3 = -1 :010 + 101 + 0 = 111 C 0 O 0 0 0
010 + 110 : 2 + -2 = 0 :010 + 110 + 0 = 000 C 1 O 0 0 0
010 + 111 : 2 + -1 = 1 :010 + 111 + 0 = 001 C 1 O 0 0 0
011 + 000 : 3 + 0 = 3 :011 + 000 + 0 = 011 C 0 O 0 0 0
011 + 001 : 3 + 1 = 4 :011 + 001 + 0 = 100 C 0 O 1 1 1 X
011 + 010 : 3 + 2 = 5 :011 + 010 + 0 = 101 C 0 O 1 1 1 X
011 + 011 : 3 + 3 = 6 :011 + 011 + 0 = 110 C 0 O 1 1 1 X
011 + 100 : 3 + -4 = -1 :011 + 100 + 0 = 111 C 0 O 0 0 0
011 + 101 : 3 + -3 = 0 :011 + 101 + 0 = 000 C 1 O 0 0 0
011 + 110 : 3 + -2 = 1 :011 + 110 + 0 = 001 C 1 O 0 0 0
011 + 111 : 3 + -1 = 2 :011 + 111 + 0 = 010 C 1 O 0 0 0
100 + 000 :-4 + 0 = -4 :100 + 000 + 0 = 100 C 0 O 0 0 0
100 + 001 :-4 + 1 = -3 :100 + 001 + 0 = 101 C 0 O 0 0 0
100 + 010 :-4 + 2 = -2 :100 + 010 + 0 = 110 C 0 O 0 0 0
100 + 011 :-4 + 3 = -1 :100 + 011 + 0 = 111 C 0 O 0 0 0
100 + 100 :-4 + -4 = -8 :100 + 100 + 0 = 000 C 1 O 1 1 1 X
100 + 101 :-4 + -3 = -7 :100 + 101 + 0 = 001 C 1 O 1 1 1 X
100 + 110 :-4 + -2 = -6 :100 + 110 + 0 = 010 C 1 O 1 1 1 X
100 + 111 :-4 + -1 = -5 :100 + 111 + 0 = 011 C 1 O 1 1 1 X
101 + 000 :-3 + 0 = -3 :101 + 000 + 0 = 101 C 0 O 0 0 0
101 + 001 :-3 + 1 = -2 :101 + 001 + 0 = 110 C 0 O 0 0 0
101 + 010 :-3 + 2 = -1 :101 + 010 + 0 = 111 C 0 O 0 0 0
101 + 011 :-3 + 3 = 0 :101 + 011 + 0 = 000 C 1 O 0 0 0
101 + 100 :-3 + -4 = -7 :101 + 100 + 0 = 001 C 1 O 1 1 1 X
101 + 101 :-3 + -3 = -6 :101 + 101 + 0 = 010 C 1 O 1 1 1 X
101 + 110 :-3 + -2 = -5 :101 + 110 + 0 = 011 C 1 O 1 1 1 X
101 + 111 :-3 + -1 = -4 :101 + 111 + 0 = 100 C 1 O 0 0 0
110 + 000 :-2 + 0 = -2 :110 + 000 + 0 = 110 C 0 O 0 0 0
110 + 001 :-2 + 1 = -1 :110 + 001 + 0 = 111 C 0 O 0 0 0
110 + 010 :-2 + 2 = 0 :110 + 010 + 0 = 000 C 1 O 0 0 0
110 + 011 :-2 + 3 = 1 :110 + 011 + 0 = 001 C 1 O 0 0 0
110 + 100 :-2 + -4 = -6 :110 + 100 + 0 = 010 C 1 O 1 1 1 X
110 + 101 :-2 + -3 = -5 :110 + 101 + 0 = 011 C 1 O 1 1 1 X
110 + 110 :-2 + -2 = -4 :110 + 110 + 0 = 100 C 1 O 0 0 0
110 + 111 :-2 + -1 = -3 :110 + 111 + 0 = 101 C 1 O 0 0 0
111 + 000 :-1 + 0 = -1 :111 + 000 + 0 = 111 C 0 O 0 0 0
111 + 001 :-1 + 1 = 0 :111 + 001 + 0 = 000 C 1 O 0 0 0
111 + 010 :-1 + 2 = 1 :111 + 010 + 0 = 001 C 1 O 0 0 0
111 + 011 :-1 + 3 = 2 :111 + 011 + 0 = 010 C 1 O 0 0 0
111 + 100 :-1 + -4 = -5 :111 + 100 + 0 = 011 C 1 O 1 1 1 X
111 + 101 :-1 + -3 = -4 :111 + 101 + 0 = 100 C 1 O 0 0 0
111 + 110 :-1 + -2 = -3 :111 + 110 + 0 = 101 C 1 O 0 0 0
111 + 111 :-1 + -1 = -2 :111 + 111 + 0 = 110 C 1 O 0 0 0
000 - 000 : 0 - 0 = 0 : 000 + 111 + 1 = 000 C 1 O 0 0 0
000 - 001 : 0 - 1 = -1 : 000 + 110 + 1 = 111 C 0 O 0 0 0
000 - 010 : 0 - 2 = -2 : 000 + 101 + 1 = 110 C 0 O 0 0 0
000 - 011 : 0 - 3 = -3 : 000 + 100 + 1 = 101 C 0 O 0 0 0
000 - 100 : 0 - -4 = 4 : 000 + 011 + 1 = 100 C 0 O 1 1 1 X
000 - 101 : 0 - -3 = 3 : 000 + 010 + 1 = 011 C 0 O 0 0 0
000 - 110 : 0 - -2 = 2 : 000 + 001 + 1 = 010 C 0 O 0 0 0
000 - 111 : 0 - -1 = 1 : 000 + 000 + 1 = 001 C 0 O 0 0 0
001 - 000 : 1 - 0 = 1 : 001 + 111 + 1 = 001 C 1 O 0 0 0
001 - 001 : 1 - 1 = 0 : 001 + 110 + 1 = 000 C 1 O 0 0 0
001 - 010 : 1 - 2 = -1 : 001 + 101 + 1 = 111 C 0 O 0 0 0
001 - 011 : 1 - 3 = -2 : 001 + 100 + 1 = 110 C 0 O 0 0 0
001 - 100 : 1 - -4 = 5 : 001 + 011 + 1 = 101 C 0 O 1 1 1 X
001 - 101 : 1 - -3 = 4 : 001 + 010 + 1 = 100 C 0 O 1 1 1 X
001 - 110 : 1 - -2 = 3 : 001 + 001 + 1 = 011 C 0 O 0 0 0
001 - 111 : 1 - -1 = 2 : 001 + 000 + 1 = 010 C 0 O 0 0 0
010 - 000 : 2 - 0 = 2 : 010 + 111 + 1 = 010 C 1 O 0 0 0
010 - 001 : 2 - 1 = 1 : 010 + 110 + 1 = 001 C 1 O 0 0 0
010 - 010 : 2 - 2 = 0 : 010 + 101 + 1 = 000 C 1 O 0 0 0
010 - 011 : 2 - 3 = -1 : 010 + 100 + 1 = 111 C 0 O 0 0 0
010 - 100 : 2 - -4 = 6 : 010 + 011 + 1 = 110 C 0 O 1 1 1 X
010 - 101 : 2 - -3 = 5 : 010 + 010 + 1 = 101 C 0 O 1 1 1 X
010 - 110 : 2 - -2 = 4 : 010 + 001 + 1 = 100 C 0 O 1 1 1 X
010 - 111 : 2 - -1 = 3 : 010 + 000 + 1 = 011 C 0 O 0 0 0
011 - 000 : 3 - 0 = 3 : 011 + 111 + 1 = 011 C 1 O 0 0 0
011 - 001 : 3 - 1 = 2 : 011 + 110 + 1 = 010 C 1 O 0 0 0
011 - 010 : 3 - 2 = 1 : 011 + 101 + 1 = 001 C 1 O 0 0 0
011 - 011 : 3 - 3 = 0 : 011 + 100 + 1 = 000 C 1 O 0 0 0
011 - 100 : 3 - -4 = 7 : 011 + 011 + 1 = 111 C 0 O 1 1 1 X
011 - 101 : 3 - -3 = 6 : 011 + 010 + 1 = 110 C 0 O 1 1 1 X
011 - 110 : 3 - -2 = 5 : 011 + 001 + 1 = 101 C 0 O 1 1 1 X
011 - 111 : 3 - -1 = 4 : 011 + 000 + 1 = 100 C 0 O 1 1 1 X
100 - 000 :-4 - 0 = -4 : 100 + 111 + 1 = 100 C 1 O 0 0 0
100 - 001 :-4 - 1 = -5 : 100 + 110 + 1 = 011 C 1 O 1 1 1 X
100 - 010 :-4 - 2 = -6 : 100 + 101 + 1 = 010 C 1 O 1 1 1 X
100 - 011 :-4 - 3 = -7 : 100 + 100 + 1 = 001 C 1 O 1 1 1 X
100 - 100 :-4 - -4 = 0 : 100 + 011 + 1 = 000 C 1 O 0 0 0
100 - 101 :-4 - -3 = -1 : 100 + 010 + 1 = 111 C 0 O 0 0 0
100 - 110 :-4 - -2 = -2 : 100 + 001 + 1 = 110 C 0 O 0 0 0
100 - 111 :-4 - -1 = -3 : 100 + 000 + 1 = 101 C 0 O 0 0 0
101 - 000 :-3 - 0 = -3 : 101 + 111 + 1 = 101 C 1 O 0 0 0
101 - 001 :-3 - 1 = -4 : 101 + 110 + 1 = 100 C 1 O 0 0 0
101 - 010 :-3 - 2 = -5 : 101 + 101 + 1 = 011 C 1 O 1 1 1 X
101 - 011 :-3 - 3 = -6 : 101 + 100 + 1 = 010 C 1 O 1 1 1 X
101 - 100 :-3 - -4 = 1 : 101 + 011 + 1 = 001 C 1 O 0 0 0
101 - 101 :-3 - -3 = 0 : 101 + 010 + 1 = 000 C 1 O 0 0 0
101 - 110 :-3 - -2 = -1 : 101 + 001 + 1 = 111 C 0 O 0 0 0
101 - 111 :-3 - -1 = -2 : 101 + 000 + 1 = 110 C 0 O 0 0 0
110 - 000 :-2 - 0 = -2 : 110 + 111 + 1 = 110 C 1 O 0 0 0
110 - 001 :-2 - 1 = -3 : 110 + 110 + 1 = 101 C 1 O 0 0 0
110 - 010 :-2 - 2 = -4 : 110 + 101 + 1 = 100 C 1 O 0 0 0
110 - 011 :-2 - 3 = -5 : 110 + 100 + 1 = 011 C 1 O 1 1 1 X
110 - 100 :-2 - -4 = 2 : 110 + 011 + 1 = 010 C 1 O 0 0 0
110 - 101 :-2 - -3 = 1 : 110 + 010 + 1 = 001 C 1 O 0 0 0
110 - 110 :-2 - -2 = 0 : 110 + 001 + 1 = 000 C 1 O 0 0 0
110 - 111 :-2 - -1 = -1 : 110 + 000 + 1 = 111 C 0 O 0 0 0
111 - 000 :-1 - 0 = -1 : 111 + 111 + 1 = 111 C 1 O 0 0 0
111 - 001 :-1 - 1 = -2 : 111 + 110 + 1 = 110 C 1 O 0 0 0
111 - 010 :-1 - 2 = -3 : 111 + 101 + 1 = 101 C 1 O 0 0 0
111 - 011 :-1 - 3 = -4 : 111 + 100 + 1 = 100 C 1 O 0 0 0
111 - 100 :-1 - -4 = 3 : 111 + 011 + 1 = 011 C 1 O 0 0 0
111 - 101 :-1 - -3 = 2 : 111 + 010 + 1 = 010 C 1 O 0 0 0
111 - 110 :-1 - -2 = 1 : 111 + 001 + 1 = 001 C 1 O 0 0 0
111 - 111 :-1 - -1 = 0 : 111 + 000 + 1 = 000 C 1 O 0 0 0
所以为了添加你会有这样的一个(根据定义签名的溢出标志是当你将这些位解释为签名时)
011 + 001 : 3 + 1 = 4 :011 + 001 + 0 = 100 C 0 O 1 1 1 X
所以1 + 3(001 + 011)=位模式100,它在三位二进制补码世界中具有值-4所以1 + 3 = -4这是错误的所以签名溢出,我们不能代表一个+ 4有三位。在x86上,这相当于增加了127 + 1(0x7F + 0x01)的8位。基本上所有正数的组合导致128(或更大)126 + 2,125 + 3 124 + 4等等。都有这个问题。
010 + 010 : 2 + 2 = 4 :010 + 010 + 0 = 100 C 0 O 1 1 1 X
我做了加法和减法。减法在逻辑上来自二进制补码概念反转并加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),那么会混淆进位的概念,可以通过借位或减法进行加法。
我计算了溢出标志三种不同的(真的?)方式。
ov=0;
if((ra&4)==(rc&4)) ov = ((rd>>3)&1) ^ ((rd>>2)&1);
ovx = ((rd>>3)&1) ^ ((re>>2)&1);
ovy=0;
if((ra&4)==(rc&4)) if((rd&4) != (ra&4)) ovy=1;
ov就像你正在阅读的文本中一样,如果加法器中的符号相同,那么溢出就会与结果的msbit一致。
ovx是溢出进位的定义,与执行msbit相比
和ovy是一个可以使用的快捷方式,如果你想弄清楚但是寄存器没有N + 1位(你怎么能用一种你看不到执行的语言中的32位变量来计算溢出?我在代码中展示的方法很多,但只是检查msbits的工作原理。)
然后如果结果不符合可用的位数,那么最后的X也是溢出的定义,然后溢出。对于无符号(进位)和有符号(溢出)溢出,则为true。因为这是关于溢出然后这是关于有符号的数字,所以对于我的三位系统,你只能得到-4到+3以上+3或小于-4的任何东西,并且打印输出结尾的X表明,所以这是在这个简化的例子中显示溢出的第四种方式。
上面的输出再次是通用逻辑如何做到这一点,然后你有处理器族的细微差别和进位标志,一些处理器将进位反转为使其成为借位而有些则在进行减法时不进行。真正的实际逻辑会将一堆3个输入(两个操作数和进位)两个输出(结果和执行)加法器级联在一起,尽管在HDL语言中你可以使用加号运算符并绕过它(并且在那些语言中也需要一个这些快捷方式没有检查进位与执行)
如果你使用booloean方程,你应该能够发现计算溢出的三种方法是等价的,不仅仅是在这里进行实验,而是数学上。
答案 2 :(得分:0)
我在你的数字中看到的一件事是数字是“0111 1111”+ “0000 0101”都是正数,因为左边的第一个数字是0但是在第二个例子中第一个数字是“1111 1111”,这意味着它是负数,第二个数字是“0000 0101”,这也意味着它是正数!请记住:OF(溢出标志)何时设置,两个数字具有相同的符号。在第二个因为数字的2个差异符号OF = 0;