本文整理 CPU 内部结构、指令周期、原码/反码/补码,以及 32 位和 64 位体系。

1. 计算机系统的基本组成

计算机系统的基本组成示意图
计算机系统的基本组成示意图
计算机系统的基本组成示意图 2
计算机系统的基本组成示意图 2
从经典冯·诺依曼模型看,计算机系统通常由以下部分组成:
  • 运算器;
  • 控制器;
  • 存储器;
  • 输入设备;
  • 输出设备。
现代实现中,运算器和控制器等集成在 CPU 内;主存储器保存正在运行的程序和数据;I/O 控制器和外设负责输入输出。

2. CPU 内部主要部件

本章从「控制单元(CU)」「算术逻辑单元(ALU)」和「寄存器」等方面说明 CPU 内部主要部件。

2.1 控制单元(CU)

控制单元负责:
  • 获取指令;
  • 对指令进行译码;
  • 产生控制信号;
  • 调度寄存器、执行单元、缓存和访存部件。
现代 CPU 的控制实现可能是硬连线控制、微程序控制或二者结合。

2.2 算术逻辑单元(ALU)

ALU 负责整数算术和逻辑操作,例如:
  • 加减;
  • 位与、位或、异或、取反;
  • 比较;
  • 移位。
浮点运算通常由浮点执行单元负责;现代处理器还包含 SIMD/向量执行单元、地址生成单元等。

2.3 寄存器

寄存器是 CPU 内部高速存储单元。
常见类别:
  • 通用寄存器:保存操作数、中间结果和地址。
  • 程序计数器 PC / 指令指针 IP:保存下一条将要获取的指令地址。
  • 指令寄存器 IR:教学模型中保存当前指令。
  • 状态寄存器 / 标志寄存器:记录零、进位、溢出、符号等状态。
  • 栈指针 SP:指向当前栈顶。
  • 控制寄存器:用于内存管理、特权级和系统控制。

2.4 Cache

Cache 保存近期或高概率再次访问的指令和数据,用来缩小 CPU 与主存之间的速度差距。
常见层级:
Cache 不是简单的“数据和指令仓库”,还涉及缓存行、局部性、替换策略、写策略和一致性协议。

2.5 内部互连和总线

CPU 内部通过数据通路和互连结构连接寄存器、执行单元、缓存等部件。
系统层面常区分:
  • 地址信息;
  • 数据信息;
  • 控制信息。
“数据总线、地址总线、控制总线”是功能上的分类,不应直接当作 CPU 的全部结构组成。

2.6 时钟、流水线和预测

现代 CPU 还常包含:
  • 时钟和时序电路;
  • 指令流水线;
  • 分支预测器;
  • 乱序执行调度器;
  • 重排序缓冲区;
  • 取指、译码和发射单元。
这些结构允许多条指令的不同阶段重叠执行。逻辑上仍可使用“取指—译码—执行”理解单条指令,但物理实现远比顺序模型复杂。

3. CPU 执行指令的基本过程

教学模型通常分为:
  1. 取指;
  1. 译码;
  1. 执行;
  1. 访存(如需要);
  1. 写回;
  1. 更新下一条指令地址。

3.1 取指

  • PC 保存下一条指令地址;
  • CPU 请求对应地址的指令;
  • 指令通过缓存层次或主存进入 CPU;
  • PC 更新为顺序下一地址,或之后被跳转目标覆盖。

3.2 译码

译码单元分析:
  • 操作码;
  • 源操作数;
  • 目标操作数;
  • 寻址方式;
  • 立即数;
  • 是否需要访存或改变控制流。

3.3 执行

根据指令类型:
  • ALU 执行整数运算;
  • 浮点/向量单元执行对应运算;
  • 访存单元计算地址并读写缓存/内存;
  • 分支指令修改控制流;
  • 结果写回寄存器或内存。

3.4 PC 如何递增

PC 的更新步长由指令集和当前指令长度决定,不能直接由 CPU 位宽推断。
正确说法:
  • PC 按指令长度或 ISA 规定的指令宽度更新;
  • x86/x86-64 指令是变长的,一条指令可占不同字节数;
  • AArch64 的常规指令通常为固定 4 字节;
  • 遇到跳转、调用、返回、异常或中断时,PC 会改为目标地址;
  • CPU 是 32 位还是 64 位,不能直接决定每条指令都占 4 或 8 字节。

4. 原码、反码和补码

以下以 8 位有符号整数为例。

4.1 原码

  • 最高位表示符号:0 为正,1 为负;
  • 其余位表示绝对值。
问题:存在 +0-0 两种零。

4.2 反码

  • 正数反码与原码相同;
  • 负数符号位不变,其余位取反。
仍然存在两种零。

4.3 补码

  • 正数补码与原码相同;
  • 负数补码通常可由“对应正数按位取反再加 1”得到。
