Files
test-repo/docs/zh-cn/appendix/1-computer-fundamentals/computer-organization.md
T
sanbuphy f44c842fe7 feat(docs): update computer fundamentals content and demos
- Refactor frontend framework demo descriptions for clarity
- Remove interactive features from triad and field map demos
- Add new computer organization and DSL documentation links
- Split type systems and compilers into separate pages
- Enhance power-on-to-web article with relay race analogy
- Add new interactive demos for type systems and compilation
- Improve visual presentation of boot process and hardware flow
- Introduce new Vibe Coding flow demo component
2026-02-25 01:38:27 +08:00

486 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 计算机组成原理
::: tip 前言
**从晶体管到 CPU 后,计算机如何组成完整系统?** 上一章我们从晶体管出发,构建了加法器、寄存器、运算单元,最终拼出了 CPU 核心。但仅有 CPU 是不够的——它需要和内存、I/O 设备协同工作,需要总线连接各个部件,需要指令系统来驱动。这一章我们将从 CPU 的内部视角转向整个计算机系统的视角,深入理解冯诺依曼架构、指令系统、存储层次、总线与 I/O 的专业原理。
:::
**这篇文章会带你学什么?**
学完这章后,你将获得:
- **系统视角**:理解 CPU、内存、I/O 是如何协同工作的不再是孤立的硬件爱好者
- **硬件专业术语**:掌握指令周期、流水线、CPI、缓存命中率等硬核概念
- **性能思维**:理解计算机组成中的瓶颈与优化手段
- **后续学习基础**:为操作系统、体系结构、嵌入式开发打下专业基础
| 章节 | 内容 | 核心概念 |
|-----|------|---------|
| **第 1 章** | 冯诺依曼架构 | 存储程序、五大组成部件、数据通路 |
| **第 2 章** | 指令系统 | 指令格式、寻址方式、CISC vs RISC |
| **第 3 章** | CPU 控制器 | 控制单元、微操作、指令周期 |
| **第 4 章** | 存储体系 | 缓存、主存、虚拟内存、分页机制 |
| **第 5 章** | 总线与 I/O | 总线仲裁、DMA、中断机制 |
---
## 0. 全景图:计算机硬件系统
在上一章"从晶体管到 CPU"中,我们已经理解了 CPU 内部是如何工作的——从取指、译码、执行到写回。但 CPU 本身只是一个执行单元,要让计算机真正"能用",还需要一系列外围部件的配合。
<CpuArchitectureDemo />
::: tip 逐层解构:计算机硬件系统
- **第一层:CPU 核心**
负责指令执行,包括控制单元(发出控制信号)和运算单元(执行算术逻辑运算)
- **第二层:寄存器组**
CPU 内部的高速存储单元,包括通用寄存器和专用寄存器(PC、IR、MAR、MDR 等)
- **第三层:主存储器**
用于存放程序和数据的内存,CPU 通过地址总线和数据总线访问
- **第四层:I/O 设备**
输入输出设备通过 I/O 控制器与系统总线相连
- **第五层:系统总线**
连接 CPU、内存、I/O 的数据通道,包括地址总线、数据总线、控制总线
:::
---
## 1. 冯诺依曼架构:现代计算机的"宪法"
### 1.1 存储程序原理
1945 年,数学家约翰·冯·诺依曼(John von Neumann)提出了划时代的**存储程序(Stored-program)**架构思想。这一思想奠定了现代计算机的基础。
::: tip 核心概念
**存储程序**:程序本身作为一种特殊的数据,和普通数据一样存储在内存中。CPU 可以像读写数据一样读取并执行存储在内存中的程序指令。
:::
这意味着:
- **早期计算机**:程序是固定布线实现的,改变程序需要重新焊接电路
- **冯诺依曼架构**:程序存储在内存中,改变程序只需修改内存内容
### 1.2 五大组成部件
冯诺依曼架构将计算机划分为五个核心组成部分:
<RegisterDemo />
| 部件 | 英文 | 功能 | 主要组成 |
|------|------|------|---------|
| **运算器** | ALU (Arithmetic Logic Unit) | 执行算术和逻辑运算 | 加法器、移位器、比较器 |
| **控制器** | CU (Control Unit) | 指挥协调各部件工作 | 指令寄存器、译码器、时序发生器 |
| **存储器** | Memory | 存储程序和数据 | 内存地址寄存器(MAR)、内存数据寄存器(MDR) |
| **输入设备** | Input | 信息输入 | 键盘、鼠标、扫描仪 |
| **输出设备** | Output | 信息输出 | 显示器、打印机 |
### 1.3 数据通路
**数据通路(Data Path)**是数据在各个功能部件之间流动的路径。在 CPU 内部,数据通路连接了:
- 寄存器组
- 算术逻辑单元(ALU)
- 内存数据寄存器(MDR)
数据通路的宽度(一次能传输多少位)直接影响了计算机的性能。
### 1.4 冯诺依曼瓶颈
冯诺依曼架构有一个著名的**性能瓶颈**:
> CPU 与内存之间的数据传输速度,远低于 CPU 的处理速度。
这导致 CPU 经常处于"等待数据"的空闲状态。现代计算机的很多优化技术都是围绕这个问题展开的:
| 优化技术 | 原理 |
|---------|------|
| **缓存(Cache)** | 在 CPU 附近放置小容量高速存储 |
| **指令流水线** | 让多条指令同时处于不同阶段 |
| **超标量** | 同一时钟周期发射多条指令 |
| **多核并行** | 多个 CPU 核心分担计算任务 |
---
## 2. 指令系统:CPU 与软件的接口
上一节我们知道了冯诺依曼架构的核心思想:**程序和数据一样存储在内存中**。但这引出了一个关键问题——存在内存里的"程序"到底长什么样?CPU 怎么读懂它?
答案就是**指令系统(Instruction Set Architecture, ISA**。如果把 CPU 比作一个服务,那指令系统就是它的 **API 文档**——它定义了 CPU 能听懂的所有命令、每条命令的格式、以及命令能操作的数据范围。你写的每一行代码,最终都会被编译器翻译成这套"API"的调用序列。
### 2.1 从代码到指令:一行代码的翻译之旅
我们先建立一个全局认知:你在编辑器里写的代码,和 CPU 实际执行的东西,中间隔了好几层翻译。
<CodeToInstructionDemo />
这个翻译链路是理解指令系统的关键:
| 层次 | 内容 | 谁能看懂 |
|------|------|---------|
| 高级语言 | `int a = 10 + 5;` | 人类 |
| 汇编语言 | `MOV R1, #10` / `ADD R3, R1, R2` | 人类(需要训练) |
| 机器码 | `0001 0001 0000 1010` | CPU |
::: tip 为什么要理解这个链路?
- 看到编译报错时,你知道错误发生在"高级语言→汇编"这一步
- 看到运行时崩溃时,你知道问题出在 CPU 执行指令的阶段
- 理解性能优化时,你知道编译器在"翻译"过程中做了哪些优化
- 选择 CPU 架构时(x86 vs ARM),你知道差异在于"指令集 API"不同
:::
### 2.2 一条指令长什么样?
知道了代码会被翻译成指令,下一个问题是:**一条指令的内部结构是什么?**
每条机器指令本质上就是一串二进制数字,但它有严格的内部格式。最核心的两个部分:
- **操作码(Opcode)**:告诉 CPU「做什么」——是加法?跳转?还是读内存?
- **操作数(Operand)**:告诉 CPU「对谁做」——哪个寄存器?哪个内存地址?什么常数?
就像一句话有「动词 + 宾语」的结构,指令也有「操作 + 对象」的结构:
```
指令: ADD R3, R1, R2
─── ──────────
操作码 操作数
(做加法) (R3 = R1 + R2)
```
根据操作数的数量,指令格式从简单到复杂分为四种:
<InstructionFormatDemo />
| 格式 | 结构 | 例子 | 使用场景 |
|------|------|------|---------|
| 零地址 | 只有操作码 | `RET`(返回) | 堆栈计算机,操作数隐含在栈顶 |
| 一地址 | 操作码 + 1个地址 | `INC R1`R1加1 | 单操作数运算 |
| 二地址 | 操作码 + 2个地址 | `MOV R1, R2` | 最常用,数据传送和运算 |
| 三地址 | 操作码 + 3个地址 | `ADD R3, R1, R2` | 不破坏源操作数 |
::: tip 为什么有这么多格式?
这是**空间和灵活性的权衡**。零地址指令最短(省内存),但需要额外的栈操作;三地址指令最灵活(不破坏源数据),但占用更多位数。不同 CPU 架构会选择不同的指令格式组合。
:::
### 2.3 CPU 怎么找到数据?——寻址方式
指令告诉 CPU「做加法」,但加法的两个数在哪里?可能直接写在指令里,可能在寄存器里,也可能在内存的某个地址。**寻址方式**就是告诉 CPU「去哪里找操作数」的规则。
用生活中「找人」来类比:
| 寻址方式 | 类比 | 指令示例 | 说明 |
|---------|------|---------|------|
| **立即数寻址** | 人就站在你面前 | `MOV R1, #100` | 数据直接写在指令里,最快 |
| **寄存器寻址** | 打内线电话找同事 | `MOV R1, R2` | 数据在 CPU 内部的寄存器里,很快 |
| **直接寻址** | 知道门牌号,直接上门 | `MOV R1, [0x1000]` | 指令里写了内存地址 |
| **间接寻址** | 问前台「张三在哪个房间」 | `MOV R1, [R2]` | 寄存器里存的是地址,要多查一次 |
| **变址寻址** | 「3号楼 + 5层」算出房间 | `MOV R1, [R2+10]` | 基地址 + 偏移量,用于数组访问 |
<AddressingModeDemo />
::: tip 为什么需要这么多寻址方式?
不同场景需要不同的「找数据」策略:
- **常量赋值**`x = 100`)→ 立即数寻址,数据就在指令里
- **变量运算**`a + b`)→ 寄存器寻址,数据已经加载到寄存器
- **数组访问**`arr[i]`)→ 变址寻址,基地址 + 下标偏移
- **指针操作**`*ptr`)→ 间接寻址,寄存器里存的是地址
你写 `arr[i]` 时不会想到寻址方式,但编译器会自动选择最合适的方式。
:::
### 2.4 CPU 的能力清单——指令分类
现在我们知道了指令的格式和寻址方式,最后一个问题:**CPU 到底能做哪些事?**
所有指令可以归为六大类,它们覆盖了计算机能做的一切操作:
| 类型 | 做什么 | 代表指令 | 对应你写的代码 |
|------|-------|---------|-------------|
| **数据传送** | 搬运数据 | MOV, LOAD, STORE | `let x = y`、函数传参 |
| **算术运算** | 加减乘除 | ADD, SUB, MUL, DIV | `a + b``count++` |
| **逻辑运算** | 位操作 | AND, OR, NOT, XOR | `flags & 0xFF`、权限判断 |
| **移位操作** | 左移右移 | SHL, SHR | `x << 2`(等价于乘4 |
| **控制转移** | 跳转和调用 | JMP, CALL, RET | `if``for`、函数调用 |
| **输入输出** | 与外设通信 | IN, OUT | 读键盘、写屏幕 |
::: tip 一个关键洞察
你写的所有代码——不管多复杂的业务逻辑、多炫酷的 UI 动画——最终都会被拆解成这六类基本操作的组合。CPU 的"智能"不在于它能做多复杂的事,而在于它能以每秒几十亿次的速度执行这些简单操作。
:::
### 2.5 两种设计哲学:CISC vs RISC
指令系统的设计有一个根本性的分歧:**是让每条指令尽可能强大,还是让每条指令尽可能简单?**
这个分歧产生了两大阵营,直接影响了你今天用的每一台设备:
<CISCvsRISCDemo />
用一个类比来理解:
- **CISC 像瑞士军刀**:一把刀集成了剪刀、开瓶器、螺丝刀……功能多但每个不一定最好用
- **RISC 像专业工具套装**:每个工具只做一件事,但做得又快又好
::: tip 为什么你的手机用 ARM、电脑用 x86?
- **x86 (CISC)** 统治了 PC 和服务器市场 40 年,积累了庞大的软件生态。换架构意味着所有软件都要重新编译
- **ARM (RISC)** 凭借低功耗优势统治了移动设备。手机电池小,每一毫瓦都很珍贵
- **Apple Silicon** 证明了 RISC 也能做到高性能——M 系列芯片在性能和功耗上同时超越了 x86 对手
- **RISC-V** 是开源的 RISC 架构,正在 IoT、教育、AI 芯片领域快速崛起
:::
---
> **小结**:指令系统是连接软件和硬件的桥梁。你写的代码通过编译器翻译成指令,指令通过操作码和操作数告诉 CPU 做什么、对谁做,寻址方式决定了数据从哪里来。不同的指令集设计(CISC/RISC)决定了 CPU 的性能特征和适用场景。
>
> 现在我们知道了指令的「静态结构」——它长什么样、有哪些类型。下一个问题是:**CPU 内部是怎么一步步执行这些指令的?** 这就是控制器的工作。
---
## 3. 控制器:CPU 的"指挥中心"
### 3.1 控制器的组成
控制器是 CPU 的"大脑",负责协调各部件按指令要求工作:
<ControllerDemo />
| 组件 | 功能 |
|------|------|
| **程序计数器 (PC)** | 存放下一条指令的地址 |
| **指令寄存器 (IR)** | 存放当前正在执行的指令 |
| **指令译码器** | 解析指令的操作码和操作数 |
| **时序发生器** | 产生节拍信号,控制各部件时序 |
| **微操作序列生成器** | 产生执行指令所需的一系列控制信号 |
<PSWFlagDemo />
### 3.2 指令周期
CPU 执行一条指令需要经历一个完整的**指令周期**,通常包括:
1. **取指周期 (Fetch)**: 从内存读取指令到 IR
2. **译码周期 (Decode)**: 解析指令含义
3. **执行周期 (Execute)**: 执行操作
4. **访存周期 (Memory Access)**: 如果需要访存,访问内存
5. **写回周期 (Write Back)**: 把结果写回寄存器或内存
### 3.3 微操作
**微操作**是控制信号驱动下的最基本操作。例如,"取指"这个阶段可以分解为以下微操作:
| 节拍 | 微操作 | 控制信号 |
|------|--------|---------|
| T1 | PC → MAR | PCout, MARin |
| T2 | MEM → MDR | MEMout, MDRin |
| T3 | MDR → IR | MDRout, IRin |
| T4 | PC + 1 → PC | PC+1, PCin |
### 3.4 硬布线 vs 微程序控制器
| 特性 | 硬布线控制器 | 微程序控制器 |
|------|------------|-------------|
| **实现方式** | 组合逻辑电路 | 微指令序列(固件) |
| **速度** | 快 | 稍慢 |
| **设计难度** | 复杂 | 较简单 |
| **灵活性** | 差(改动需重新设计电路) | 好(修改微程序即可) |
| **典型应用** | RISC 处理器 | CISC 处理器早期 |
---
## 4. 存储体系:为什么需要缓存?
### 4.1 存储层次结构
计算机的存储设备构成了一个金字塔结构:
<StorageHierarchyDemo />
| 层次 | 存储类型 | 访问时间 | 典型容量 | 位置 |
|------|---------|---------|---------|------|
| **寄存器** | SRAM | <1ns | 几 KB | CPU 内部 |
| **L1 缓存** | SRAM | ~1ns | 32-64KB | CPU 核心附近 |
| **L2 缓存** | SRAM | ~3-10ns | 256KB-1MB | CPU 芯片内 |
| **L3 缓存** | SRAM | ~10-20ns | 2-16MB | CPU 芯片内/共享 |
| **主存(内存)** | DRAM | ~50-100ns | 8-64GB | 主板上 |
| **SSD** | Flash | ~10-100μs | 256GB-2TB | 主板上 |
| **HDD** | 磁盘 | ~5-10ms | 1-10TB | 机箱内 |
::: tip 速度差异的比喻
如果把 CPU 访问 L1 缓存比作**从桌上拿一张纸**:
- 访问内存 → 坐电梯去楼下便利店买纸
- 访问 SSD → 开车去另一个城市买纸
- 访问 HDD → 坐飞机去另一个国家买纸
速度差异可达**上百万倍**
:::
### 4.2 缓存原理
**缓存(Cache)** 是位于 CPU 和内存之间的快速存储,其核心思想基于两个局部性原理:
::: tip 局部性原理
- **时间局部性**:如果一个数据刚被访问,它很可能很快又被访问
- **空间局部性**:如果一个数据被访问,它附近的数据很可能也被访问
:::
#### 缓存的工作方式
1. **命中(Hit)**CPU 要的数据在缓存中,直接读取
2. **缺失(Miss)**:数据不在缓存中,需要从内存加载
```
命中率 = 命中次数 / 总访问次数
平均访问时间 = 命中率 × 缓存时间 + (1-命中率) × 内存时间
```
<CacheDemo />
### 4.3 缓存映射方式
| 方式 | 原理 | 优点 | 缺点 |
|------|------|------|------|
| **直接映射** | 每个内存块只能放到一个固定位置 | 简单快速 | 冲突率高 |
| **组相联** | 每个内存块可以放到 N 个位置(N路) | 平衡速度与命中率 | 实现复杂 |
| **全相联** | 任意位置 | 最低冲突率 | 实现困难(需要比较所有标签) |
### 4.4 虚拟内存
**虚拟内存**是操作系统提供的重要抽象:
- 每个进程都认为自己拥有完整的虚拟地址空间
- 操作系统负责把虚拟地址翻译成物理地址
- 不常用的页面可以换出到磁盘(交换空间)
::: tip 虚拟内存的比喻
把虚拟内存想象成**酒店管理房间**:
- 你(进程)以为整栋楼都是你的
- 实际上酒店(OS)只给你分配当前需要的房间
- 不住的房间会被"换出"到仓库(磁盘)
- 需要的房间可以随时"换入"
:::
---
## 5. 总线与 I/O:计算机的"血管"
### 5.1 系统总线
**总线(Bus)** 是连接计算机各部件的数据通道:
<BusSystemDemo />
| 总线类型 | 功能 | 方向 | 典型宽度 |
|---------|------|------|---------|
| **地址总线** | 传送内存地址 | 单向(CPU→内存) | 32位/64位 |
| **数据总线** | 传送数据 | 双向 | 32位/64位 |
| **控制总线** | 传送控制信号 | 双向 | 多个信号线 |
### 5.2 总线仲裁
当多个设备同时请求使用总线时,需要**仲裁**机制决定谁先使用:
| 仲裁方式 | 说明 |
|---------|------|
| **集中仲裁** | 中央仲裁器统一决定 |
| **分布式仲裁** | 各设备自行协商 |
### 5.3 I/O 设备访问方式
| 方式 | 原理 | 优点 | 缺点 |
|------|------|------|------|
| **程序查询** | CPU 轮询检查 I/O 状态 | 简单 | CPU 利用率低 |
| **中断方式** | I/O 完成后主动通知 CPU | CPU 可并行工作 | 中断处理有开销 |
| **DMA** | I/O 设备直接访问内存 | CPU 完全不参与 | 需要 DMA 控制器 |
<IOMethodDemo />
### 5.4 DMA 原理
**DMA (Direct Memory Access,直接内存访问)** 允许 I/O 设备直接与内存交换数据:
<NetworkOverviewDemo />
- **无 DMA**:CPU 全程参与数据传送,CPU 无法做其他事
- **有 DMA**CPU 告诉 DMA 控制器"从哪里传到哪里、传多少",然后去执行其他任务,DMA 完成后通知 CPU
::: tip DMA 的比喻
这就像**点外卖**
- **没有 DMA**:你亲自去超市买菜、回家、洗菜、炒菜(全过程参与)
- **有 DMA**:你打电话下单,外卖小哥直接送到厨房(别人帮你搞定,你只需要最后"收货")
:::
### 5.5 中断机制
**中断**是计算机系统中非常重要的机制:
1. I/O 设备完成操作后,向 CPU 发送**中断请求**
2. CPU 正在执行指令,完成当前指令后响应中断
3. CPU 保存当前状态,跳转到中断处理程序
4. 处理完成后,恢复状态继续执行
---
## 6. CPU 性能优化:流水线技术
### 6.1 指令流水线
**指令流水线**是一种让 CPU 效率最大化的并行技术:
<PipelineDemo />
#### 流水线的工作原理
```
顺序执行(5条指令,15个周期):
指令1: IF→ID→EX→MEM→WB
指令2: IF→ID→EX→MEM→WB
指令3: IF→ID→EX→MEM→WB
...
流水线执行(5条指令,9个周期):
指令1: IF→ID→EX→MEM→WB
指令2: IF→ID→EX→MEM→WB
指令3: IF→ID→EX→MEM→WB
...
```
理想情况下,N 条指令的 CPI(每指令周期数) ≈ 1
### 6.2 流水线冒险
流水线虽然能提高性能,但也会带来**冒险(Hazard)** 问题:
| 类型 | 原因 | 解决方案 |
|------|------|---------|
| **结构冒险** | 硬件资源冲突 | 增加硬件/错开执行 |
| **数据冒险** | 后面的指令需要前面的结果 | 数据转发/气泡/调度 |
| **控制冒险** | 跳转指令改变执行流 | 延迟槽/分支预测 |
---
## 7. 总结:计算机是如何"跑起来"的?
让我们用专业术语串联整个流程:
> **程序启动后,操作系统将可执行文件从磁盘加载到内存。CPU 的取指单元(IF)通过地址总线从内存读取指令到指令寄存器(IR)。控制器对指令进行译码(ID),识别出操作类型后产生相应的控制信号。运算单元(EX)执行算术逻辑运算,如果需要访存则通过数据总线访问内存(MEM),最后结果写回(WB)到寄存器或内存。整个过程由时钟驱动,控制器发出的微操作序列协调各部件有序工作。**
---
## 延伸阅读
| 主题 | 推荐深入学习内容 |
|------|-----------------|
| 计算机体系结构 | 《计算机组成与设计:硬件/软件接口》- Patterson & Hennessy |
| CPU 微架构 | 《深入理解计算机系统》- Bryant & O'Hallaron |
| 指令集架构 | ARMv8 架构手册、Intel x64 手册 |
| 缓存原理 | 缓存一致性协议(MESI)、缓存写策略 |
| 操作系统 | 后续章节《操作系统》 |
---
## 下一步
现在你已经掌握了计算机组成原理的专业知识。接下来可以继续学习:
- **[操作系统](./operating-systems.md)**:了解程序是如何在操作系统上运行的,进程、线程、内存管理是如何实现的
- **[数据的编码、存储与传输](./data-encoding-storage.md)**:深入理解数据在计算机中的表示方式