无符号数的溢出/下溢

时间:2011-10-21 01:34:04

标签: numbers overflow mips unsigned underflow

所以,如果你在无符号数字上加1,你就已经溢出了,如果你有一个带有减法的0,那么你已经下溢了。这是否适用于所有情况?

如果你做5-0: 0101 -0000

= 0101 +(1111 + 1)

= 0101 0000

= 0101 ...这里有一个零,而不是1.如何解释这个案例?有没有不同的方法呢?

(使用MIPS架构或其他任何东西)

---修改

谢谢Amadan。不过,我理解这一部分。我的问题只是零似乎是一个特例。它似乎不遵循正常数字所做的:在上面的例子中,没有执行1。

我正在进行电路设计,目前正在与ALU合作并尝试实施溢出检测,当这一个案例出现时并不遵循其他人所做的那样。

我们假设通过减法,第二个操作数在进入ALU之前被预转换(二进制补码)(然后添加到第一个操作数)。因此,每当减法的“invert_b”设置为1时,b被反转,我们假设我们检查的情况是减法,其执行时应为1。

3 个答案:

答案 0 :(得分:5)

我相信msbit在其自己的位上执行无符号覆盖,并且对于签名,您可以查看进入msbit和进位是否不同。

5-0不会溢出,因为结果符合可用的位数。与15-1不会溢出4位系统的有符号数字

的方式相同

5 - 0 = 0101 + 1111 + 1

    1
 0101
+1111
=====

11111
 0101
+1111
=====
 0101

所以5 - 0肯定会执行1,因为这是一个不是溢出的减法

15 - 1 = 1111 + ~1,进位设置

    1
 1111
 1110
 ====

11111
 1111
 1110
 ====
 1110

带有1 out的减法不是你所说的无符号溢出

同样-1 - 1 = 1111 + ~1,进位位设置

11111
 1111
 1110
 ====
 1110

进位到最后一位是1,进位是1匹配,没有符号溢出。

8 + 8 = 1000 + 1000,进位清晰

    0
 1000
+1000
=====

10000
 1000
+1000
=====
 0000

无符号溢出。

嗯4 + 4

    0
 0100
+0100
=====

01000
 0100
+0100
=====
 1000

unsigned add执行是0这不是无符号溢出。但这是一个带符号的溢出,因为进入msbit并执行不同。 +4 + +4 = +8,在4位有符号系统中,你不能代表+8,所以有符号的溢出是准确的。

无论有多少位,奇数都是0和1,其余为零,0和8或-8用于4位系统。

使用2,3或4位数字组成一个图表所有组合,并手动查看所有组合以查看它们是否有意义。无论你发现什么,无论多少位宽,100位加法器就像10位加法器一样......

