4.4.1. 加法
回想一下,在二进制数中,每个数字只包含 0 或 1。因此,当将两个都是 1 的位相加时,结果会执行到下一位数字(例如,1 + 1 = 0b10,这需要两个位来表示)。在实践中,程序会添加多位变量,其中一位数字的结果 进位输出(carry out) 会通过 进位输入(carrying in) 影响下一位数字。
一般来说,当对两个二进制数(A 和 B)进行数字求和时,根据前一位数字的 DigitA、DigitB 和 Carryin 的值,有 八种 可能的结果。 表 1 列举了添加一对位可能产生的八种可能性。 Carryin 列是指从前一个数字向和中输入进位,Carryout 列表示将这对数字相加是否会将进位输入到下一个数字中。
表 1. 添加两个二进制数字(A 和 B)以及可能从前一个数字进位(Carry In)的八种可能结果
Inputs | Inputs | Inputs | Outputs | Outputs |
---|---|---|---|---|
DigitA | DigitB | Carryin | Result (Sum) | Carryout |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
考虑两个四位二进制数的相加。首先将数字排列起来,使其对应的数字垂直匹配,然后按从低位数字 (d0) 到高位数字 (d3) 的顺序将每个对应数字相加。例如,添加 0b0010 + 0b1011:
Problem Setup | Worked Example |
---|---|
   0010 + 1011 |      1 <- Carry the 1 from digit 1 into digit 2    0010 + 1011 Result: 1101 |
该示例显示 1 从 d1 传送到 d2。这种情况类似于将两个十进制数字相加,其总和大于 9。例如,当 5 + 8 = 13 相加时,结果个位包含 3,并且 1 进位到十位。
第一个操作数 (0b0010) 有一个前导 0,因此对于二进制补码和无符号解释来说,它都代表 2。如果将第二个操作数 (0b1011) 解释为带符号的二进制补码值,则表示 -5。否则,如果解释为无符号值,则表示 11。幸运的是,操作数的解释不会影响计算结果的步骤。也就是说,计算结果 (0b1101) 表示 13(无符号:2 + 11)或 -3(有符号:2 + -5),这两者都是正确的,具体取决于第二个操作数的解释。
更一般地,当解释为 无符号 时,四位序列表示范围 [0, 15] 内的值。当解释为 signed 时,它表示范围 [-8, 7]。在前面的示例中,无论哪种方式,结果都符合可表示的范围,但我们可能并不总是那么幸运。例如,当添加0b1100(无符号12)+ 0b0111(7)时,答案应该是19,但四位不能代表19:
Problem Setup | Worked Example |
---|---|
   1100 + 0111 |  11 <- Carry a 1 from: digit 2 into digit 3, and    1100  digit 3 out of the overall value + 0111 Result: 0011 Carry out: 1 |
请注意,此示例中的加法从最高有效位开始携带 1,这种条件称为整个算术运算的 执行。在此示例中,进位表明算术输出需要额外的位来存储预期结果。然而,当执行四位算术时,没有地方可以放置进位的额外位,因此硬件只是丢弃或截断它,留下 0b0011 作为结果。当然,如果目标是加上12+7,那么3的结果可能会令人惊讶。令人惊讶的是 溢出(overflow) 的结果。我们将在后面的部分中探讨如何检测溢出以及它为何会产生这样的结果。
[!NOTE] 多位加法器电路还支持进位输入(carry in),其行为类似于最右边数字的进位(即,它充当 d0 的_进位_ 输入)。进位在执行加法时没有用——它被隐式设置为 0,这就是为什么它没有出现在前面的示例中。然而,进位确实与使用加法器电路的其他操作相关,最值得注意的是4.4.2. 减法。