ALU
上节,我们谈了如何用二进制表示数字,比如二进制 00101010 是十进制的 42,表示和存储数字是计算机的重要功能,但真正的目标是计算,有意义的处理数字。比如把两个数字相加,这些操作由计算机的 "算术逻辑单元 "处理。但大家会简称:ALU。
ALU 是计算机的数学大脑,等你理解了 ALU 的设计和功能之后,你就理解了现代计算机的基石。ALU 就是 计算机里负责运算的组件基本其他所有部件都用到了它。
先来看看这个美人,这可能是最著名的 ALU,英特尔 74181,1970 年发布时,它是第一个封装在单个芯片内的完整 ALU,这在当时是惊人的工程壮举。
今天我们用上周学的布尔逻辑门,做一个简单的 ALU 电路,功能和 74181 一样,然后接下来几周,用它从头做出一台电脑,所以会有点复杂,但我觉得你们搞的定。
ALU 有 2 个单元,1 个算术单元和 1 个逻辑单元,我们先讲"算术单元",它负责计算机里的所有数字操作,比如加减法它还做很多其他事情,比如给某个数字 1,这叫增量运算,我们之后会说。
今天的重点是一切的根本 - "把两个数字相加",我们可以用单个晶体管一个个拼,把这个电路做出来,但很快就会复杂的难以理解。所以与其用晶体管,我们会像第 3 节,用更高层的抽象,用逻辑门来做,我们会用到 AND,OR,NOT 和 XOR 逻辑门,最简单的加法电路, 是拿 2 个 bit 加在一起(bit 是 0 或 1),有 2 个输入:A 和 B, 1 个输出:就是两个数字的和,需要注意的是:A, B, 输出,这3个都是单个 Bit ( 0 或 1 )。
输入只有四种可能,前三是 0 0 = 0 ; 1 0 = 1 ; 0 1 = 1。记住二进制里,1 与 true 相同,0 与 false 相同。这组输入和输出,和 XOR 门的逻辑完全一样,所以我们可以把 XOR 用作 1 位加法器(adder)。但第四个输入组合,1 1,是个特例 1 1=2(显然),但二进制里没有 2。上节说过,二进制 1 1 的结果是0,1进到下一位和是 10 (二进制)。XOR 门的输出,只对了一部分, 1 1 输出 0,但我们需要一根额外的线代表 "进位",只有输入是 1 和 1 时,进位才是 "true"。因为算出来的结果用 1 个 bit 存不下,方便的是,我们刚好有个逻辑门能做这个事!没那么复杂 , 就两个逻辑门而已让我们抽象化。把 "半加器" 封装成一个单独组件,两个输入 A 和 B 都是 1 位, 两个输出 "总和" 与 "进位"。这进入了另一层抽象,我好像说了很多次,说不定会变成一个梗。
全加器
如果想处理超过 1 1 的运算,我们需要"全加器",半加器输出了进位,意味着,我们算下一列的时候,还有之后的每一列,我们得加 3 个位在一起,并不是 2 个。全加器复杂了一点点,全加器表格,有 3 个输入:A, B, C (都是 1 个 bit),所以最大的可能是 1 1 1,"总和"1 "进位"1 , 所以要两条输出线: "总和"和"进位",我们可以用半加器做全加器。我们先用半加器将 A 和 B 相加,然后把 C 输入到第二个半加器,最后用一个 OR 门检查进位是不是 true,这样就做出了一个全加器!
我们可以再提升一层抽象,把全加器作为独立组件,全加器会把 A,B,C 三个输入加起来输出 "总和" 和 "进位"。现在有了新组件,我们可以相加两个 8 位数字,叫两个数字叫 A 和 B 好了。我们从 A 和 B 的第一位开始,叫 A0 和 B0 好了。现在不用处理任何进位,因为是第一次加法,所以我们可以用半加器,来加这2个数字,输出叫 sum0。现在加 A1 和 B1,因为 A0 和 B0 的结果有可能进位,所以这次要用全加器,除了 A1 和 B1,还要连上进位,输出叫 sum1。然后,把这个全加器的进位,连到下个全加器的输入,处理 A2 和 B2。以此类推,把 8 个 bit 都搞定。注意每个进位是怎么连到下一个全加器的,所以叫 "8位行波进位加法器"。
溢出
注意最后一个全加器有 "进位" 的输出,如果第 9 位有进位,代表着 2 个数字的和太大了,超过了 8 位,这叫 "溢出" (overflow),一般来说 "溢出" 的意思是, 两个数字的和太大了,超过了用来表示的位数,这会导致错误和不可预期的结果。著名的例子是,吃豆人用 8 位存当前关卡数,如果你玩到了第 256 关( 8 位 bit 最大表示 255),ALU 会溢出,造成一连串错误和乱码,使得该关卡无法进行,这个 bug 成了厉害吃豆人玩家的代表。
如果想避免溢出,我们可以加更多全加器,可以操作 16 或 32 位数字,让溢出更难发生,但代价是更多逻辑门。另外一个缺点是,每次进位都要一点时间,当然时间不久,因为电子移动的很快。但如今的量级是每秒几十亿次运算,所以会造成影响,叫 "超前进位加法器"。它更快,做的事情是一样的 - 把二进制数相加,ALU 的算术单元,也能做一些其他数学运算,一般支持这 8 个操作。
就像加法器一样,这些操作也是由逻辑门构成的,有趣的是,你可能注意到没有乘法和除法,因为简单的 ALU 没有专门的电路来处理,而是把乘法用多次加法来实现。假设想算 12x5,这和把 "12" 加 5 次是一样的,所以要 5 次 ALU 操作来实现这个乘法,很多简单处理器都是这样做的。比如恒温器,电视遥控器和微波炉,慢是慢,但是搞的定。然而笔记本和手机有更好的处理器,有专门做乘法的算术单元,你可能猜到了,乘法电路比加法复杂,没什么魔法,只是更多逻辑门。所以便宜的处理器没有。