首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无符号数字中的上溢/下溢

无符号数字中的上溢/下溢
EN

Stack Overflow用户
提问于 2011-10-21 09:34:04
回答 3查看 22.7K关注 0票数 3

所以,如果你对无符号数字的加法进位为1,你就溢出了,如果你的减法进位为0,你就下溢了。然而,这在所有情况下都有效吗?

如果你做5-0: 0101 -0000

= 0101 +(1111 + 1)

= 0101 +0000

= 0101...这里有一个0的进位,而不是1。如何解释这种情况?有没有不同的方法呢?

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

-编辑

谢谢阿玛丹。不过,我理解这一点。我的问题是,零似乎是一个特例。它似乎不遵循正常数字的作用:在我上面的例子中,没有进位1。

我正在做电路设计,目前正在与ALU合作,并试图实现溢出检测,当这个案例出现时,并没有遵循其他案例的做法。

我们假设使用减法时,第二个操作数在进入算术逻辑单元(然后与第一个操作数相加)之前被预反转(二进制补码)。因此,只要减法的"invert_b“被设置为1,b就被反转,我们假设我们检查的情况是减法,它的进位应该是1。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-22 10:51:51

我相信msbit进位在它自己的封面上是无符号的,对于有符号的,你可以看看msbit的进位和进位是否不同。

5-0不会溢出,因为结果适合可用的位数。同样的方式,15-1不会使有符号数的4位系统溢出

5-0= 0101 + 1111 +1

代码语言:javascript
运行
复制
    1
 0101
+1111
=====

11111
 0101
+1111
=====
 0101

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

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

代码语言:javascript
运行
复制
    1
 1111
 1110
 ====

11111
 1111
 1110
 ====
 1110

带1输出的减法不是您所说的无符号溢出

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

代码语言:javascript
运行
复制
11111
 1111
 1110
 ====
 1110

进位到最后一位的进位是1,进位输出是他们匹配的1,没有带符号的溢出。

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

代码语言:javascript
运行
复制
    0
 1000
+1000
=====

10000
 1000
+1000
=====
 0000

无符号溢出。

hmmm 4+4

代码语言:javascript
运行
复制
    0
 0100
+0100
=====

01000
 0100
+0100
=====
 1000

unsigned add进位输出为0这不是无符号溢出。但是这是带符号溢出,因为进位到msbit和进位不同。+4 + +4 = +8,在4位有符号系统中,您不能表示+8,因此有符号溢出是准确的。

不管有多少位,奇怪的数字都是0和1,其余的0,对于4位系统,0和8或-8。

制作一个包含2、3或4位数字所有组合的图表,并手动查看所有组合,以查看它们是否有意义。无论你发现多少位宽的加法器,100位加法器就像10位加法器。

代码语言:javascript
运行
复制
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

生成上述代码的代码

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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的事情,但在尝试正面到正面分析中的每种可能组合时,找不到它与进位和进位方法不匹配的情况。

如果我在答案中走得太远,我不介意在开始时把它剪掉,因为它显示5-0有一个1作为1的进位,这对于减法来说不是溢出。答案很长,因为很难理解有符号的和无符号的,以及加法器在逻辑上是如何工作的。加法器不知道也不关心有符号或无符号,它关心的是加法和减法,用减法反转第二个操作数,反转进位到lsbit和msbit的进位(想想加法、进位加法、sub和sub进位)。有符号vs无符号需要注意自身(二进制的美是互补的)。将上面的讨论简化为unsigned only讨论使其简单一半以上,因为对于不经意的观察者来说,签名溢出并不明显(就像unsigned overflow一样)。

我当然希望我剪切并粘贴了调试过的HDL,如果我没有这样做,会得到很多响应/更正……我花了几天的时间说服自己相信上面的所有内容,并与我可以访问的其他处理器的结果进行比较,等等。希望这能节省你几天时间。

票数 6
EN

Stack Overflow用户

发布于 2011-10-21 09:45:17

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

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

如果你使用2的补码加法,那么正如你所说的:进位1是下溢。

代码语言:javascript
运行
复制
5 - 6
= 0101 - 0110
= 0101 + (1001 + 1)
= 0101 + 1010
= (0)1111, carry 0 = underflow

如果直接减法,则1进位是下溢:

代码语言:javascript
运行
复制
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
票数 3
EN

Stack Overflow用户

发布于 2011-10-21 10:43:54

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

它只是简单地检查被添加的数字(如果某些数字被倒置为2的补码或不重要,我们随后查看这些值)是否进入最后一个数字的计算,而不是进入超过支持的位大小的数字,或者相反。

这是有道理的,因为如果它们进位而不是输出,结果肯定是负的(因为MSB必须是1),但操作数必须是正的(因为如果它们是负的,就会有进位)。这是溢出的定义,因为两个正和不能等于负。

这是一个签名的模型,但是,我不确定这是否是你想要的,因为你提到了未签名。如果是这种情况,那么你是对的,当进位输出为1时,简单的加法模型有溢出(这相当于上面的情况,如果你认为加法对于每个操作数的MSB有额外的0,那么进位输出将始终是0,如果进位输入是1,那么就会有溢出。在这种情况下,进位输入就是我们模型中的进位)。

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

您的示例也不例外: 0101 + 1111 +1= 0101,进位为1,因此没有下溢,因为结果是肯定的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7844120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档