CC 咖啡猫的工作空间 Coding Space

从晶体管到 CPU

这篇解决什么问题

我们每天写的代码最终都会变成 CPU 能执行的指令。理解「晶体管到 CPU」这条链路,可以帮你把抽象代码和真实机器连接起来:为什么计算机只认识 0 和 1,为什么寄存器很快,为什么条件判断、循环、函数调用最终都能落到硬件执行。

学完你会掌握

  • 晶体管为什么可以表示开关。
  • 逻辑门如何组合出计算能力。
  • 寄存器、时钟、指令在 CPU 中扮演什么角色。
  • 高级语言代码如何一步步变成机器执行。

核心概念

晶体管可以理解为可控开关。开表示 1,关表示 0。大量晶体管组合在一起,就能形成逻辑门。

这条链路可以按抽象层级理解:

晶体管
  -> 逻辑门
  -> 加法器、译码器、选择器
  -> 触发器、寄存器
  -> ALU、控制单元、寄存器组
  -> CPU
  -> 操作系统和应用程序

抽象的意义在于:上层不需要时时刻刻关心下层细节,但下层决定了上层的能力边界。你写的 if、循环、函数调用,最终都会落到这些硬件结构上。

常见逻辑门包括:

逻辑门 含义 例子
AND 两个输入都为真,输出才为真 权限 A 且权限 B
OR 任意输入为真,输出为真 手机号或邮箱登录
NOT 取反 非管理员
XOR 两个输入不同才为真 简单校验

逻辑门继续组合,可以得到加法器、选择器、寄存器、控制电路,最后形成 CPU。

从开关到运算

晶体管真正重要的地方,不只是能表示 0 和 1,而是它可以被电信号控制。一个开关控制另一个开关,电路就能自动完成逻辑判断。

例如:

  • NOT 门可以翻转信号。
  • AND 门可以表达「两个条件同时成立」。
  • OR 门可以表达「任意条件成立」。
  • XOR 门可以表达「两个输入不同」。

把 XOR、AND、OR 组合起来,就可以构造半加器和全加器。全加器不只计算当前位的和,还会处理进位。多个全加器串联,就能完成多位二进制加法。

这就是硬件运算的核心:复杂计算不是凭空出现的,而是大量简单逻辑的组合。

功能单元

CPU 内部不是一整块神秘电路,而是由很多功能单元协作:

功能单元 作用
ALU 执行算术和逻辑运算
控制单元 解析指令,发出控制信号
寄存器组 保存正在计算的临时数据
程序计数器 PC 保存下一条指令的地址
指令寄存器 IR 保存当前正在执行的指令
内存地址寄存器 MAR 保存要访问的内存地址
内存数据寄存器 MDR 保存从内存读出或准备写入的数据

寄存器和内存的区别非常关键:

对比项 寄存器 内存
位置 CPU 内部 CPU 外部的主存
速度 极快 相对慢
容量 很小 大得多
用途 暂存指令、操作数、计算结果 存储程序和数据

这也是为什么性能优化经常强调减少内存访问、提升缓存命中率。

它是怎么工作的

CPU 执行程序时,通常会不断重复三件事:

  1. 取指令:从内存中读取下一条指令。
  2. 译码:判断这条指令要做什么。
  3. 执行:进行计算、读写寄存器、访问内存或跳转。

更完整地说,现代 CPU 常把一条指令拆成这些阶段:

  1. 取指 Fetch:根据 PC 从内存或缓存读取指令。
  2. 译码 Decode:控制单元解析操作码和操作数。
  3. 执行 Execute:ALU 或其他执行单元完成计算。
  4. 访存 Memory:如果指令需要读写内存,则访问缓存或主存。
  5. 写回 Write Back:把结果写回寄存器或内存。

例如一行简单代码:

const total = price + tax;

在底层会被拆成类似这样的动作:

把 price 读入寄存器
把 tax 读入寄存器
执行加法
把结果写回 total 对应的位置

高级语言隐藏了这些细节,但硬件执行时仍然离不开取指、译码、执行。

流水线为什么重要

如果 CPU 必须等一条指令完整走完取指、译码、执行、访存、写回之后,才开始下一条指令,效率会很低。流水线的思路类似工厂分工:当指令 A 在执行阶段时,指令 B 可以在译码,指令 C 可以在取指。

简化对比:

顺序执行:
指令1: IF -> ID -> EX -> MEM -> WB
指令2:                          IF -> ID -> EX -> MEM -> WB

流水线执行:
指令1: IF -> ID -> EX -> MEM -> WB
指令2:      IF -> ID -> EX -> MEM -> WB
指令3:           IF -> ID -> EX -> MEM -> WB

流水线提升的是吞吐量,不是让单条指令每个阶段都消失。它也会引入冒险问题,例如分支跳转导致后续已经取出的指令可能无效。

开发中的真实场景

你不需要每天设计 CPU,但理解底层会影响很多工程判断:

  • 为什么频繁访问内存通常比访问局部变量慢。
  • 为什么位运算在某些场景下很高效。
  • 为什么并发程序会遇到原子性和可见性问题。
  • 为什么性能优化不能只看代码行数,还要看数据访问方式。

AI Coding 时代怎么用

当 AI 生成性能敏感代码时,你可以追问:

  • 这段代码的热点路径在哪里?
  • 是否存在不必要的内存分配?
  • 是否可以减少重复计算?
  • 这段位运算是否可读,是否值得保留?

不要让 AI 为了「看起来高级」写难懂的底层技巧。大多数业务代码优先可读,只有在有性能证据时才需要底层优化。

常见误区

误区一:以为 CPU 直接理解 JavaScript、Python 或 Java。实际上 CPU 执行的是机器指令,高级语言需要解释器、虚拟机或编译器转换。

误区二:以为二进制只是存储格式。实际上二进制是硬件电路最自然、最稳定的表达方式。

误区三:认为底层知识只属于硬件工程师。软件工程师不必会设计芯片,但理解基本原理能减少很多错误判断。

误区四:认为多核和高主频一定能让程序线性变快。程序能否利用多核,取决于并行结构、锁竞争、I/O 等因素。

小结

计算机的复杂能力来自大量简单开关的组合。晶体管提供开关,逻辑门提供判断,寄存器保存状态,指令驱动 CPU 执行。理解这条链路,会让你更清楚代码最终是在怎样的机器上运行。