add           C V  unsigned    signed
00 + 00 = 000 0 0  0 + 0 = 0   0 +  0 =  0
00 + 01 = 001 0 0  0 + 1 = 1   0 +  1 =  1
00 + 10 = 010 0 0  0 + 2 = 2   0 + -2 = -2
00 + 11 = 011 0 0  0 + 3 = 3   0 + -1 = -1
01 + 00 = 001 0 0  1 + 0 = 1   1 +  0 =  1
01 + 01 = 010 0 1  1 + 1 = 2   1 +  1 =  2  signed cannot represent a +2
01 + 10 = 011 0 0  1 + 2 = 3   1 + -2 = -1
01 + 11 = 100 1 0  1 + 3 = 4   1 + -1 =  0  unsigned cannot represent +4
10 + 00 = 010 0 0  2 + 0 = 2  -2 +  0 = -2 
10 + 01 = 011 0 0  2 + 1 = 3  -2 +  1 = -1
10 + 10 = 100 1 1  2 + 2 = 4  -2 + -2 = -4 neither +4 nor -4 will fit in 2 bits
10 + 11 = 101 1 1  2 + 3 = 5  -2 + -1 = -3 neither +4 nor -3 will fit in 2 bits
11 + 00 = 011 0 0  3 + 0 = 3  -1 +  0 = -1 
11 + 01 = 100 1 0  3 + 1 = 4  -1 +  1 = -2 +4 does not fit in 2 bits
11 + 10 = 101 1 1  3 + 2 = 5  -1 + -2 = -3 neither +5 nor -3 fit in 2 bits
11 + 11 = 110 1 0  3 + 3 = 6  -1 + -1 = -2 6 does not fit in 2 bits
sub
00 - 00 = 100 0 0
00 - 01 = 011 1 0  0 - 1 = -1   -1 does not fit in an unsigned result
00 - 10 = 010 1 1  0 - 2 = -2  0 - -2 = +2  
00 - 11 = 001 1 0  0 - 3 = -3
01 - 00 = 101 0 0
01 - 01 = 100 0 0
01 - 10 = 011 1 1  1 - 2 = -1  1 - -2 =  3
01 - 11 = 010 1 1  1 - 3 = -2  1 - -1 =  2
10 - 00 = 110 0 0  
10 - 01 = 101 0 1             -2 -  1 = -3
10 - 10 = 100 0 0
10 - 11 = 011 1 0  2 - 3 = -1
11 - 00 = 111 0 0
11 - 01 = 110 0 0
11 - 10 = 101 0 0
11 - 11 = 100 0 0

生成上述代码的代码

printf("add\n");
for(ra=0;ra<4;ra++)
{
    for(rb=0;rb<4;rb++)
    {
        rd=(ra&1)+(rb&1);
        rc=ra+rb;
        rd=(rd>>1)&1;
        re=(rc>>2)&1;
        if(re) c=1; else c=0;
        if(rd!=re) v=1; else v=0;

        if(ra&2) printf("1"); else printf("0");
        if(ra&1) printf("1"); else printf("0");
        printf(" + ");
        if(rb&2) printf("1"); else printf("0");
        if(rb&1) printf("1"); else printf("0");
        printf(" = ");
        if(rc&4) printf("1"); else printf("0");
        if(rc&2) printf("1"); else printf("0");
        if(rc&1) printf("1"); else printf("0");
        printf(" %u %u\n",c,v);
    }
}
printf("sub\n");
for(ra=0;ra<4;ra++)
{
    for(rb=0;rb<4;rb++)
    {
        rd=(ra&1)+((~rb)&1)+1;
        rc=ra+((~rb)&3)+1;
        rd=(rd>>1)&1;
        re=(rc>>2)&1;
        if(re) c=0; else c=1;
        if(rd!=re) v=1; else v=0;

        if(ra&2) printf("1"); else printf("0");
        if(ra&1) printf("1"); else printf("0");
        printf(" - ");
        if(rb&2) printf("1"); else printf("0");
        if(rb&1) printf("1"); else printf("0");
        printf(" = ");
        if(rc&4) printf("1"); else printf("0");
        if(rc&2) printf("1"); else printf("0");
        if(rc&1) printf("1"); else printf("0");
        printf(" %u %u\n",c,v);
    }
}

现在你的问题是谈论无符号数字是吗?所以你可能不关心V位,也不关心右半边,签名的一半。

这是我实现的小型16位处理器的一些HDL / RTL:

