从零开始
目录

00 · 入门

电脑怎么算数:从开关到加法器(进阶)

本篇你将学到

  • 逻辑门:用开关和灯就能做“判断”
  • 怎么用几个门搭出会做加法的电路
  • 电脑怎么只靠加法和“挪位置”算出减、乘、除

上一篇说过,电脑里的数字就是一排开关(0 和 1)。这一篇看看,开关是怎么“算”出 5 + 6 的。干这活的,是 CPU 里叫算术逻辑单元(ALU)的部分,意思就是“专门做算术和简单判断的小车间”[4](CPU 见 00-03 的 CPU 小节)。

逻辑门:开关和灯

想象一盏灯,前面接着开关。按不同方式接线,就得到几种最基本的“门”[5]:

门 什么时候灯亮(输出 1) 生活里像
与(AND) 两个开关都是 1 两个开关串在一根线上
或(OR) 至少一个是 1 两个开关并排接
非(NOT) 开关是 0 时 反着来的开关
异或(XOR) 两个开关不一样时 楼梯上下两个开关控制同一盏灯

真正的芯片里,“开关”是几十亿个极小的晶体管,但道理就是这几种门[5]。

用门搭一个加法器

一位加一位只有四种情况:0+0=0,0+1=1,1+0=1,1+1=10(写 0,进 1)。仔细看:

  • “这一位写几”:两个数不一样时是 1 → 正好是异或门;
  • “要不要进位”:两个数都是 1 才进位 → 正好是与门。

一个异或门加一个与门,就是半加器[1][6]。

但多位数相加时,每一位除了 A、B,还要加上右边送来的进位,一共三个数。把两个半加器接起来(先算 A+B,再加进位),两边任一边进位就向左进 1(用一个或门),就得到全加器[2][6]。

把 4 个全加器排成一排,每个的进位输出接到左边那个的进位输入,就是一个 4 位加法器。进位像接力棒一样从右往左一位一位传,所以叫“行波进位”[1][2]。电脑里的加法器原理一样,只是有 32 位、64 位那么宽,还用了更快的进位方法[2]。

自己点一点:先在“单个门”里认识四种门,再看半加器、全加器,最后在 4 位加法器里试试 5 + 3、9 + 8(会溢出),以及勾上“做减法”算 5 − 3、3 − 5。

模拟实操 · 开关搭出加法器点开关,看灯亮

绿色粗线 = 1(有电),灰色细线 = 0(没电);黄灯亮 = 1。电路已简化,只为说明原理。

加减乘除

先在纸上算:满 2 进 1

二进制加法和小学的竖式加法一模一样,从最右边一位开始加,只是十进制“满 10 进 1”,二进制是满 2 进 1[1]。所以只有四种情况要记:0+0=0,0+1=1,1+0=1,1+1=10(写 0,向左进 1)。

比如 5 + 6(用 4 位来写):

  进位   1
    5 = 0101
 +  6 = 0110
 ───────────
   11 = 1011

从右往左:1+0=1;0+1=1;1+1=10,写 0 进 1;0+0 再加进上来的 1,得 1。结果 1011 就是 8+2+1=11。

减法:加上一个“负数”

上面的加法器只会加,所以电脑不另外造减法器,而是把“减去 6”变成“加上负 6”[2]。那负数怎么写?有个很巧的办法,叫补码,做法就两步:把每一位 0 变 1、1 变 0,再加 1[2][3]。

用 4 位举例算 7 − 6:6 是 0110,翻转得 1001,再加 1 得 1010,这就是“负 6”。然后 7 + (负 6):

    0111   (7)
 +  1010   (负 6)
 ─────────
   10001

结果有 5 位,但我们只有 4 个格子,最左边多出来的 1 直接扔掉,剩下 0001,就是 1。答案对了!

在电路里,“翻转”就是让 B 的每一位过一个非门,“再加 1”就是把最右边那个全加器的进位输入设成 1——还是同一个加法器[2]。上面模拟里勾上“做减法”就能看到。

可以把它想象成汽车的里程表:4 位的表只能显示 0000 到 1111,再往上加就“转满一圈”回到 0000。在这样的表上,“往前走 10 格”和“往回退 6 格”停在同一个位置,所以加上 1010 就等于减去 6。

乘法:加法 + 挪位置

在十进制里,一个数后面添个 0 就变成 10 倍:25 → 250。二进制也一样,只不过后面添个 0(也就是整体往左挪一格)是变成 2 倍:3 是 11,往左挪一格变成 110,就是 6[1]。

乘法就是用这个办法:看乘数的每一位,是 1 就把被乘数(挪好位置后)加进来,是 0 就跳过,最后全部加起来[1]。比如 5 × 3,3 是 11:5(101)加上“往左挪一格的 5”(1010),101 + 1010 = 1111,就是 15。

除法:反复试着减

13 块糖,每人分 3 块,能分给几个人?一次拿走 3 块:13 → 10 → 7 → 4 → 1,拿了 4 次,剩 1 块。所以 13 ÷ 3 = 4 余 1——除法就是反复减,数减了几次。

数字大了一次次减太慢,所以像小学长除法那样,从左边一位一位算。二进制每位只能是 0 或 1,所以每步只问一句:够减就减掉、商写 1;不够就商写 0,再拿下一位[1]。

13 ÷ 3(1101 ÷ 11):

第几步 拿下一位后,手里的数 够不够减 11(3) 商写 剩下
1 1(1) 不够 0 1(1)
2 11(3) 够 1 0(0)
3 0(0) 不够 0 0(0)
4 1(1) 不够 0 1(1)

每步把上一步“剩下”的数后面接上新拿下的一位。商从上往下读 0100 就是 4,剩 1,和分糖一样。除以 2 更简单:整体往右挪一格,挪出去的那位就是余数[1]。

4 个开关只能装到 15,数字大了就用下面的计算器:电路一样,只是位数多一些。试试“5 + 6”,再切换成减法试试“7 − 6”和“3 − 5”,乘法试试“5 × 3”,除法试试“13 ÷ 3”:

小结

  • 逻辑门就是开关和灯:与(都亮才亮)、或(有一个就亮)、非(反着来)、异或(不一样才亮)。
  • 异或 + 与 = 半加器;两个半加器 + 或 = 全加器;一排全加器 = 多位加法器。
  • 减法 = 翻转再加 1,用的还是同一个加法器;乘法 = 加法 + 往左挪;除法 = 反复试着减。
  • 把这些电路组合起来、再加上“选哪种运算”的开关,就是 CPU 里的 ALU[4][6]。

下一篇是术语表,把这几篇里出现的词集中整理一遍,忘了随时回来查。

参考资料

  1. [1]CIS 371 Computer Organization and Design · Unit 4: Arithmetic · University of Pennsylvania (Milo Martin)
    https://acg.cis.upenn.edu/milom/cis371-Spring11/lectures/04_arith.pdf
  2. [2]6.111 Lecture 8: Arithmetic Circuits & Multipliers · MIT
    https://web.mit.edu/6.111/www/f2016/handouts/L08.pdf
  3. [3]Two's Complement · Thomas Finley, Cornell University
    https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
  4. [4]What is a Central Processing Unit? · Arm
    https://www.arm.com/glossary/cpu
  5. [5]Project 1: Boolean Logic · Nand2Tetris (Nisan & Schocken)
    https://www.nand2tetris.org/project01
  6. [6]Project 2: Boolean Arithmetic · Nand2Tetris (Nisan & Schocken)
    https://www.nand2tetris.org/project02