《编码》笔记:Petzold 教你从手电筒开始,亲手搭出一台计算机
- 约 27 分钟读完 - 全文 10503 字《编码》笔记:Petzold 教你从手电筒开始,亲手搭出一台计算机
目标读者:写了多年代码、对"计算机底层怎么跑起来的"只有模糊印象的工程师;也适合所有想给 CS 基础补课的非科班同行。 参考书籍:Charles Petzold《编码:隐匿在计算机软硬件背后的语言》(Code: The Hidden Language of Computer Hardware and Software,1999 年初版;2022 年第 2 版对章节做了扩充并配了在线交互演示,主线结构不变)。 阅读目标:不是抄一份计算机组成原理提纲,而是跟着 Petzold 的搭积木路径走一遍——每一层只用上一层的东西,绝不凭空引入新概念——把"CPU 在执行指令"这句话从信仰变成直觉。
一、全书主线:一次不跳步的推导
大多数计算机教材的讲法是"切横断面":第一章讲数制,第二章讲门电路,第三章讲组成原理,每章都是成品快照。Petzold 的讲法是纵向钻一口井:从两个小孩隔着窗户用手电筒闪摩尔斯电码开始,一路向下——电筒换成电线,电线换成电报,电报里拆出继电器,继电器组成逻辑门,逻辑门搭出加法器,加法器加上触发器变成内存,内存配上指令码变成自动计算机。全书二十多章,每一步的零件都来自上一步,没有一处"此处略去一万字"。
flowchart TD
A["手电筒 + 摩尔斯电码<br/>编码即信息表示"] --> B["电报 + 继电器<br/>电流的可控开关"]
B --> C["布尔代数 + 逻辑门<br/>开关做判断"]
C --> D["加法器<br/>门电路做算术"]
D --> E["触发器 + 振荡器<br/>电路有了记忆与节拍"]
E --> F["内存阵列<br/>可寻址的存储"]
F --> G["自动操作<br/>指令码 + 累加器 + 跳转"]
G --> H["微处理器 + 操作系统<br/>进入我们熟悉的世界"]
style A fill:#e8f5e9
style G fill:#fff3cd
这种写法对工程师有一个特别的价值:它把"底层"从黑话变成了具体的东西。我们日常说"这代码编译成指令在 CPU 上跑",多数人(包括多年前的我)其实只是在复述一个信仰。跟着这本书走完一遍,“指令"就是你亲手设计过的那几个二进制编码,“CPU"就是你亲手连过的那几个加法器和触发器的组合——再没有神秘空间留给想象。
Petzold 在全书贯串的那句话,也是这篇笔记的主线:计算机里没有魔法,一切都建立在二元选择与电路上。 剩下的全是组合与封装。
二、编码的本质:信息表示与二元选择
书的前几章一个电子元件都没有,全在讲"码”:摩尔斯电码、布莱叶盲文、手电筒信号。Petzold 这么安排是在立全书的第一个支柱——编码不依赖任何具体载体,它只依赖"可区分的不同状态”。
- 摩尔斯电码证明:只用两种信号(点、划),加上时序规则,就能表达全部字母和数字。它还顺手展示了编码设计的精妙:常用字母(E、T)用短码,生僻字母用长码——这就是一百多年前的变长编码和频率统计。Petzold 还画出了那张著名的解码二叉树:从树根出发,点是向左、划是向右,顺着信号一路走下去就唯一落到某个字母上——译码本质上是二分查找,这是"二元选择组合出任意复杂度"的第一个具体例子。书里有个诚实的补充也值得记住:摩尔斯电码严格说不是纯二元码,因为"点与划之间的停顿、字母之间的停顿、单词之间的停顿"本身就携带信息——时序也是一种码元。这个细节在后面讲串行通信和时钟的章节里会一再回来。
- 布莱叶盲文证明:6 个凸点位置,每个位置只有"凸/平"两种状态,2 的 6 次方等于 64 个码字,足够装下字母、数字、标点,还留了余量给"数字转义符"“大写转义符"这类转义码(shift/escape code)——码不够用时,不扩格子,用前缀切换语义。更进一步,二级布莱叶盲文(Grade 2)还引入了缩写字——用一个码字表示整个常用词——用空间(码表复杂度)换速度。这个思路后来在 ASCII 扩展、Unicode、协议设计、甚至 Huffman 编码里反复出现。
- 手电筒闪码证明:编码可以是纯行为,不需要任何纸张和机器。
这三章合起来说的其实是一句话:只要一个系统能提供足够多的"可区分的二选一”,它就能表示任何信息。 二进制不是一种"计算机语言",它是最小成本的区分方案——两个状态最容易造、最抗干扰、最不容易读错。计算机用二进制不是因为它"喜欢"0 和 1,而是因为造一个可靠区分两档的物理装置(开/关、高/低电压)远比造可靠区分十档的装置便宜。
数制:二进制是机器的语言,十六进制是人的速记
书里对数制的处理也很克制:二进制是电路的天然语言,八进制和十六进制只是人类给二进制发明的速记法——一位十六进制数字恰好对应 4 个二进制位,换算零成本。这解释了为什么我们至今还在和 0xFF 打交道:不是情怀,是十六进制在"人类可读"和"机器对齐"之间的最佳折中。字节(8 位)成为标准单位后,两位十六进制数恰好表示一个字节,这个巧合让十六进制的地位彻底锁死。
感悟:编码这一层想通之后,再看日常的东西眼光会变。字符集是编码、颜色是编码、文件格式是编码、协议报文是编码——全是"约定一组状态,再约定每个状态意味着什么"。出 bug 的时候,一半是逻辑错,另一半是两边对同一份编码的理解不一致(编码声明错了、转义没做、字节序反了)。Petzold 把编码放在第一章不是怀旧,是在定义全书的词汇表。
三、电报与继电器:一切从一根电线开始
从手电筒到计算机之间隔着一个关键跳跃:让电替你传递信号,并且让电替你控制电。Petzold 借电报史完成了这一步。
电报机(Samuel Morse 那一脉)的原理朴素得让人不好意思:一根导线、一个电池、一个能通断电路的按键、另一头一个电磁铁吸动的发声器。按下按键,远处"咔嗒"一声——摩尔斯电码就此摆脱了视线距离的限制。1844 年莫尔斯在华盛顿和巴尔的摩之间架通了第一条实验电报线,发出的第一封电文《圣经》语句"What hath God wrought",Petzold 引用它时也带着点敬意:这是人类第一次让信息的传播速度超过了马和火车。
真正的问题出在工程上:导线有电阻,信号传几十公里就衰减得不成样子。解决办法是继电器(relay)——用微弱电流驱动电磁铁,电磁铁吸动一个新的开关,接通一段新的、电力充足的电路,把信号"原样转发"出去。
继电器就是这条主线上最重要的零件,它有两个身份:
- 信号放大器/中继器:弱信号进,强信号出,电报线路因此可以无限接力延长;
- 用电流控制的开关:这是它的本质——一个不需要人手的、可以被另一路电流开合的开关。
第二个身份是整座大厦的地基。Petzold 在这里点破了一件事:继电器输出的电,可以反过来去控制别的继电器。这句话听起来平淡,但它意味着电路第一次可以"自己操作自己"——后面所有的逻辑门、加法器、存储器,都是这句话的展开。把"人手按开关"换成"电流控制开关",就是硬件开始脱离人工的瞬间。
四、布尔代数与逻辑门:用开关做判断
19 世纪中叶,George Boole 发表了他的逻辑代数:把"真/假"映射成 1/0,把"并且/或者/否定"映射成代数运算。Boole 本人大概没想过这东西有什么用——直到 1938 年,Claude Shannon 在 MIT 的硕士论文里证明:开关电路和布尔代数是同一件事的两面。串联的开关就是"与",并联的开关就是"或",反向接通就是"非"。Petzold 把这段历史搬出来,是为了让逻辑门的出现显得不可避免:
- 与门(AND):两个继电器串联,两路都有电流,输出才通。
- 或门(OR):两个继电器并联,任一路有电流,输出就通。
- 反相器(NOT):电磁铁吸动一个"平时闭合"的开关,有输入反而断开。
- 由这三样再组合出与非(NAND)、或非(NOR)、异或(XOR)。其中异或——“两者不同才为真”——马上要成为加法器的主角。
这里有个对程序员很有亲切感的转折:从这一章开始,继电器这个具体的电磁装置就退场了,剩下的书里只剩抽象的门符号。 Petzold 特意提醒你:门可以用继电器做,后来用真空管做,再后来用晶体管做,今天用 CMOS 做——实现换了一代又一代,逻辑结构一行都不用改。这是我们软件工程师天天享受却未必意识到其来历的红利:抽象层一旦正确,底下怎么换天都无所谓。
感悟:Shannon 那篇论文常被引用为"信息论的开端",但在这本书的语境里它更像一份接口定义文档——一边是数学家的布尔代数,一边是工程师的开关电路,两边从此可以各自演化、互相对接。好的抽象层都是这个形态:两边的人都不用懂对方的全部细节,只要共同遵守那个映射。
五、搭加法器:全书的第一个工程高潮
有了门,Petzold 立刻提出第一个像样的工程问题:用门电路算加法。这一步的推导漂亮得值得记下来:
- 先看一位加法的结果表:0+0=0、0+1=1、1+0=1、1+1=0(进位 1)。结果位恰好是异或;进位位恰好是与。一个 XOR 门加一个 AND 门,就是半加器(half adder)。
- 半加器处理不了低位传上来的进位,所以真正的每一位要用全加器(full adder):两个半加器加一个或门——先加两个输入,再把结果与进位输入相加,两路进位用或门合并输出。
- 把 8 个全加器首尾相接(低位的进位输出接高位的进位输入),就是一台 8 位行波进位加法器(ripple-carry adder)。进位像波浪一样从右往左传播,最坏情况要传满 8 级——这是书里第一次出现"性能"概念:电路的正确性和电路的速度是两回事。
flowchart LR
A["输入 A"] --> HA1["半加器 1<br/>XOR 出和<br/>AND 出进位"]
B["输入 B"] --> HA1
CI["低位进位输入"] --> HA2["半加器 2"]
HA1 -->|"中间和"| HA2
HA1 -->|"进位 1"| OR1["或门"]
HA2 -->|"进位 2"| OR1
HA2 --> SUM["本位和输出"]
OR1 --> CO["进位输出<br/>送往更高一位"]
8 个这样的全加器级联,接上 8 个开关作输入、8 个灯泡作输出,你就有一台能算 8 位加法的机器——开关拨出被加数和加数,灯泡亮灭就是结果,输入输出全是二进制,但这已经是"人机界面"的雏形:机器内部的表示和呈现给人的形式,从第一天起就是两回事。Petzold 在这一章结尾的成就感是全书第一个峰值:减法也不用另造——把减数按位取反再加一(补码),扔回同一台加法器就算完了。补码这个设计让减法、负数表示全部复用加法硬件,是"编码设计省掉硬件"的典范——一个纯粹的数制约定,换掉了整整一套减法电路。
感悟:读这一章的时候我专门停下来想了一下:我写了这么多年 a + b,这是第一次真正"看见"那个加号。不是比喻意义上的看见,是逐位地、进位一级一级传过去地看见。这个体验本身值回书价。
六、反馈与触发器:电路学会了记忆
到加法器为止,所有电路都是组合的——输出完全由当前输入决定,输入撤了,输出就没了。这样的电路不会"记住"任何东西。Petzold 用整整一章讲那个改变一切的结构:反馈(feedback)——把输出接回输入。
- 振荡器(oscillator):把反相器的输出接回自己的输入,电路就在 0 和 1 之间自动来回翻转。不需要任何人操作,它自己产生了节拍——这就是时钟(clock)的雏形,后来计算机里一切"按节拍推进"的源头。
- R-S 触发器(flip-flop):两个或非门交叉耦合——每个门的输出接回另一个门的输入。S(置位)给一个脉冲,输出变 1 并保持;R(复位)给一个脉冲,输出变 0 并保持。两个输入都撤掉之后,输出停在最后的状态。电路记住了"上一次谁碰过我"。
- D 触发器(电平/边沿触发):给 R-S 触发器加一路"时钟"输入,数据端(D)决定"存什么",时钟端决定"什么时候存"。时钟跳变的瞬间,D 的值被锁存下来,之后 D 再怎么变都不影响输出。这就是 1 位存储器。
flowchart LR
S["置位 S"] --> N1["或非门 1"]
R["复位 R"] --> N2["或非门 2"]
N1 -->|"输出 Q"| OUT["Q<br/>电路记住的状态"]
N1 -.->|"交叉反馈"| N2
N2 -.->|"交叉反馈"| N1
N2 -->|"反相输出"| NQ["Q 反"]
反馈结构还有一个直接的红利:计数器。把触发器的反相输出接回自己的数据端,每来一个时钟脉冲它就翻转一次——输出波形的频率恰好是输入的一半。把 n 个这样的触发器串起来,每级的输出频率依次减半,把各级输出当作二进制的各位来读,你就得到一个 n 位二进制计数器,时钟每跳 2 的 n 次方次循环一轮。Petzold 在这里埋了一个很妙的呼应:前几章刚教会你读二进制数,这一章电路自己就"数"出了二进制数——数制不是抽象数学,是电路的自然行为。计数器在后面的自动操作里会扮演"程序计数器"的角色:让电路自己记住"执行到第几条指令了"。
感悟:这一章是全书概念密度最高的一章,也是最值得慢读的一章。软件里"状态"是理所当然的(变量往那一放就有了),硬件里"状态"是要专门设计的——没有反馈回路就没有记忆,没有记忆就没有程序计数器、没有寄存器、没有一切。“存储"不是自然存在的,是用两个或非门互相咬尾咬出来的。理解这一点之后,“时序电路"和"组合电路"的分野、为什么信号完整性和时钟频率会成为硬件的命门,全都顺理成章。
七、内存阵列与自动操作:积木的最后两格
内存:把触发器组织成可寻址的阵列
一个 D 触发器存 1 位。8 个一排存 1 个字节。接下来是纯粹的工程组织问题:怎么让"写入"动作精确命中阵列里的某一个字节?答案是我们今天无比熟悉的三件套:地址、译码器、选择器。
- 16 位地址就是 16 根信号线,经译码器展开成 65536 条选择线,每条线唯一选中一个字节——64K 字节的 RAM 阵列。
- 读数据时,选择器(一堆与门加或门)把被选中的字节送到输出;写数据时,只有被选中的那一排触发器的时钟端被放行。
- 触发器太贵?书上接着讲了省继电器的折衷(锁存结构的演进、以及后来电容式 DRAM 的思路),但逻辑骨架不变:可寻址 = 译码 + 选择。
自动操作:让电路按清单自己干活
全书第十七章"自动化"是积木封顶的地方,Petzold 的目标明确:造一台不用人盯着拨开关的计算机器。零件都已备齐:加法器、RAM 阵列、计数器、触发器。
在进入自动化之前,书里先让你体会了一把"手工操作"的滋味:要算两个数的乘积,你得自己坐在控制面板前,扳开关把被乘数写进 RAM、扳开关触发加法、把中间结果抄下来再写回去——每算一步人都在场。这个铺垫很关键,它让"自动化"的必要性变成了体感而不是概念:瓶颈从来不是电路算得慢,是人操作得慢。 组装的思路是:
- 代码进内存:把数据和指令都编码成字节放进 RAM——指令就是约定俗成的字节值,比如某个字节表示"Load”(把某地址的值装进累加器),某个表示"Add”,某个表示"Store",某个表示"Jump",某个表示"Halt"。书里这台机器的指令表还包括带进位加(Add with Carry)、带借位减(Subtract with Borrow)、零跳转(Jump If Zero)等变体——多字节运算靠进位标志串起来,这正是后来 x86 里
ADC/SBB这类指令的原型。指令集就是一张编码表,回到第二章的主题。 - 累加器(accumulator):一个带锁存的寄存器,挂在加法器上,是所有运算的集散地——Load 装进来,Add 累加,Store 写回内存。
- 自动取指:用一个计数器(程序计数器)依次生成地址,每执行完一条指令自动加一,取下一条。RAM 的一部分存指令、一部分存数据,同一套读写机构伺候两者。
- 跳转(Jump):Jump 指令把指定地址直接装进计数器,下一条指令就换地方取了。配上"条件跳转"(结果为零才跳、有进位才跳),程序有了分支;分支加循环,通用计算的全部要件就此凑齐。
flowchart TD
PC["程序计数器<br/>自动加一"] --> RAM["RAM 阵列<br/>指令与数据共处一室"]
RAM -->|"取出指令字节"| DEC["译码与控制<br/>查表: 这是什么操作?"]
DEC -->|"Load / Store"| ADDR["地址送往 RAM 读写"]
DEC -->|"Add / Subtract"| ALU["加法器 + 累加器"]
ADDR --> ACC["累加器"]
ALU --> ACC
ACC -->|"Store 写回"| RAM
DEC -->|"Jump: 改写计数器"| PC
DEC -->|"Halt"| STOP["停机"]
这就是冯·诺依曼结构的全部实质:指令和数据用同一种编码、住在同一片存储里,机器按计数器自动取指执行。书里这台"玩具计算机"只有几条指令,但 Petzold 会算给你看:用 Load/Add/Store/Jump 这几条,循环累加做乘法、乘法套乘法做乘方,都能跑——慢,但没有做不到。通用性不是来自指令多,是来自跳转。
八、从玩具机到真实世界:总线、微处理器与字符编码
登顶之后,书的最后几章把我们熟悉的世界一件件接回来:
- 微处理器:把前面搭的所有东西——运算器、寄存器、控制逻辑——集成进一枚芯片。Petzold 用 Intel 8080 和 Motorola 6800 做标本:你会发现它们的指令集就是自己搭的那台玩具机的豪华版,Load/Add/Store/Jump 一条不少,只是更多、更快、更小。
- 总线(bus):处理器、内存、外设之间不能每两个都拉专线,于是大家共享一组公共信号线——地址总线、数据总线、控制总线——挂在上面的设备按地址认领属于自己的请求。总线本质上是用时间换空间的多路复用。
- 存储层次:书里的 RAM 阵列有个致命弱点——断电即失(触发器是电路,不是石刻)。于是需要更慢但持久的介质兜底:纸带、磁芯、磁盘、闪存,一代代接力。这一慢一快的落差逼出了存储层次结构:越快越贵越小的离 CPU 越近,越慢越便宜越大的垫底。寄存器、缓存、内存、磁盘的金字塔,不是设计出来的品味,是物理约束逼出来的妥协。
- 操作系统:有了能自动执行指令的机器,就需要一个"先跑起来、再替别的程序干活"的程序——管理内存、管理设备、把文件抽象成字节流。从自动操作到 OS,差的只是一层软件约定。
- 高级语言与汇编:机器码太难写,于是有人写了一个把助记符翻译成机器码的程序——汇编器;再往上,一个把接近数学表达的文本翻译成机器码的程序——编译器。软件开始生产软件,这是全书暗线的必然终点:每一层抽象一旦稳固,就变成下一层的建材。
- 定点与浮点:要表示小数和极大极小的数,又得回到编码问题——约定哪些位是整数部分、哪些是小数部分(定点),或者约定一套"符号 + 尾数 + 指数"的科学计数法格式(浮点)。浮点的一切怪异(0.1 加 0.2 不等于 0.3)都是这套编码约定的直接推论。
- ASCII 与字符编码:兜兜转转回到编码——计算机要处理文字,于是约定 7 位二进制数对应字符:95 个可打印字符加 33 个控制字符。这套约定和第一章的摩尔斯电码、布莱叶盲文在结构上一模一样:有限状态、人为约定、带转义。全书在这里闭环:从编码出发,绕电路一大圈,最后又回到编码。
第 2 版(2022)补充的在线交互演示值得单独提一句:书里搭的继电器、逻辑门、加法器都能在网页上拨开关亲眼看它跑。对"不亲手拨一遍就记不住"型学习者(比如我),这个配套资源把书的完成度又推高了一截。
九、落到工程实践:这本书改变了什么
这本书不是工具书,但它在我日常工作中留下了几个具体的使用痕迹:
- 排障时下意识"降层"。 遇到玄学 bug,以前的第一反应是往上翻日志;现在会先问一句"这一层底下是什么"——字符乱码降一层是编码声明错位,再降一层是字节序;接口超时降一层是重试放大,再降一层是队头阻塞。Petzold 的书本质上训练的就是这种"每一层都是上一层的编码"的世界观:任何一层的魔法,降一层都是约定。
- 对"性能"有了物理直觉。 行波进位加法器那一节是全书第一次讲"正确但慢":进位要一级一级传,n 位加法器的延迟随位数线性增长,真实 CPU 用超前进位(carry lookahead)用空间换时间。这个"信号要在物理结构里传播"的直觉,换个尺度就是缓存行、内存墙、网络 RTT——所有性能问题归根结底都是"距离"问题。
- 设计编码和协议时更克制。 布莱叶盲文的转义码、补码省掉减法器、ASCII 的控制字符,讲的都是同一件事:好的编码用最小状态数表达最大语义,余量留给扩展。自己设计消息格式、状态机、错误码时,我会先问:状态数能不能再砍一半?需不需要留一个"转义"出口?
- 给新人讲底层时有了最短路径。 组里有同学问"程序到底怎么跑起来的",与其扔一本组成原理,不如复述 Petzold 的积木链:手电筒 → 继电器 → 门 → 加法器 → 触发器 → 内存 → 取指执行。十五分钟讲完,对方的眼神从"敬畏"变成"就这?"——“就这?“就是这本书想达到的效果。
- 动手验证的习惯被强化。 这本书的写法本身就是示范:每个论断都跟着一个"不信你自己连一遍"的电路。受它影响,我现在学任何底层概念(调度、GC、索引结构)都会逼自己写一个最小可跑的实现——写一个 50 行的玩具调度器,比读十篇调度原理文章管用。第 2 版的在线交互演示把这个门槛降到零:浏览器里就能拨开关看加法器跑,没有借口不动手。
十、积木依赖速查表
把全书的搭积木链条压成一张表。每一行回答三个问题:这一层用什么搭的、获得了什么新能力、对应我们今天熟悉的什么。这张表也是我给新人讲底层的提纲——从上到下念一遍,就是计算机的简史。
| 层级 | 用什么搭的 | 获得的新能力 | 今天的对应物 |
|---|---|---|---|
| 编码(摩尔斯/布莱叶) | 可区分的两种状态 | 任何信息都可表示 | 字符集、协议、文件格式 |
| 电报 | 电池 + 导线 + 电磁铁 | 信息超越视线距离传播 | 一切通信的祖先 |
| 继电器 | 电磁铁吸动开关 | 电流控制电流 | 晶体管的逻辑祖先 |
| 逻辑门 | 继电器串并联 | 用开关做布尔判断 | CPU 里的门电路 |
| 半加器/全加器 | XOR + AND + OR | 电路做算术 | ALU |
| 行波进位加法器 | 8 个全加器级联 | 多位加法 | 整数运算单元 |
| 振荡器 | 反相器输出接回输入 | 自动产生节拍 | 时钟信号 |
| R-S/D 触发器 | 两个或非门交叉耦合 | 电路有了记忆 | 寄存器、锁存器 |
| 计数器 | 触发器串联分频 | 电路自己会数数 | 程序计数器 |
| RAM 阵列 | 触发器 + 译码器 + 选择器 | 可寻址的海量存储 | 内存 |
| 自动计算机 | 加法器 + RAM + 计数器 + 指令码 | 不用人盯的通用计算 | CPU + 冯·诺依曼结构 |
| 微处理器/OS/总线 | 上述一切的集成与封装 | 进入我们熟悉的世界 | 今天的一切 |
看这张表有一个额外的收获:每一层都极其简单,复杂的只有组合方式。 这也是面对任何庞大系统时该有的心态——别怕它大,找到它的"继电器层”,从那里开始读。
本篇小结
- 全书主线一句话:计算机没有魔法,一切都建立在二元选择与电路上;其余全是组合与封装。
- 编码的本质是信息表示:摩尔斯电码、布莱叶盲文、ASCII 是同一结构的三个实例——有限状态、人为约定、转义扩展。
- 继电器是地基零件:用电控制的开关,让电路第一次能自己操作自己。
- 布尔代数给开关赋予逻辑:与、或、非三件套搭出一切判断;异或加与门就是半加器,两个半加器加或门就是全加器,八个级联就是行波进位加法器;补码让减法复用加法。
- 反馈让电路有了记忆:反相器咬尾成振荡器(时钟),或非门交叉耦合出 R-S 触发器,加时钟成 D 触发器(1 位存储),串联成计数器(程序计数器)。
- 自动操作的全部要件:指令编码表 + 累加器 + 程序计数器 + 条件跳转;指令与数据同住一片 RAM,就是冯·诺依曼结构。
- 往上走的每一层——微处理器、总线、操作系统、高级语言——都只是同一套积木的规模化封装;积木依赖速查表见第十节。
- 本书的副产物是一种读系统的方法论:面对任何庞大系统,找到它的"继电器层”,从那里开始读。
这本书我常推荐给两类人:刚入行想补计算机地基的,和写了很多年上层代码、开始好奇底下发生了什么的。对前者它是最平滑的入门路径,对后者它是一次"祛魅"——读完你会发现,所谓底层,不过是一群被理解得很透的简单东西。
参考资料
- Charles Petzold, Code: The Hidden Language of Computer Hardware and Software, Microsoft Press, 1999(第 1 版)/ 2022(第 2 版,含 codehiddenlanguage.com 在线交互演示)。
- 中译本:《编码:隐匿在计算机软硬件背后的语言》,左飞、薛佟佟 译,电子工业出版社。
- Claude E. Shannon, “A Symbolic Analysis of Relay and Switching Circuits”, 1938(书中第四章主线的原始论文,继电器与布尔代数的联姻)。
- George Boole, An Investigation of the Laws of Thought, 1854(布尔代数的原始出处)。