case 4b0000:
{
    //0000 add rd,rs
    op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
    op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
    op_res = op_a + op_b;
    reg[1].value[CBIT] <= op_res[16];
    reg[1].value[NBIT] <= op_res[15];

    if(op_res[16;0] == 16h0000)
    {
        reg[1].value[ZBIT] <= 1b1;
    }
    else
    {
        reg[1].value[ZBIT] <= 1b0;
    }
    if((op_a[15] == op_b[15]) && (op_res[15] != op_b[15] ) )
    {
        reg[1].value[VBIT] <= 1b1;
    }
    else
    {
            reg[1].value[VBIT] <= 1b0;
    }
    reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
case 4b0001:
{
    //0001 sub rd,rs
    op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
    op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
    op_res = op_a - op_b;
    reg[1].value[CBIT] <= (~op_res[16]);
    reg[1].value[NBIT] <= op_res[15];

    if(op_res[16;0] == 16h0000)
    {
        reg[1].value[ZBIT] <= 1b1;
    }
    else
    {
        reg[1].value[ZBIT] <= 1b0;
    }
    if((op_a[15] != op_b[15]) && (op_res[15] == op_b[15] ) )
    {
        reg[1].value[VBIT] <= 1b1;
    }
    else
    {
        reg[1].value[VBIT] <= 1b0;
    }
    reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}

我已经/已经看过其他逻辑中签名溢出的msbit事情,并且在头对头分析中尝试每种可能的组合时,无法找到与进入vs执行方法不匹配的情况。

如果我过分接受答案,我不介意在开头剪掉它,它显示5 - 0有一个1作为1的进位,这对于减法不是溢出。答案很长,因为很难将你的头围绕着签名与无符号以及加法器如何在逻辑中起作用。加法器不知道或不关心有符号或无符号,它关心加减vs,减去你反转第二个操作数,反转进入lsbit和执行msbit(想想添加,加载带,sub和sub with carry)。签名vs unsigned照顾自己(两个补充的美)。将上述内容简化为无符号唯一的讨论使得它变得超过一半,因为有符号溢出对于不经意的观察者来说并不明显(作为无符号溢出)。

我确定希望我剪切并粘贴已调试的HDL,如果我没有得到很多响应/更正......我花了几天时间说服自己以上所有内容并与我拥有的其他处理器的结果进行比较访问,等希望这可以节省你几天。

答案 1 :(得分:3)

不是专家,但关于减法的整个陈述似乎都是错误的。

您可以通过两种基本方式实现减法:直接作为减法,或者作为二进制补码的加法。

如果你选择两个补码,那就像你说的那样:1的进位是下溢。

5 - 6
= 0101 - 0110
= 0101 + (1001 + 1)
= 0101 + 1010
= (0)1111, carry 0 = underflow

如果直接减去,则1个随身携带是下溢:

0101 - 0110:
0     to    1 is 1
1     to (1)0 is 1, carry 1
1 + 1 to (1)1 is 1, carry 1
0 + 1 to (1)0 is 1, carry 1 = underflow

答案 2 :(得分:0)

为加法器设置溢出检测单元可能还有其他等效方法,但最常见的是Cin XOR Cout。例如,请参阅第4讲的结尾http://cs.nyu.edu/~gottlieb/courses/2007-08-fall/arch/class-notes.html

它只是检查是否添加的数字(如果某些内容被反转为2的补码与否无关紧要,我们之后会查看这些值)进入最后一位数的计算,但不会超出支持位的数字 - 大小,或相反。

这是有道理的,因为如果它们输入而不输出结果必须为负(因为MSB必须为1),但操作数必须为正(因为如果它们是负数则会执行)。这是溢出的定义,因为两个正数不能求和为负。

这是一个签名的模型但是,我不确定这是否是你所要求的,因为你提到了unsigned。如果是这种情况,那么你是对的,当执行为1时,简单的加法模型有溢出(如果你认为每个操作数'MSB的加法有一个额外的0,这相当于上面的那个,那么执行将是如果进位是1,则总是为0并且有溢出。在这种情况下的进位是我们模型中的进位。)

如果值为负,则减法会导致下溢。如果我们认为正操作数的附加MSB为0且负操作数1为1(符号扩展),我们可以再次推导出等价。当结果的MSB为1时,我们为负。如果我们原始模型中的执行(新模型中的进位)为0,则会发生这种情况,因为只有这样,新模型中结果的MSB才会保持为1

你的例子也不例外:0101 + 1111 + 1 = 0101,执行1,因此没有下溢,因为结果为正。