进行二进制减法时如何检测溢出

How is overflow detected when doing binary subtraction

假设我们有 3 位可以玩。我将在 2 的补码中表示正负 3:

+3 = 0b011
-3 = 0b101

在进行 加法 时,当像这样发生溢出时,你总是有一个悬空位 (-3) + (+3):

  1 0 1
+ 0 1 1
  -----
1 0 0 0

但是减法 (-3) - (+3)呢?

  1 0 1
- 0 1 1
  -----
  0 1 0

0b0102,这不是我们预期的 -6 的正确结果。有溢出 甚至没有生成额外的位,那么如何检测到溢出?

我想解决这个问题的正确方法是先对输入进行签名扩展?

可以通过(进位到 MSB)XOR(进位到 MSB)创建溢出标志。

如何在逻辑中检测有符号溢出

(-3) - (+3) = (-3) + (-3) = (-3) + (~3) + 1

用小学数学和补码

    1
  101
+ 100
======

完成

 1011
  101
+ 100
======
  010

当msbit的进位和出位不同时,会发生SIGNED溢出。我们在这里看到的。另一种说法是,使用反转操作数 B,如果操作数的 msbits 相同且结果不相同,则它是有符号溢出。

请注意,msbit 的进位不是借位,因此 1 表示没有借位,0 表示有借位。一些处理器架构反转进位并称其为借位,而另一些则没有。这两种解决方案都有效,您只需要让比较逻辑匹配并用借位减去即可。

对于小学数学,我们可以继续添加列。如果我们可以简单地在寄存器中增加一位,我们就可以获得加法和减法的完整答案。对于乘法,我们需要两倍的位数。对于 3 位操作数,我们需要 6 位结果才不会溢出。作为补充,理想情况下,您需要一个 6 位分子作为一个三位除数。并非所有指令集都提供此功能。是的,对于有符号运算,您需要对扩展符号进行签名,而对于无符号运算,您需要零填充,因此有符号乘法和无符号乘法之间的区别。对于 3 位结果(乘法),signed/unsigned 无关紧要(像小学一样在纸和铅笔上做,这应该是显而易见的)。同样,对于 3 位加法或减法,无需知道无符号与有符号。

用加法和减法虽然正常的解法是加进位,减法借位。 -3 - +3 给出 -6 我们不能用 3 位表示,我们需要 4 但如果我们假设 3 位寄存器那么我们唯一能做的就是 6。这意味着我们真的在尝试做 111101 - 000011.

     1011
   111101
  +111100
    ======
      010

如果我们在视觉上这样做并将其切成两半

     1   011
   111   101
  +111   100
  ============
         010

我们可以使用第二条指令完成减法(借位减法)

  1111 
   111 
  +111 
  =====
   111
   

111010为-6,没有溢出。关键是让下半部分的进位进入上半部分的进位。

如果体系结构在减法的途中反转进位位,那么它需要在途中将借位反转为带借位的减法,否则如果它没有将其反转出 sub 则不要将其转换为 sbb。 Add 和 adc (add with carry) 的工作方式相同,只是没有反转,进位位作为 msbit 的进位进入 adc。

乘法并不那么简单,它不是一个位的东西,你需要整个寄存器的位,所以一些架构会给你 3 位乘以 3 位等于 6 位有符号和无符号乘法指令。但是对于加法和减法没有真正的需要,使用进位位和包含其余位的 memory/registers 的附加指令。你可以 add/subtract 和你 memory/registers 一样宽,1000 位加 1000 位很容易,它只是一个加法和一组连续的 adc。