无符号数的上溢/下溢

发布于 2024-12-10 20:12:37 字数 484 浏览 0 评论 0原文

因此,如果无符号数的加法进位为 1,则发生溢出;如果减法的进位为 0,则发生下溢。但这在所有情况下都有效吗?

如果你打成5-0: 0101 -0000

= 0101 +(1111 + 1)

= 0101 +0000

= 0101...这里进位为零,而不是 1。如何解释这种情况?有不同的方法吗?

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

---编辑

感谢 Amadan。不过我理解那部分。我的问题是零似乎是一个特例。它似乎不遵循正常数字的做法:在上面的示例中,没有 1 的进位。

我目前正在使用 ALU 进行电路设计,并尝试实现溢出检测,当出现这种情况时不遵循其他人所做的事情。

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

So, if you have a carry out of 1 on addition with unsigned numbers, you have overflowed, and if you have a carry out of 0 with subtraction, you have underflowed. Does this work in every case, though?

If you do 5-0:
0101
-0000

=
0101
+(1111 + 1)

=
0101
+0000

= 0101... there is a carry out of zero here, instead of 1. How does one account for this case? Is there a different way to do it?

(using MIPS architecture, or anything else)

---Edit

Thanks Amadan. I understand that part, though. My problem is just that zero seems to be a special case. It does not seem to follow what normal numbers do: in my example above, there is no carry out of 1.

I'm doing circuit design working with an ALU at the moment and trying to implement the overflow detection, when this one case came up that doesn't follow what the others do.

We are assuming that with subtraction, the second operand is preinverted (twos complement) before going into the ALU (then added to the first operand). So, whenever the "invert_b" for subtraction is set to 1, b is inverted and we assume that the case we are checking for is subtraction, which should have a carry out of 1.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光磨忆 2024-12-17 20:12:37

我相信 msbit 进位位本身涵盖了未签名的情况,对于有符号的情况,您可以查看 msbit 的进位和进位是否不同。

5-0 不会溢出,因为结果适合可用位数。 的 4 位系统一样

与 15-1 不会溢出有符号数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 相减不是您所说的无符号溢出

同样 -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

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

无论有多少位,这些奇怪的数字都是零和一个一,其余的都是零,0和8,或者对于4位系统来说是-8。

使用 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 事物,并且在尝试每种可能的组合时找不到与进位与进位方法不匹配的情况在头对头分析中。

如果我的答案太过分了,我不介意在开头将其剪掉,它显示 5 - 0 有一个 1 作为 1 的进位,这对于减法来说不是溢出。答案很长,因为很难理解有符号与无符号以及加法器在逻辑上的一般工作原理。加法器不知道或不关心有符号或无符号,它确实关心加法与减法,通过减法可以反转第二个操作数,反转进位到 lsbit 以及进位出 msbit(考虑加法,带进位的加法) 、 sub 和带有进位的 sub )。有符号与无符号的关系取决于它本身(二进制补码的美妙之处)。将上述内容简化为仅无符号的讨论,使其简单一半以上,因为有符号溢出对于不经意的观察者来说并不明显(如无符号溢出)。

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

I believe the msbit carry out bit on its own covers unsigned and for signed you look to see if the carry in to the msbit and the carry out differ.

5-0 does not overflow because the result fits in the number of bits available. The same way that 15-1 does not overflow a 4 bit system for signed numbers

5 - 0 = 0101 + 1111 + 1

    1
 0101
+1111
=====

11111
 0101
+1111
=====
 0101

so 5 - 0 certainly carries out a 1, since this is a subtract that is not an overflow

15 - 1 = 1111 + ~1 with the carry in set

    1
 1111
 1110
 ====

11111
 1111
 1110
 ====
 1110

a subtract with a 1 out is not an unsigned overflow as you stated

Likewise -1 - 1 = 1111 + ~1 with the carry in bit set

11111
 1111
 1110
 ====
 1110

the carry in to the last bit is a 1 the carry out is a 1 they match, no signed overflow.

8 + 8 = 1000 + 1000 with the carry in clear

    0
 1000
+1000
=====

10000
 1000
+1000
=====
 0000

unsigned overflow.

hmmm 4 + 4

    0
 0100
+0100
=====

01000
 0100
