但是,在 CPU、ALU、寄存器以及复杂指令集的背后,所有算术运算其实都可以追溯到一个非常简单的问题:
数字电路究竟怎样把两个二进制位相加?
能够完成这种最基本加法运算的电路,叫做 半加器(Half Adder)。
半加器接收两个二进制输入,并产生两个输出:
- Sum(和)
- Carry(进位)
更有意思的是,一个最基本的半加器只需要两个逻辑门:
- 一个 XOR(异或)门
- 一个 AND(与)门
下面一步一步来看。
1. 从二进制加法开始
在研究电路之前,我们先看看两个二进制位相加会出现哪些情况。
因为每一个二进制位只能是 0 或 1,所以两个 bit 相加一共只有四种可能:
|
1 2 3 4 5 6 7 8 |
0 + 0 = 0 0 + 1 = 1 1 + 0 = 1 1 + 1 = 10 |
前三种情况都很直观。
真正重要的是最后一种:
|
1 2 |
1 + 1 = 10 |
这里的结果需要 两个二进制位 才能表示。
右边的 0 是:
|
1 2 |
Sum |
也就是加法结果的当前位。
左边的 1 是:
|
1 2 |
Carry |
也就是进位。
因此,一个负责两个 bit 相加的电路,并不能永远只产生一个输出。
它必须产生两个输出:
|
1 2 3 |
Sum Carry |
这就是半加器的基本出发点。
2. 两个输入,两个输出
假设半加器的两个输入分别是:
|
1 2 3 |
A B |
半加器产生两个输出:
|
1 2 3 |
S = Sum C = Carry |
从概念上看,可以表示成:
|
1 2 3 4 5 6 |
┌─────────────┐ A ─────►│ │────► S │ HALF ADDER │ B ─────►│ │────► C └─────────────┘ |
所以现在问题就变得很简单了:
应该使用什么逻辑来产生 S 和 C?
答案可以直接从所有可能的输入组合中找出来。
3. 半加器的真值表
半加器完整的真值表如下:
| A | B | Sum (S) | Carry (C) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
这个小小的真值表,实际上已经包含了构建半加器所需要的全部信息。
接下来,我们分别观察 Sum 和 Carry 两个输出。
4. 找到 Sum 电路
首先暂时忽略 Carry,只看 Sum 这一列。
| A | B | S |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
观察这个规律。
当两个输入不同的时候:
|
1 2 3 4 |
0, 1 → 1 1, 0 → 1 |
输出是 1。
而当两个输入相同的时候:
|
1 2 3 4 |
0, 0 → 0 1, 1 → 0 |
输出是 0。
这正好就是 XOR(异或)门 的逻辑。
因此:
|
1 2 |
S = A XOR B |
使用布尔代数符号表示:
|
1 2 |
S = A ⊕ B |
所以,半加器中负责产生 Sum 的部分,其实就是一个 XOR 门:
|
1 2 3 4 |
A ─────┐ ├──── XOR ─────► S B ─────┘ |
到这里,我们已经完成了半加器的一半。
5. 找到 Carry 电路
接下来再看 Carry 这一列:
| A | B | C |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
可以看到,Carry 只有在一种情况下才会变成 1:
|
1 2 3 |
A = 1 B = 1 |
这正好就是 AND(与)门 的逻辑。
因此:
|
1 2 |
C = A AND B |
使用布尔代数表示:
|
1 2 |
C = A · B |
对应的 Carry 电路就是:
|
1 2 3 4 |
A ─────┐ ├──── AND ─────► C B ─────┘ |
现在,Sum 和 Carry 两部分都已经找到了。
6. 完整的半加器电路
把 XOR 门和 AND 门组合起来,就得到了一个完整的半加器。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
┌──── XOR ─────► S A ───────────────┤ │ │ B ───────────────┘ ┌──── AND ─────► C A ───────────────┤ │ │ B ───────────────┘ |
两个逻辑门接收完全相同的输入:
|
1 2 3 |
A B |
其中:
- XOR 门产生 Sum
- AND 门产生 Carry
所以,一个半加器可以用两个非常简单的布尔表达式描述:
|
1 2 3 4 |
S = A XOR B C = A AND B |
或者:
|
1 2 3 4 |
S = A ⊕ B C = A · B |
这就是数字电子学中最简单的算术电路之一。
7. 当 A = 0,B = 0 时会发生什么?
假设:
|
1 2 3 |
A = 0 B = 0 |
XOR 门输出:
|
1 2 |
S = 0 |
AND 门输出:
|
1 2 |
C = 0 |
把 Carry 和 Sum 放在一起:
|
1 2 3 |
C S 0 0 |
也就是二进制:
|
1 2 |
00 |
因此:
|
1 2 |
0 + 0 = 00 |
结果就是十进制的 0。
8. 当 A = 0,B = 1 时会发生什么?
现在输入变成:
|
1 2 3 |
A = 0 B = 1 |
XOR 门输出:
|
1 2 |
S = 1 |
AND 门输出:
|
1 2 |
C = 0 |
组合起来:
|
1 2 3 |
C S 0 1 |
也就是:
|
1 2 |
01 |
所以:
|
1 2 |
0 + 1 = 01 |
它表示十进制的 1。
9. 当 A = 1,B = 0 时会发生什么?
把两个输入交换:
|
1 2 3 |
A = 1 B = 0 |
XOR 门仍然输出:
|
1 2 |
S = 1 |
AND 门输出:
|
1 2 |
C = 0 |
因此:
|
1 2 3 |
C S 0 1 |
也就是:
|
1 2 |
1 + 0 = 01 |
结果仍然是十进制的 1。
电路的行为完全符合普通二进制加法。
10. 当 A = 1,B = 1 时会发生什么?
这是四种情况中最重要的一种。
现在:
|
1 2 3 |
A = 1 B = 1 |
XOR 门计算:
|
1 2 |
1 XOR 1 |
得到:
|
1 2 |
S = 0 |
AND 门计算:
|
1 2 |
1 AND 1 |
得到:
|
1 2 |
C = 1 |
把两者组合起来:
|
1 2 3 |
C S 1 0 |
也就是:
|
1 2 |
10 |
二进制 10 等于十进制的 2。
所以:
|
1 2 |
1 + 1 = 10 |
这说明仅仅通过 XOR 门和 AND 门,数字电路已经成功完成了一次真正的二进制加法。
11. 为什么叫“半”加器?
看到这里,一个很自然的问题是:
半加器明明已经能够计算所有可能的:
|
1 2 |
A + B |
为什么它还叫 Half Adder——半加器?
原因在于,真正的多位二进制加法还有另外一个问题:
进位。
例如计算:
|
1 2 3 4 |
11 + 01 ---- |
首先从最低位开始:
|
1 2 |
1 + 1 = 10 |
当前位写下:
|
1 2 |
0 |
然后把:
|
1 2 |
1 |
进到左边的下一位。
于是,下一列真正需要计算的并不是:
|
1 2 |
1 + 0 |
而是:
|
1 2 |
1 + 0 + 1 |
最后这个 1,就是前一位产生的进位。
这时候,半加器的局限就出现了。
一个半加器只有两个输入:
|
1 2 3 |
A B |
它没有第三个输入来接收来自前一级的进位。
也就是说,半加器可以计算:
|
1 2 |
A + B |
却不能直接计算:
|
1 2 |
A + B + Carry-in |
其中:
|
1 2 |
Carry-in |
就是来自低一位的输入进位。
正因为缺少 Carry-in,半加器不能直接作为多位加法器中每一个 bit 的完整加法单元。
这也是它为什么叫做“半加器”。
12. 半加器与真正的二进制加法
半加器虽然非常简单,但它告诉了我们一个重要事实:
逻辑门可以直接实现算术运算。
它们之间的关系可以概括为:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Binary Addition │ ▼ ┌───────────┐ │Half Adder │ └───────────┘ │ │ ▼ ▼ XOR AND │ │ ▼ ▼ Sum Carry |
这里没有软件。
也没有程序在半加器内部解释某条“加法指令”。
表示 0 和 1 的电信号直接进入逻辑门。
逻辑门根据自身的物理结构和布尔逻辑产生输出。
XOR 产生 Sum。
AND 产生 Carry。
于是:
二进制算术直接从数字逻辑中产生出来。
这是理解计算机硬件非常重要的一步。
13. 从逻辑门走向计算机算术
半加器本身是一个非常小的电路。
但它背后的思想却非常重要。
前面我们已经知道,逻辑门可以实现各种布尔运算,例如:
|
1 2 3 4 5 |
AND OR NOT XOR |
现在,这些逻辑门开始做一件更加有意思的事情:
算术运算。
只需要:
|
1 2 3 4 |
1 个 XOR + 1 个 AND |
我们就可以把两个二进制位相加。
但是,真正的计算机当然不会只处理两个 bit。
CPU 需要处理:
|
1 2 3 4 5 |
8-bit 16-bit 32-bit 64-bit |
甚至更宽的数据。
如果要把许多个 bit 连续相加,就必须解决一个关键问题:
进位必须能够从一个 bit 位置传递到下一个 bit 位置。
这意味着,加法电路还需要增加第三个输入:
|
1 2 |
Carry-in |
一旦加入这个输入,半加器就会演化成一个更加实用的电路:
全加器(Full Adder)。
Conclusion
半加器(Half Adder) 是数字电路中用于两个二进制位相加的最基本算术电路。
它有两个输入:
|
1 2 3 |
A B |
以及两个输出:
|
1 2 3 |
Sum Carry |
Sum 的逻辑与 XOR 完全相同:
|
1 2 |
S = A XOR B |
或者:
|
1 2 |
S = A ⊕ B |
Carry 的逻辑与 AND 完全相同:
|
1 2 |
C = A AND B |
或者:
|
1 2 |
C = A · B |
因此,一个最基本的半加器只需要:
|
1 2 3 4 |
1 个 XOR 门 + 1 个 AND 门 |
就是这样一个极其简单的电路,展示了计算机体系结构中的一个重要思想:
算术运算可以直接由逻辑门构建出来。
但是半加器存在一个关键限制:
它不能接收前一个 bit 产生的进位。
如果希望构建能够处理多位二进制数的加法器,就需要一个具有三个输入的电路:
|
1 2 3 4 |
A B Carry-in |
这个电路就是:
全加器(Full Adder)。
接下来,我们将继续看看全加器如何在半加器的基础上解决 Carry-in 问题,以及多个全加器又是怎样连接起来,最终构成 CPU 中真正使用的多位二进制加法器。

