加法器如何执行无符号整数减法?

Joh*_*ang 5 assembly unsigned subtraction

假设AB是带正号的正整数,则对于A-B,它是使用A+2的的补码计算的B

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

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

7-3=0111-0011=0111+1101=(1)0100
Run Code Online (Sandbox Code Playgroud)

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

如果我的分析是正确的,那么使用加法器执行无符号整数减法是不是错误?

GJ.*_*GJ. 5

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

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

在通常的二进制算术运算中,有符号整数和无符号整数的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'+ 进位(仅在compl时才清除(0))

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

在第二种情况下,一切都清楚了。如果我们在进位有进位(溢出),这意味着我们需要另一个溢出来标准化减法结果。


Ale*_*nze 5

这个相关问题的答案中,有 C 语言的示例代码,展示了如何通过加法进行减法。该代码还设置进位和溢出标志,并包含一个简单的“测试”,用于添加和减去一些数字并打印结果。这些数字是 8 位的。

编辑:正式证明可以使用 ADD 而不是 SUB 来处理无符号整数,并且可以像从 SUB 中一样发现无符号上溢/下溢。

假设我们要计算a - b,其中a和是 4 位无符号整数,并且我们希望通过加法执行减法,并在a < bb时获得 4 位差值和下溢/上溢指示。

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

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

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

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

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

嗯,a >= b与a < b完全相反。

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

只需颠倒进位或以相反的方式处理即可。