8 位补码范围:

4.4 为什么使用补码

本节从「零只有一种表示」和「加减法可以统一到加法器」两方面说明为什么使用补码。
4.4.1 零只有一种表示
因此 8 位编码可以覆盖一个额外负数 -128
4.4.2 加减法可以统一到加法器
计算:
可转换为:
丢弃超出 8 位的最高进位,得到 0000 0010,即 2。
更严谨地说,是将减法转换为加上被减数的相反数的补码,而不是笼统地说“加上这个数的补码”。

4.5 溢出

固定宽度补码运算会溢出。
8 位有符号数:
位模式结果为:
按 8 位补码解释为 -128。CPU 通常通过溢出标志等状态帮助软件判断。

5. 32 位和 64 位程序

本章从「32 位与 64 位的含义」「地址空间」和「数据模型」等方面说明 32 位和 64 位程序。

5.1 32 位与 64 位的含义

“32 位 CPU”或“64 位 CPU”并不是只指一个单一参数,常涉及:
  • 通用寄存器宽度;
  • 指令集架构;
  • 地址计算能力;
  • 指针和虚拟地址模型;
  • 操作系统 ABI;
  • 数据通路宽度。
不同架构的具体实现可能不同。

5.2 地址空间

32 位指针理论上可编码:
单个 32 位进程通常只能使用其中一部分,具体划分取决于操作系统。
64 位指针理论上可编码 16 EiB,但现代处理器和操作系统通常只实现较少的有效虚拟地址位数,例如常见的 48 位或 57 位地址形式。不能把“64 位”直接等同于现实中可用 16 EiB 内存。

5.3 数据模型

常见模型:
  • ILP32intlong、指针通常为 32 位;
  • LP64long 和指针为 64 位,int 为 32 位,常见于 64 位 Linux/macOS;
  • LLP64long long 和指针为 64 位,long 仍为 32 位,常见于 64 位 Windows。
因此跨平台代码不能假设:
应使用 sizeof、固定宽度整数类型和 uintptr_t 等进行判断。

5.4 指令集和寄存器

以 x86 为例,x86-64:
  • 将部分通用寄存器扩展到 64 位;
  • 增加了更多通用寄存器;
  • 定义了新的调用约定和系统编程环境;
  • 提供 64 位地址和整数运算能力。
这些结论不能无条件推广到所有 CPU 架构。

6. 操作系统与程序兼容性

本章从「64 位 CPU 能否安装 32 位操作系统」「32 位 CPU 能否运行 64 位操作系统」和「64 位操作系统能否运行 32 位程序」等方面说明操作系统与程序兼容性。

6.1 64 位 CPU 能否安装 32 位操作系统

取决于该 CPU 是否保留对应兼容执行模式,以及设备是否仍有合适驱动。
传统 x86-64 处理器通常可以运行 32 位 x86 操作系统,但此时操作系统运行在 32 位模式,不是“64 位长模式下的兼容子模式”。
32 位系统仍可能通过 PAE 使用超过 4 GiB 的物理内存,但单个普通 32 位进程的虚拟地址空间仍受到 32 位地址范围限制。

6.2 32 位 CPU 能否运行 64 位操作系统

不能直接运行要求 64 位指令集和执行模式的操作系统内核,因为 CPU 缺少对应指令、寄存器和系统机制。

6.3 64 位操作系统能否运行 32 位程序

可能可以,但取决于:
  • 操作系统是否提供兼容层;
  • 是否安装 32 位运行库;
  • CPU 是否支持相应执行模式;
  • 程序是否依赖已经移除的驱动或组件。
64 位内核通常要求 64 位内核驱动,不能直接加载 32 位内核驱动。

6.4 64 位一定更快吗

不一定。
可能更快的场景:
  • 需要超过 4 GiB 地址空间;
  • 大量 64 位整数运算;
  • 得益于更多寄存器和更好的调用约定;
  • 数据库、虚拟机、科学计算、大型内容生产。
可能没有优势或产生额外成本:
  • 指针从 4 字节变为 8 字节,使数据结构变大;
  • 缓存中能容纳的对象减少;
  • 内存带宽和缓存压力增加;
  • 程序主要受磁盘、网络或 GPU 限制;
  • 只处理小整数和小规模数据。
性能最终取决于程序、编译器、ABI、微架构、内存行为和工作负载。

7. 总结

CPU 通过取指、译码和执行不断推进程序;补码让有符号整数的加减法可以复用同一套二进制运算规则。32 位与 64 位不仅影响寄存器和地址空间,也受到指令集、ABI、操作系统与应用依赖共同约束。
分析具体程序时,应明确讨论的是数据宽度、地址宽度、进程架构还是操作系统兼容层,避免把“64 位”简单等同于“必然更快”。

8. 参考资料