从逻辑门到CPU:手搓一台8位教学计算机的完整路线
只用 AND、OR、NOT、NAND、XOR 这类基础逻辑门,能不能搭出一台真正能执行程序的计算机?答案是能,而且这正是 CPU 设计最本质的路线。这个目标看起来很难,是因为从一颗逻辑门到一台计算机之间缺少的并不是材料,而是层次:先要明白逻辑门能构成加法器这类运算部件,再要明白如何用触发器构成存储部件,最后还要解决运算、存储、控制信号如何在同一个时钟节拍里协同工作。下面就把这条链路拆开讲清楚,并给出一条从仿真验证到准备上板的可执行路线。
这篇内容适合正在学习数字电路、计算机组成原理,或者想自己做一个教学 CPU 的开发者。读完以后,你应该能回答三个问题:逻辑门为什么能做出计算机;一台最小计算机需要哪几个模块;这些模块在仿真里跑通以后,上到真实电路还要补哪些功课。
1. 先拆解:计算机到底由哪些“积木层”构成
1.1 逻辑门是数字电路的最小功能单元
逻辑门做的事情非常单一:根据输入电平,决定输出电平。输入和输出都只有两种状态,通常用 0 和 1 表示。数字电路里最常见的门包括 AND、OR、NOT、NAND、NOR、XOR,它们的功能可以用一张真值表概括。
| 门类型 | 输出为 1 的条件 | 逻辑表达式 |
|---|---|---|
| AND | 所有输入都为 1 | Y = A & B |
| OR | 至少一个输入为 1 | Y = A | B |
| NOT | 输入为 0 | Y = ~A |
| NAND | 不是“所有输入都为 1” | Y = ~(A & B) |
| NOR | 不是“至少一个输入为 1” | Y = ~(A | B) |
| XOR | 两个输入不相等 | Y = A ^ B |
这些门在物理上可以用晶体管实现,也可以更底层地用继电器实现。真正关键的是:只要能做出一个 NAND 门,理论上就能组合出所有其他门。这是从逻辑门走向计算机的第一步,也是最容易被人忽略的一步。
用 NAND 门构造其他门并不复杂:
NOT A = A NAND A A AND B = NOT(A NAND B) = (A NAND B) NAND (A NAND B) A OR B = NOT A NAND NOT B = (A NAND A) NAND (B NAND B) A XOR B = (A NAND A NAND B) NAND (A NAND B NAND B)所以“只用基础逻辑门”这个前提并不苛刻。问题不是有没有足够的门,而是如何用这些门组织出更高层的功能模块。
注意:NAND 是通用门,但通用不代表高效。实际芯片会同时提供 AND、OR、XOR 等门,是为了减少门级延迟和晶体管数量。教学实验里可以用 NAND 搭一切,真实工程里应按需要选择门类型。
1.2 从门到 CPU 的四次跳跃
从逻辑门到计算机,不能直接一步到位,需要经过四个层次:
- 从逻辑门到运算部件。用 AND、XOR 等门构成半加器、全加器,再扩展成多位加法器和 ALU。
- 从组合逻辑到时序逻辑。用门构成锁存器、触发器和寄存器,让电路具备“记住状态”的能力。
- 从存储单元到可寻址内存。用触发器和地址译码器构成寄存器堆、RAM 和程序计数器。
- 从数据通路到控制单元。把运算部件和存储部件通过总线连起来,再用控制器协调每一步操作。
这条路线就是整篇内容的技术主线。后面几节按这个顺序展开。理解这条主线以后,再看任何 CPU 结构图都不会觉得它是黑盒,因为每一层都由更底层的东西组成。
2. 用逻辑门造“运算”:从半加器到 ALU
2.1 半加器与全加器
CPU 最核心的运算单元是加法器。先看一位加法。两个一位二进制数 A 和 B 相加,结果包括“和 S”与“进位 C”。这个电路叫半加器,因为不考虑来自低位的进位。
半加器真值表:
| A | B | S | C |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
观察真值表可以发现,S 就是 A 和 B 的 XOR 结果,C 就是 A 和 B 的 AND 结果。所以半加器只需要两个门:
S = A XOR B C = A AND B一位加法器显然不够用。多位数相加时,低位会产生进位,高位必须把进位也计算进去。于是有了全加器,它有三个输入:A、B、以及来自低位的进位 Cin,输出是 S 和 Cout。
全加器的逻辑表达式:
S = A XOR B XOR Cin Cout = (A AND B) OR (Cin AND (A XOR B))用门电路实现时,需要两个 XOR 门、两个 AND 门和一个 OR 门。全加器是所有算术运算的基础。
2.2 从串行进位到超前进位
把 8 个全加器按位串联,低位的 Cout 接到高位的 Cin,就得到一个 8 位加法器。这是最容易理解的结构,叫串行进位加法器(Ripple Carry Adder)。
它的问题也很明显:最高位的计算结果必须等低位的进位一路传上来,延迟会随位数线性增长。8 位还不明显,32 位、64 位时进位链延迟就会成为性能瓶颈。
解决思路是用更多逻辑门换取更短延迟。先算出每个位置的“生成信号 G”和“传播信号 P”:
G_i = A_i AND B_i P_i = A_i XOR B_i进位可以写成:
C_{i+1} = G_i OR (P_i AND C_i)把这个公式展开,就能让各位进位不依赖前一位的逐级计算,而是用同一组输入直接生成,这就是超前进位加法器(Carry Look-ahead Adder)。代价是逻辑表达式会膨胀,门数量增加,布线复杂。
实际 CPU 不会只用一种方案。学习阶段建议先实现串行进位,因为它能让你看清进位的传递过程。真要做高性能模块,再研究超前进位。
2.3 减法运算和 ALU 控制
有了加法器,减法并不需要单独造一套电路。计算机普遍使用补码表示有符号数,A - B 可以转换成:
A - B = A + (~B) + 1所以 ALU 里只需要一组反相器和一个“加 1”控制信号。当控制信号为 1 时,B 先取反,再通过 Cin 加 1,加法器就变成了减法器。
一个最小 ALU 至少需要支持加、减、与、或、非等运算。用一个多路选择器根据操作码选择输出结果。下面是一个 8 位 ALU 的 Verilog 示例,管脚和控制信号都用最简单的方式定义,方便理解:
module alu8( input [7:0] a, input [7:0] b, input [2:0] op, output reg [7:0] y, output reg z ); always @(*) begin case (op) 3'b000: y = a + b; // add 3'b001: y = a - b; // sub 3'b010: y = a & b; // and 3'b011: y = a | b; // or 3'b100: y = ~a; // not default: y = 8'h00; // 避免组合逻辑产生锁存器 endcase z = (y == 8'h00); end endmodule这里要注意两个点。第一,op就是 ALU 的控制信号,它决定多路选择器选哪个运算结果。第二,default分支不能省略。组合逻辑里如果漏掉某个分支,综合工具可能推断出锁存器,导致电路行为和你预期完全不同。
行为级 Verilog 看起来比门级简洁很多,但它综合之后仍然会被映射成逻辑门和触发器。学习阶段可以先用行为级描述验证数据通路,再回到门级图里理解每一条连线。
3. 用逻辑门造“记忆”:锁存器、寄存器和计数器
3.1 组合逻辑没有记忆能力
前文提到的 AND、OR、XOR 等门都属于组合逻辑。组合逻辑的特点是没有状态:输入变化,输出立刻跟随变化。无论电路运行多久,它都记不住之前发生过什么。
要让电路记住数据,必须引入反馈。把输出接回输入,就形成了一种“保持”结构。最简单的记忆单元是锁存器。两个 NAND 门交叉连接,可以得到 RS 锁存器:一个输入负责置位,一个输入负责复位,两个输入都无效时输出保持原样。
RS 锁存器虽然能保存 1 位数据,但它的输入规则比较严格:S 和 R 同时为有效电平时状态不确定。所以现代时序电路不会直接使用 RS 锁存器,而是在它基础上增加“使能”控制和“边沿触发”能力。
3.2 锁存器、触发器和寄存器
先看门控 D 锁存器。它把数据端 D 送到存储结构,由使能端 EN 控制是否采样。EN 为高电平时,输出跟随 D;EN 为低电平时,输出保持。
D 锁存器有一个缺陷:EN 为高电平期间,如果 D 电平变化,输出也会跟着变,这叫电平敏感。CPU 内部如果大量使用电平敏感锁存器,很难保证多位数据在同一时刻被稳定采样。所以寄存器通常使用边沿触发的 D 触发器,只在时钟上升沿或下降沿采样输入。
用 Verilog 描述一个上升沿 D 触发器很简短:
module dff( input clk, input d, output reg q ); always @(posedge clk) begin q <= d; end endmodule这里的<=是非阻塞赋值。时序逻辑中多个触发器在同一时钟沿更新时,非阻塞赋值可以避免出现“读到的还是旧值”这类竞争问题。这是仿真和综合实践中非常重要的细节。
把多个 D 触发器共用一个时钟,就构成一个多位寄存器。8 个 D 触发器组成 8 位寄存器,16 个组成 16 位寄存器。寄存器内部并不神秘,它只是一排触发器共用同一根时钟信号。
3.3 寄存器堆、RAM 和程序计数器
有了寄存器,还要解决如何选择“读写哪一个寄存器”。这需要地址译码器。例如两个地址信号可以选出 4 个寄存器中的一个,3 个地址信号可以选出 8 个中的一个。寄存器堆内部就是“寄存器阵列 + 地址译码器 + 读使能/写使能逻辑”。
RAM 的原理和寄存器堆类似,但规模更大、单元结构更紧凑。教学 CPU 里,程序放在指令存储器,运行过程中的数据放在数据存储器。存储器一端接收地址,一端接收写数据,同时有读使能和写使能信号控制访问行为。
程序计数器 PC 是一类特殊的寄存器。它保存当前指令的地址,每取完一条指令后要加 1,遇到跳转指令时又要被改成目标地址。所以 PC 本质上由三部分组成:
PC = 寄存器 + 增量器(加1电路) + 多路选择器(选择PC+1还是跳转地址)这时候你会发现,之前做的加法器和多路选择器都派上用场了。PC 的计算结果和跳转地址通过 MUX 选择,再在下一个时钟沿写回 PC 寄存器。整个 CPU 的“自动运行”能力,就来自这块简单的计数器电路。
4. 数据通路与控制:把运算和存储串成计算机
4.1 最小数据通路设计
一台最小教学 CPU 的完整数据通路,至少需要这几类部件:
- 程序计数器 PC,提供当前指令地址。
- 指令存储器,根据 PC 取出一条机器指令。
- 指令寄存器 IR,暂存当前指令。
- 控制器,根据指令操作码产生控制信号。
- 寄存器堆或累加器,保存操作数和中间结果。
- ALU,执行算术和逻辑运算。
- 数据存储器,保存程序运行时的数据。
它们之间的关系可以概括成一条取指-译码-执行循环:
取指阶段:PC -> 指令存储器 -> IR;PC <= PC + 1 译码阶段:控制器根据 IR 中的操作码生成所有控制信号 执行阶段:寄存器堆读出数据 -> ALU 计算 -> 写回目标寄存器或数据存储器 跳转处理:跳转指令把目标地址写回 PC这里把地址、数据、控制三类信号分开理解会轻松很多。地址信号决定从哪个位置取数;数据信号是真正被运算的内容;控制信号决定何时读、何时写、选哪一个操作数、做哪一种运算。
4.2 控制器:把指令翻译成控制信号
控制器是整台计算机里“看起来最聪明”的部分,拆开以后就是把指令操作码翻译成一组高低电平。
一个简单控制器需要输出的控制信号至少包括下面这些:
| 控制信号 | 作用 | 有效电平或编码 |
|---|---|---|
| PCWrite | 是否允许 PC 在下一个时钟沿更新 | 1 为允许 |
| IRWrite | 是否把取到的指令写入 IR | 1 为允许 |
| RegWrite | 是否允许寄存器堆写入 | 1 为允许 |
| ALUSrc | 选择 ALU 第二操作数来自寄存器还是数据存储 | 0/1 可选 |
| ALUOp | 选择 ALU 执行哪种运算 | 编码,对应 add/sub/and 等 |
| MemRead | 数据存储器读使能 | 1 为允许 |
| MemWrite | 数据存储器写使能 | 1 为允许 |
例如执行ADD指令时,控制器会让寄存器堆读使能有效,让 ALU 操作码选择加法,再让写回目标寄存器使能有效。执行STORE指令时,ALU 计算结果不写回寄存器,而是让数据存储器的写使能有效。
实现控制器有两种常见风格。硬布线控制器用有限状态机直接产生控制信号,速度快,但每加一条指令都要修改逻辑。微码控制器把控制信号存在一段 ROM 里,相当于用“微指令”解释“机器指令”,优点是指令扩展方便,缺点是额外多一层取微码的延迟。教学 CPU 适合先做硬布线,因为它能直观反映每条指令对应哪个状态。
4.3 时钟同步和时序约束
数据通路本身只是一堆门和触发器,真正把它们协调起来的是时钟。所有状态元件共用同一个时钟信号,才能保证整个系统按统一节拍工作。
时钟电路有两个重要参数:建立时间和保持时间。建立时间指时钟沿到来前数据必须稳定的时间;保持时间指时钟沿到来后数据必须继续维持的时间。如果门延迟太长,导致数据到达触发器的时间晚于建立时间要求,寄存器就会采到错误值。所以在真实电路里,时钟频率不能随意提高,必须满足最差路径的时序要求。
注意:不要用组合逻辑把时钟信号“切”出另一个时钟再送给触发器。例如用 AND 门把 clk 和某个使能信号组合,会产生毛刺,触发器的行为不可靠。推荐做法是所有触发器统一使用同一个时钟,需要暂停更新时用使能信号控制写操作。
5. 最小可运行示例:8 位教学 CPU 的搭建路线
5.1 先定义最小指令集
开始搭 CPU 之前,必须先定指令集。指令集就是硬件能直接识别的一组操作码编码。教学 CPU 不需要支持几十条指令,4 条指令就能跑通一个完整的“取数-计算-存数”流程。
| 助记符 | 操作码 | 机器码格式 | 功能 |
|---|---|---|---|
| LDA | 00 | 00 地址 | 把内存对应地址的值装入 A 寄存器 |
| ADD | 10 | 10 地址 | A = A + 内存对应地址的值 |
| STA | 01 | 01 地址 | 把 A 寄存器的值写入内存对应地址 |
| JMP | 11 | 11 地址 | 跳转到指定地址继续执行 |
这里采用 8 位指令字:高 2 位是操作码,低 6 位是地址。所以最多支持 64 个字节的内存空间,足够验证一个简单程序。
下面是一段计算 1 + 2 并保存结果的汇编程序:
地址0: LDA 1 ; A = Mem[1] = 1 地址1: ADD 2 ; A = A + Mem[2] = 3 地址2: STA 3 ; Mem[3] = A = 3 地址3: JMP 3 ; 跳回自身,相当于停机 地址1的数据: 01 地址2的数据: 02 地址3的数据: 00对应的二进制机器码可以由你自己在汇编器里编码。学习阶段手动填 8 位二进制就可以,重点不是汇编器,而是让指令真正在数据通路上执行起来。
5.2 模块清单与仿真环境
建议从仿真开始,因为仿真可以观察每一个内部信号。常用组合是 Icarus Verilog 做编译仿真,GTKWave 看波形。安装完成后,用下面命令编译并运行:
iverilog -o cpu_tb cpu.v tb.v vvp cpu_tb gtkwave cpu_tb.vcd仿真环境里先生成时钟和复位信号。测试文件里固定时钟周期为 20ns,仿真时间至少跑到 1000ns,才能观察到几条完整指令的执行过程。
搭建顺序可以按模块一个个来:
- 先写 8 位加法器,单独仿真。
- 加上寄存器堆和 ALU,仿真读写。
- 加上 PC 和指令存储器,仿真取指。
- 最后接入控制器,把指令流完整跑通。
不要一开始就写一个 200 行的顶层模块。模块越多,调试越难,必须靠分段验证缩小问题范围。
5.3 验证思路:从“能启动”到“结果正确”
很多新手把“仿真波形有信号”当作成功,这是不够的。最少要验证三件事:
- PC 按顺序递增,取指阶段能读到正确指令。
- ALU 输出和预期一致,写回寄存器的值正确。
- STA 指令执行后,数据存储器的目标地址确实变成正确结果。
对于上面那段计算 1+2 的程序,终点检查非常简单:仿真结束后,内存地址 3 的值应该是 0x03。
可以在 Testbench 里写一段监控逻辑,在仿真结束前打印结果:
initial begin #500; if (mem[3] == 8'h03) $display("PASS: mem[3] = %02h", mem[3]); else $display("FAIL: mem[3] = %02h, expected 03", mem[3]); end这种“断言式验证”比人肉看波形更可靠。之后每增加一条指令,就为它设计一个最小程序,覆盖正常路径和边界路径。边界路径包括全 0、全 1、减法出现负数等。
注意:不要把“仿真波形有输出”当作验证通过。要检查输出值、内存值、寄存器状态,以及控制信号是否在正确时刻有效。
6. 从仿真到真机:不同学习环境怎么选
6.1 仿真、面包板与 FPGA 的差异
同一个 8 位 CPU,既可以用仿真器看波形,也可以用面包板加 TTL 芯片搭出来,还可以用 Verilog 写完后下载到 FPGA 里跑。它们各有特点。
| 实现方式 | 可视化程度 | 调试能力 | 硬件成本 | 适合阶段 |
|---|---|---|---|---|
| Verilog 仿真器 | 中等 | 波形任意观察,信号多 | 无 | 快速验证数据通路和控制器逻辑 |
| Logisim 等逻辑仿真工具 | 高 | 可逐门连线观察 | 无 | 理解门级结构、初学者入门 |
| 面包板 + TTL 芯片 | 高 | 需要示波器和万用表 | 低到中 | 验证单个模块,比如加法器或计数器 |
| FPGA + HDL | 低 | 在线逻辑分析仪可看内部信号 | 中到高 | 接近真实设计的综合、时序、约束实践 |
学习阶段不建议直接买大型 FPGA 开发板,也不建议一上来就用电烙铁焊几百个晶体管。先用仿真器把逻辑跑通,再用适合自己预算的方式做实物验证,效率最高。
6.2 仿真和真实电路的三点差异
仿真器默认所有门延迟为 0,信号翻转是瞬时的。真实电路完全不同,至少要关注三点:
- 门延迟。信号经过每一级门都需要时间,组合逻辑越深,延迟越大。如果时钟周期小于最差路径延迟,寄存器就会采到错误数据。
- 毛刺。组合逻辑在输入切换瞬间可能出现短暂的错误电平,如果此时正好有触发器采样,就会把毛刺当成有效数据锁存进去。
- 扇出和电源噪声。一个门的输出驱动太多输入时,电平可能达不到标准阈值;电源噪声也会导致时钟沿不稳定。
所以当你把 CPU 从仿真挪到真实电路后,通常需要降低时钟频率,给信号留出足够的稳定时间。
6.3 真实板卡上需要额外补的电路
如果在 FPGA 上实现,时钟要使用开发板自带的时钟引脚,不要用低频 RC 振荡器产生时钟。复位信号要经过消抖和同步处理,避免在上电瞬间出现不确定状态。
如果在面包板上搭真实逻辑门,还建议:
- 每个电源引脚附近加去耦电容,减小电源噪声。
- 空闲输入引脚不要悬空,统一接到确定电平。
- 关键信号用示波器观察上升沿质量。
- 用低频率时钟逐步提高频率,找到稳定边界。
这些内容在仿真阶段不会遇到,但恰恰是“能写仿真”和“能跑硅片”之间的差距。
7. 常见问题和排错链路
7.1 从仿真波形倒推问题
手搓 CPU 最容易遇到的不是语法错误,而是“波形看起来在跑,但结果不对”。下面整理了几类常见故障模式。
| 问题现象 | 可能原因 | 检查方式 | 解决思路 |
|---|---|---|---|
| 所有寄存器都不更新 | 时钟没有产生或没有送到模块 | 查看 clk 波形是否翻转 | 检查 Testbench 中 clk 生成和模块端口连接 |
| 数据总线出现大量 X | 多个模块同时输出到同一总线 | 查看各输出使能信号 | 增加三态门,确保同时只有一个驱动源 |
| PC 不是顺序递增 | 跳转逻辑误触发或复位未结束 | 查看 PC 波形和控制器跳转信号 | 检查 JMP 指令译码条件,确认复位后 PC 初值 |
| 加法结果明显不对 | 数据位序接反或操作数来源选错 | 打印 ALU 输入输出 | 核对数据宽度、字节序和 ALUSrc 选择 |
| 内存被莫名写入 | MemWrite 信号悬空或默认有效 | 查看 MemWrite 默认电平 | 控制器中所有未使用状态都要给出确定的控制信号 |
| 仿真通过了但板卡不稳定 | 组合逻辑延迟或电源问题 | 降低时钟频率或观察信号毛刺 | 换更快逻辑门、加去耦电容、使用更保守时钟 |
这些故障的共同规律是:问题往往不在某一个门,而在“使能信号没有按预期配合”。所以调试时一定要同时观察控制信号和数据信号,不能只盯住某一位输出。
7.2 一套可复用的排错顺序
出现异常时,建议按下面顺序排查,不要跳步。
- 先检查时钟。时钟周期是否固定,是否到达每个触发器。
- 再检查复位。复位信号是否已经释放,复位后电路有没有进入确定状态。
- 检查 PC 和取指。PC 是否递增,IR 是否写入了正确指令。
- 检查控制信号。译码后的 PCWrite、RegWrite、MemWrite 是否只在正确状态有效。
- 检查 ALU。两个输入是否正确,运算结果是否符合真值表。
- 检查写回。目标寄存器或数据存储器是否在正确时钟沿写入了结果。
- 最后检查多条指令衔接。上一条指令的写回会不会影响下一条指令的读操作。
这个顺序从“时间基准”开始,到“功能模块”再到“整机衔接”,能避免你在复杂波形里盲目猜问题。
7.3 搭建前检查清单
每次开始一个新模块以前,先过一遍清单。它不需要很复杂,但能挡住大部分低级错误。
- 时钟周期已经确定,Testbench 里已经生成 clk 信号。
- 复位电平定义清楚,是高有效还是低有效,所有模块统一。
- 每个模块的输入输出真值表已经写好。
- 组合逻辑 always 块的所有分支和 default 值都写完整。
- 所有未使用的控制信号都固定为确定电平。
- 寄存器堆读操作和写操作不会发生在同一个时钟沿,或已经做了时序分离。
- 指令内存和数据内存的读写使能明确。
- 每个模块先单独仿真通过,再连入顶层。
- 每增加一条指令,就增加一个最小验证程序。
- 上板前已经在真机上跑过完整的内存断言,而不只是看过波形。
8. 最佳实践与扩展方向
8.1 手搓 CPU 的三条设计原则
第一条原则是模块边界清晰。PC、IR、ALU、寄存器堆、控制状态机各占一个文件或一张图纸,每个模块只暴露必要的端口。这样单个模块出问题,不会牵连整份代码。
第二条原则是先验证再集成。任何模块只要没有输出正确结果,就不要接到顶层。许多项目死在“代码全部写完结果全错”,根源就是没有做单模块测试。
第三条原则是控制信号要显式复位。上电一瞬间,寄存器内容未知,控制信号也可能处于高阻状态。必须给控制器一个复位状态,并规定每一个未使用状态的默认控制信号。
8.2 下一步可以扩展的方向
最小 8 位 CPU 能跑通之后,可以往以下几个方向扩展:
- 把串行进位加法器换成超前进位加法器,体会“用逻辑门换时间”。
- 加入条件跳转指令,比如 JZ(结果为零则跳转),让程序支持分支。
- 把单周期执行改成多周期,甚至加入简单流水线。
- 用微码控制器替换硬布线控制器,对比两种方式的设计自由度。
- 加入中断请求和中断返回指令,接近真实处理器。
- 给 CPU 增加输入输出端口,把它接到串口或显示模块上。
扩展时不要一次加太多功能。建议一次只改一个维度:要么加指令,要么改时序,要么改存储结构。这样出现问题时能迅速定位到变量。
8.3 学习路径建议
如果想继续深入,可以参考经典书籍和公开课中“从 NAND 到应用”的路线,例如一些课程会从一颗 NAND 门开始,逐步做出一个能运行简单程序的计算机。这类课程的好处是每一步都建立在可运行实验上,和“从 0 手搓 CPU”的思路一致。
对新手来说,最有价值的练习不是直接设计 32 位乱序执行处理器,而是把一个 8 位 CPU 从头到尾完整做出来:先画数据通路,再写模块,再仿真,再上板。等你真正理解了时钟、控制信号和状态机这三样东西,后面学任何架构都只是在这些基础上增加复杂度。
最终你会发现,所谓 CPU,并不存在某个不可拆解的魔法模块。它能执行的每一条指令,最终都落在逻辑门的电平变化上。理解到这一层,以后再看到“CPU 体系结构”“计算机组成原理”这些术语时,你看到的就不再是黑盒,而是一层层可以定位、可以验证、可以修改的具体电路结构。