+0100
=====
 1000

unsigned add the carry out is 0 this is not an unsigned overflow. but this is a signed overflow because the carry in to the msbit and carry out differ. +4 + +4 = +8, in a 4 bit signed system you cannot represent +8, so the signed overflow is accurate.

No matter how many bits the weird numbers are all zeros and a one and the rest zeros, 0 and 8 or -8 for a 4 bit system.

Make a chart either with 2, 3, or 4 bit numbers all combinations and manually look through all of them to see that they make sense. whatever you find will scale no matter how many bits wide, a 100 bit adder works like a 10 bit adder...

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

The code that generated the above

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);
    }
}

Now your question was talking about unsigned numbers yes? so you may not care about the V bit nor the right half, the signed half.

Here is some HDL/RTL for a small 16 bit processor I implemented:

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];
}

I have/had seen the msbit thing for signed overflow in other logic and couldnt find a case where it didnt match the carry in vs carry out method when trying every possible combination in a head to head analysis.

If I went overboard with the answer I dont mind clipping it off at the beginning where it shows that 5 - 0 has a 1 as a carry out of 1, which for a subtract is not an overflow. The long answer because it can be hard to wrap your head around signed vs unsigned and how the adder works in logic in general. The adder does not know or care about signed or unsigned, it does care about add vs subtract, with subtract you invert the second operand, invert the carry in to the lsbit and the carry out of the msbit (think about add, add with carry, sub and sub with carry). The signed vs unsigned takes care if itself (the beauty of twos complement). Reducing the above to an unsigned only discussion makes it more than half as simple as the signed overflow is not (as) obvious (as unsigned overflow) to the casual observer.

I sure hope I cut and pasted the debugged HDL , will get a lot of responses/corrections if I didnt...I spent a few days convincing myself of all of the above and comparing to the results of other processors I had access to, etc. Hopefully this saves you a few days.

梦萦几度 2024-12-17 20:12:37

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

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

如果你用二进制补码加法,那么就像你说的: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

Not an expert, but the whole statement on subtraction seems wrong.

You can implement subtraction in two basic ways: directly as subtraction, or as addition of two's complement.

If you go with two's complement addition, then it is as you say: carry of 1 is underflow.

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

If you subtract directly, then 1 carry is underflow:

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
执着的年纪 2024-12-17 20:12:37

可能还有其他等效的方法来设计加法器的溢出检测单元,但最常见的是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(符号扩展),我们可以再次导出等价性。那么当结果的 MSB 为 1 时,我们就是负数。当我们原始模型中的进位(新模型中的进位)为 0 时,就会发生这种情况,因为只有这样,新模型中结果的 MSB 才会保持为 1您

的示例也不例外:0101 + 1111 + 1 = 0101,进位为 1,因此不会下溢,因为结果为正。

There may be other equivalent ways of designing overflow detection units for adders, but the most common is Cin XOR Cout. For example, see the end of lecture 4 http://cs.nyu.edu/~gottlieb/courses/2007-08-fall/arch/class-notes.html

It simply checks if the numbers being added (if something is inverted for 2's complement or not doesn't matter, we look at these values afterwards) carry in to the last digit's calculation but not into the digit beyond the supported bit-size, or the opposite.

This makes sense because if they carry in and not out the result must be negative (since the MSB must be 1) but the operands must be positive (since if they were negative there would be carry out). This is the definition of overflow, since two positives cannot sum to a negative.

This is a signed model however, I'm not sure if that's what you're looking for since you mentioned unsigned. If that's the case, then you're right, the simple addition model has overflow when carry out is 1 (this is equivalent to the above if you consider the addition to have an extra 0 for each operands' MSB, then the carry out will always be 0 and there's overflow iff the carry in is 1. The carry in in this case is the carry out in our model).

Subtraction results in underflow if the value is negative. We can again derive an equivalence if we consider the positive operand to have an appended MSB of 0 and the negative operand one of 1 (sign extension). Then we are negative when the MSB of the result is 1. This happens iff the carry out in our original model (the carry in in the new model) is 0, since only then will the MSB of the result in the new model remain 1.

You example is no exception: 0101 + 1111 + 1 = 0101 with a carry out of 1, and therefore no underflow, since the result is positive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文