【问题标题】:How does an adder perform unsigned integer subtraction?加法器如何执行无符号整数减法?
【发布时间】:2011-11-08 15:42:35
【问题描述】:

假设AB 是有符号正整数,那么对于A-B,它是使用A+2B 的补码计算的。

例如,在 4 位二进制系统中,对于有符号整数,我们有 7-3=0111-0011=0111+1101=(1)0100, 括号中的 1 是进位位。根据有符号整数的溢出规则,我们知道没有溢出,因此结果是正确的。

但是,对于无符号整数,如果我们计算 7-3 会发生什么?如果我们使用我们上面提到的相同方式:

7-3=0111-0011=0111+1101=(1)0100

那么,根据无符号整数的溢出规则,由于进位,存在溢出。换句话说,0100 是错误的,因为存在溢出。但事实上,我们知道0100的结果是正确的。

如果我的分析是正确的,那么用adder进行无符号整数减法是不是错了?

【问题讨论】:

  • 对减法执行变化的解释。
  • @harold:没错,但仅限于用补码和加码实现的无符号减法。

标签: assembly unsigned subtraction


【解决方案1】:

您的分析不正确。实际上取决于 CPU ALU 单元。 :)

在第一种情况下,您使用的是 4 位整数,但您忘记了 4 位符号整数的最高位是 sign!因此,您只检查了进位和溢出状态,而不是 Negative 状态位。

通常二进制算术运算addsub对于有符号整数和无符号整数是相同的。只有受影响的标志不同。

其实你必须考虑:

  • 在有符号整数算术 CarryOverflowNegative 标志处。
  • 仅在无符号整数算术中携带标志。

详细说明:

补函数的挖掘是求反,所以​​要从正中得到相反的负数,从负中得到正数。我们可以通过两种方式进行二进制补码。让我们看看 3 号的两种情况。

  1. 在无符号算术是 compl (3) = b'0011' xor b'1111' + b'0001' = b'1101' + 进位(进位设置仅在 compl (0))
  2. 有符号的算术数符合 (3) = b'10000' - b'0011' = b'1101' 什么 等于 b'0000' - b'0011' = b'1101' + 进位(进位仅在 编译 (0))

在第一种情况下,函数补码也对进位位进行补码,我们还有对进位标志的第二种解释,名为borrow

在第二种情况下,一切都清楚了。如果补码有进位(溢出),则意味着我们需要另一个溢出来规范减法的结果。

【讨论】:

  • 这是一个很好的答案!人们经常忘记无符号算术只会引发进位标志!此外,我认为必须知道二进制补码可以解决包括符号位在内的所有问题!
  • 嗨,GJ,谢谢。在第一种情况下,7 和 3 都是有符号整数,因此 7-3=4 没有问题。但是,对于 7 和 3 是无符号整数的第二种情况,正如您所说,我们必须只考虑进位标志,那么 7-3=0111-0011=0111+1101=(1)0100 确实会生成一个进位位,这意味着计算确实溢出。换句话说,我们得到了正确的结果 4,但是,因为无符号运算有一个进位位,所以我们认为正确的结果 4 是错误的,因为进位位引起的溢出。这要怎么解释?
  • @user1035882:简短的回答是:因为在无符号补码处,进位标志也被补码。我已经添加了详细的解释。
  • @GJ.:非常感谢。你的回答对我来说有点困难:)我需要一些时间才能完全理解它。
【解决方案2】:

this answer 的相关问题中,C 中的示例代码显示了如何通过加法进行减法运算。该代码还设置了进位和溢出标志,并包含一个简单的“测试”,可以添加和减去一些数字并打印结果。数字是 8 位的。

编辑:正式证明可以使用 ADD 而不是 SUB 处理无符号整数 AND 发现无符号上溢/下溢,就像来自 SUB。

假设我们要计算 a - b,其中 ab 是 4 位无符号整数,我们希望通过加法执行减法并在 a 。

a - b = a + (-b)
由于我们在模 16 算术中运行,-b = 16-b。所以,
a - b = a + (-b) = a + (16 - b)

如果我们执行 a16-b 的常规无符号加法,则此加法的溢出条件(通常由 CPU 在其 carry 标志中指示)将是这个(回想一下,我们正在处理 4 -位整数):

a + (16 - b) > 15
让我们简化这个溢出条件:
a + 16 - b > 15
a + 16 > 15 + b
a + 1 > b
a > b - 1

现在让我们回想一下我们正在处理整数。因此上面可以改写为:
a >= b
这是在添加a(16)-b 后获得进位标志 = 1 的条件。如果不等式不成立,我们得到进位 = 0。

现在让我们回想一下,我们对减法 (a - b) 中的上溢/下溢感兴趣。该条件是 a 。

嗯,a >= ba 完全相反。

由此可知,a(16)-b 相加得到的 carry 标志是减法溢出的倒数,或者换句话说,是borrow 标志你可以通过使用适当的减法指令(例如 SUB)直接从 a 中减去 b 得到。

只需反转进位或以相反的方式处理它。

【讨论】:

  • @GJ.:使用加法器进行减法并没有错。我的代码显示了它。您可以检查测试输出以查看它。
  • 不正确,在低级别下这是正常的,所以在汇编中,但你必须知道规则!检查我的解释!
  • @GJ.:我已经用正式证明更新了我的答案,证明您可以在加法后使用进位标志来查看减法中是否存在上溢/下溢。您只需要在 ADD 之后反转进位标志即可在 SUB 之后获得您在其中得到的内容。
  • 没错,问题是为什么会这样!
  • @Alex,谢谢。你的答案比 GJ. 的更容易理解 :)
【解决方案3】:

这有点难以理解,但是……我有一些 VHDL 来做这件事。我有一个 CPU,其内存位置未签名,偏移值已签名。

architecture Behavioral of adder16 is
signal temp: std_logic_vector (16 downto 0);
begin
eval: process(vectA,vectB,temp)
begin
temp <=(('0'& vectB)  + (vectA(15) & vectA));
output <= temp( 15 downto 0);
end process;
end Behavioral;

【讨论】:

    【解决方案4】:

    你的分析是正确的。

    使用

    溢出 = EXOR(执行,添加'/SUB)

    为单一解释确定无符号加法和无符号减法(使用 2 的补码加法)的溢出。

    在无符号加法中溢出由

    表示

    执行 = 1

    正确的结果用

    表示

    执行 = 0

    但是

    ADD'/SUB = 0

    用于加法

    所以无论如何溢出都用 1 表示。

    同样

    在无符号减法中溢出由

    表示

    执行 = 0

    正确的结果用

    表示

    执行 = 1

    但是

    ADD'/SUB = 1

    是减法

    所以无论如何溢出都用 1 表示。

    因此,我们可以对无符号加法和无符号减法中的溢出有单一解释。

    【讨论】:

      猜你喜欢
      • 2019-02-23
      • 2016-04-25
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 2023-03-24
      • 2015-08-13
      相关资源
      最近更新 更多