# 📖 计算机组成原理（Computer Organization）—— 408考研完全笔记

## 相关笔记

- [[DS]]：缓存、存储层次和地址访问模式会改变数据结构与算法的实际运行成本。
- [[OS]]：中断、异常、虚拟内存、I/O 与操作系统的抽象和资源管理直接相连。
- [[CN]]：网卡、DMA、总线、中断和数据传输路径是网络协议落到主机硬件的基础。

> **编写说明**：本笔记严格依据全国硕士研究生招生考试计算机学科专业基础（科目代码：408/11408）考试大纲编写，结合王道考研教材体系与历年真题（2009—2025），力求概念严谨、解释通俗、解题实用。
>
> **考试概况**：408统考满分150分，考试时间180分钟（3小时）。其中数据结构约占45分（30%），**计算机组成原理约占45分（30%）**，操作系统约占35分（约23%），计算机网络约占25分（约17%）。题型包括：**单项选择题（80分，40题×2分）** 和 **综合应用题（70分，7题）**。计算机组成原理通常占约11道选择题（22分）和2道大题（约23分）。
>
> **各章分值估计**：第2章（数据表示与运算）+ 第3章（存储系统）+ 第5章（CPU）≈ 75%的组原分值。第6章（总线）在2025大纲中大幅删减（仲裁、标准已删），仅占约3%。

---

# 第一章 计算机系统概述

> **本章考情**：选择题为主，每年约1~2题。重点：冯·诺依曼体系结构特点、各部件功能、性能指标计算（MIPS/CPI/CPU执行时间）、计算机层次结构。

## 1.1 计算机发展历程（了解即可）

> ⚠️ **注意**：2025年408大纲已删除"计算机发展历程"，但了解发展脉络有助于理解为什么计算机要这样设计。

| 代 | 年代 | 逻辑元件 | 特点 |
|---|---|---|---|
| 第一代 | 1946-1957 | 电子管 | 机器语言/汇编语言编程，体积庞大 |
| 第二代 | 1958-1964 | 晶体管 | 高级语言出现（FORTRAN），体积缩小 |
| 第三代 | 1965-1971 | 中小规模集成电路 | 操作系统出现，半导体存储器 |
| 第四代 | 1972至今 | 大规模/超大规模集成电路 | 微处理器诞生，个人计算机普及 |

> 🗣️ **大白话**：计算机发展的趋势就是——元件越来越小、速度越来越快、价格越来越便宜。从占满一个房间到放进口袋里。

---

## 1.2 计算机硬件的基本组成

### 一、冯·诺依曼计算机

![冯诺依曼结构](图表/CO/CO-01_VonNeumann.png)

**冯·诺依曼体系结构**是现代计算机的基础，1945年由冯·诺依曼（John von Neumann）提出。

**冯·诺依曼计算机的五大特点**：

| 序号 | 特点 | 说明 |
|---|---|---|
| 1 | 由**运算器、控制器、存储器、输入设备、输出设备**五大部件组成 | 五大部件缺一不可 |
| 2 | 指令和数据以**同等地位**存放在存储器中，可按地址访问 | 这是"存储程序"思想的核心 |
| 3 | 指令和数据均用**二进制**表示 | 计算机只认识0和1 |
| 4 | 指令由**操作码和地址码**组成 | 操作码说"做什么"，地址码说"对谁做" |
| 5 | **存储程序**原理：将程序事先存入主存储器中，然后让计算机自动逐条取出指令并执行 | 这是冯·诺依曼机最核心的思想 |

> 🗣️ **大白话**：冯·诺依曼体系的核心就一句话——**"把程序和数据都存在内存里，然后让计算机自己一条条读指令、执行指令"**。在此之前，"编程"要手动拔插电线，改一下程序就要重新接线，累死人。冯·诺依曼说："何必呢？把指令也当成数据存起来不就好了？"——这就是"存储程序"思想。

> ⚠️ **2009年真题考点**：冯·诺依曼计算机中，指令和数据都以二进制的形式存放在存储器中，CPU如何区分它们？
> **答**：依据**指令周期的不同阶段**——在**取指阶段**（取指周期），从存储器取出的是**指令**；在**执行阶段**（执行周期），从存储器取出的是**数据**。也就是说，区分指令和数据靠的是**时间**（时序），而不是靠内容本身。

### 二、冯·诺依曼计算机的五大部件

```
                    ┌─────────────┐
    输入设备  ─────> │    存储器    │ ──────> 输出设备
                    │  (主存储器)  │
                    └───┬───┬─────┘
                     数据↕   ↕数据
                    ┌───┴───┴─────┐
                    │    运算器    |
                    │    (ALU)    │
                    └───────┬─────┘
                     控制信号↕
                    ┌───────┴──────┐
                    │    控制器     │
                    │    (CU)      │
                    └──────────────┘
```

**各部件的核心寄存器和功能**：

| 部件 | 核心组件 | 功能 |
|---|---|---|
| **运算器** | ALU（算术逻辑单元）、ACC（累加器）、MQ（乘商寄存器）、X（通用操作数寄存器）、PSW（程序状态字） | 执行算术运算和逻辑运算 |
| **控制器** | CU（控制单元）、IR（指令寄存器）、PC（程序计数器） | 协调控制各部件工作 |
| **存储器** | MAR（存储器地址寄存器）、MDR（存储器数据寄存器）、存储体 | 存放程序和数据 |
| **输入设备** | 键盘、鼠标、扫描仪等 | 将外部信息转换为计算机可识别的形式 |
| **输出设备** | 显示器、打印机、音箱等 | 将计算结果转换为人或其他设备可使用的形式 |

**关键寄存器详解**：

| 寄存器 | 全称 | 功能 | 位数 |
|---|---|---|---|
| **PC** | Program Counter（程序计数器） | 存放**下一条**待执行指令的地址，具有自动加1功能 | 与MAR位数相同 |
| **IR** | Instruction Register（指令寄存器） | 存放**当前**正在执行的指令 | 与MDR位数相同 |
| **MAR** | Memory Address Register | 存放要访问的存储单元的**地址** | 位数决定最大寻址空间 |
| **MDR** | Memory Data Register | 存放从存储器读出或要写入存储器的**数据** | 位数=存储字长 |
| **ACC** | Accumulator（累加器） | 运算结果的暂存，也作为运算的一个输入 | 与机器字长相同 |
| **PSW** | Program Status Word | 存放条件码（OF/SF/ZF/CF等标志位） | — |

> 🗣️ **大白话**：
> - **PC**就像你读书时用手指着"下一行要读的地方"，你读完一行，手指自动往下移。
> - **IR**就像你正在朗读的那一行文字。
> - **MAR**就像你告诉图书管理员"我要第几本书"。
> - **MDR**就像管理员从书架上取下来放到柜台上的那本书。

> ⚠️ **易错点**：MAR和MDR在逻辑上属于**主存**，但在现代计算机中，它们通常被集成到**CPU芯片**内部。**对程序员不可见**（程序员不能直接操作MAR、MDR、IR）。PC对汇编程序员**可见**（可以通过JMP等指令修改PC）。
>
> 📝 **2010年真题**：下列寄存器中，汇编语言程序员可见的是？ → **PC（程序计数器）**。MAR、MDR、IR都是CPU内部工作寄存器，对程序员不可见。

### 三、现代计算机的结构

现代计算机以**CPU（中央处理器）**和**主存储器**为核心：

```
CPU = 运算器 + 控制器
主机 = CPU + 主存储器
```

> ⚠️ **重要区分**：
> - **冯·诺依曼机**以**运算器**为中心（所有数据都经过运算器中转）
> - **现代计算机**以**存储器**为中心（运算器和控制器合成CPU，I/O设备可直接与存储器交换数据，不必经过运算器）

---

## 1.3 计算机的工作过程

### 一、存储程序的工作方式

计算机工作的基本流程：**取指令 → 分析指令 → 执行指令 → 再取下一条指令...**循环往复，直到遇到停机指令。

**详细过程**：

```
① (PC) → MAR         // 将PC中的指令地址送到MAR
② M(MAR) → MDR       // 根据MAR中的地址从主存中读出指令，送到MDR
③ (MDR) → IR         // 将指令从MDR送到IR中保存
④ OP(IR) → CU        // 将指令的操作码部分送到CU译码
⑤ Ad(IR) → MAR       // 将指令的地址码部分送到MAR（取操作数）
⑥ M(MAR) → MDR       // 从主存中读出操作数
⑦ (MDR) → ACC        // 操作数送ACC，执行运算
⑧ (PC) + 1 → PC      // PC自动加1，指向下一条指令
```

> 🗣️ **大白话**：计算机工作就像一个特别死板的厨师——
> 1. 先看菜谱的第几步（PC告诉它看哪一步）
> 2. 翻开菜谱读这一步的内容（取指令）
> 3. 理解这一步要干什么（译码）
> 4. 照着做（执行——比如"切5块土豆"就是"取出5块土豆并切"）
> 5. 自动看下一步（PC+1）
> 6. 不断重复，直到菜谱说"出锅"（停机指令）

> ⚠️ **注意**：步骤⑧ `(PC)+1→PC` 在取指的同时就完成了（与步骤②同时进行），而不是执行完指令才加1。这一点在相对寻址的计算中至关重要！

---

## 1.4 计算机系统的层次结构

### 一、计算机系统 = 硬件 + 软件

```
                    ┌──────────────────┐
                    │   应用程序        │  ← 最终用户
                    ├──────────────────┤
                    │   高级语言        │  ← 编译程序翻译
                    ├──────────────────┤
                    │   汇编语言        │  ← 汇编程序翻译
                    ├──────────────────┤
                    │   操作系统        │  ← 管理硬件资源
                    ├──────────────────┤
                    │   指令集架构(ISA) │  ← 软硬件交界面
                    ├──────────────────┤
                    │   微程序机器       │  ← 硬件层
                    ├──────────────────┤
                    │   数字逻辑电路     │  ← 最底层
                    └──────────────────┘
```

**ISA（Instruction Set Architecture，指令集体系结构）**：是软件和硬件之间的界面。ISA规定了：
- 指令格式、指令类型、操作类型
- 操作数的类型、存取方式
- 寄存器的种类和数量
- 数据类型、寻址方式
- 中断机制等

> 🗣️ **大白话**：ISA就像"约定好的暗号"——硬件团队和软件团队各干各的，但双方约定好：你发什么暗号（指令），我就做什么动作。只要暗号不变，硬件随便换（比如不同厂家的x86 CPU），软件照样能跑。

> 📝 **2024年真题**：ISA规定了以下哪个？ → **定长指令字**。ISA规定了指令格式、寻址方式、寄存器等，不规定具体电路实现（如阵列乘法器、微程序控制器、单总线数据通路）。

### 二、编译程序与解释程序

| 翻译方式 | 工作方式 | 特点 |
|---|---|---|
| **编译程序** | 将高级语言源程序**整体**翻译为机器语言目标程序，然后执行 | 执行时不需要源程序，速度快 |
| **解释程序** | 逐条翻译、逐条执行 | 不产生目标程序，每次运行都需要源程序，速度慢 |

> 🗣️ **大白话**：编译就像把整本英文小说翻译成中文再看；解释就像请个翻译坐旁边，他读一句英文就给你翻译一句。

### 三、指令、微指令、微操作的层次关系
![微操作时序图](图表/CO/CO-13_MicroOps.png)


| 概念 | 层级 | 说明 |
|---|---|---|
| **机器指令** | 最高层 | CPU能直接识别并执行的指令（如ADD、MOV） |
| **微程序** | 中间层 | 一条机器指令对应一个微程序 |
| **微指令** | — | 微程序中的每一步，一条微指令可以完成一个或多个微操作 |
| **微操作** | 最底层 | 最基本的不可再分的操作（如 PC→MAR） |

> 📝 **2024年真题**：CPU能直接理解并执行的是？ → **微指令和机器指令**（选B）。伪指令是汇编语言层面的，汇编指令需要汇编器翻译。

---

## 1.5 计算机的性能指标

### 一、CPU性能指标

| 指标 | 定义 | 公式 |
|---|---|---|
| **CPU主频（时钟频率）** | CPU内部时钟的振荡频率 | $f = \frac{1}{T}$（T为时钟周期） |
| **CPI** | Clock cycles Per Instruction，执行每条指令平均所需的时钟周期数 | — |
| **IPC** | Instructions Per Clock cycle，每个时钟周期执行的指令数 | $IPC = \frac{1}{CPI}$ |
| **MIPS** | Million Instructions Per Second，每秒执行百万条指令 | $MIPS = \frac{f}{CPI \times 10^6}$ |
| **MFLOPS** | 每秒百万次浮点运算 | — |
| **CPU执行时间** | CPU执行某段程序所需的时间 | $T_{CPU} = \frac{指令条数 \times CPI}{f} = 指令条数 \times CPI \times T$ |

> 🗣️ **大白话**：
> - **主频**就像你心跳的速度，"滴答"得越快，干活的节奏就越快。
> - **CPI**就像每做一件事平均要"滴答"几下。简单的事1下就够，复杂的事可能要10下。
> - **MIPS**就像"每秒能做多少件事"。
> - 所以：干活时间 = 事情总数 × 每件事要滴答几下 × 每次滴答多长时间。

> ⚠️ **常见陷阱**：
> 1. 主频高 ≠ 速度一定快（还要看CPI，一条指令需要的周期数可能更多）
> 2. MIPS不能准确反映性能（不同指令的功能强弱不同，一条x86指令可能完成ARM多条指令的功能）
> 3. CPI取决于指令类型的混合比例——不同程序的CPI不同

📝 **2010年真题**：下列选项中，能缩短程序执行时间的措施是？
- Ⅰ. 提高CPU时钟频率 ✅（f增大 → 时钟周期T减小 → 执行时间减小）
- Ⅱ. 优化数据通路结构 ✅（可减少CPI）
- Ⅲ. 对程序进行编译优化 ✅（可减少指令条数或选择CPI更小的指令）
- **答案：D. Ⅰ、Ⅱ和Ⅲ**

📝 **2011年真题**：描述浮点数操作速度的指标是？ → **D. MFLOPS**（Million Floating-point Operations Per Second）。MIPS描述定点运算速度，CPI是每条指令的时钟周期数，IPC是每周期指令数。

### 二、整机性能指标

| 指标 | 定义 |
|---|---|
| **机器字长** | CPU一次整数运算能处理的二进制数据的位数（通常等于内部寄存器的位数） |
| **指令字长** | 一条指令的二进制位数（可以等于或大于机器字长） |
| **存储字长** | 一个存储单元存储的二进制位数 |
| **数据通路带宽** | 数据总线一次能传送信息的位数 |
| **主存容量** | 主存能存储的最大信息量 = 存储单元个数 × 存储字长 |

> ⚠️ **易混淆概念**：
> - **字节**（Byte）= 8 bit，这是固定的
> - **字**（Word）= 机器字长的位数，不同计算机可能不同（16位机的"字"=16bit，32位机的"字"=32bit）
> - **按字节编址**：每个地址对应1个字节（8bit）
> - **按字编址**：每个地址对应1个字

📝 **性能指标综合计算例题**：

**2009年真题（大题）**：某计算机的CPU主频为500MHz，CPI为5。某外设数据传输率为0.5MB/s，采用中断方式与主机进行数据传送，以32位为传输单位，中断服务程序包含18条指令，中断服务的其他开销相当于2条指令的执行时间。

**（1）中断方式下，CPU用于该外设I/O的时间百分比是多少？**

**解**：
- 每条指令执行时间 = CPI × T = 5 × (1/500MHz) = 10ns
- 每次中断处理时间 = (18+2) 条指令 × 10ns = 200ns = 0.2μs
- 每秒中断次数 = 0.5MB/s ÷ 4B = 125,000次/s
- CPU用于I/O的时间占比 = 125,000 × 200ns / 1s = **2.5%**

**（2）改用DMA方式，每次传送5000B，DMA预处理和后处理总开销为500个时钟周期，CPU时间百分比？**

**解**：
- 每秒DMA次数 = 5MB/s ÷ 5000B = 1000次/s
- 每次DMA的CPU开销 = 500个时钟周期 × (1/500MHz) = 1μs
- CPU用于I/O的时间占比 = 1000 × 1μs / 1s = **0.1%**

> 💡 **对比**：中断方式CPU开销2.5%，DMA方式仅0.1%。这说明DMA方式CPU效率远高于中断方式，这就是为什么磁盘等高速设备要用DMA。

---

## 📌 第一章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 冯·诺依曼体系5大特点 | ⭐⭐⭐ | 选择题 |
| 区分指令和数据的方法 | ⭐⭐⭐ | 选择题 |
| 各寄存器（PC/IR/MAR/MDR）功能 | ⭐⭐⭐⭐ | 选择题 |
| CPU执行时间/MIPS/CPI计算 | ⭐⭐⭐⭐ | 选择题、大题计算 |
| 程序员可见/不可见寄存器 | ⭐⭐⭐ | 选择题 |
| ISA的定义与作用 | ⭐⭐ | 选择题 |
| 编译程序 vs 解释程序 | ⭐⭐ | 选择题 |

---

# 第二章 数据的表示和运算

> **本章考情**：计组三大核心章之一，每年必考3~4道选择题 + 可能出大题。重点：补码运算与溢出判断（★★★★★）、IEEE 754浮点数表示（★★★★★）、C语言类型转换（★★★★）、标志位计算（★★★★）。本章是"计算题重灾区"，必须熟练到手算秒出的程度！

## 2.1 进位计数制与相互转换

### 一、常用进位计数制

| 进位制 | 基数 | 数码 | 权的一般形式 | 标记 |
|---|---|---|---|---|
| 二进制(B) | 2 | 0, 1 | $2^i$ | 1010B |
| 八进制(O) | 8 | 0~7 | $8^i$ | 12O |
| 十进制(D) | 10 | 0~9 | $10^i$ | 10D |
| 十六进制(H) | 16 | 0~9, A~F | $16^i$ | 0AH |

### 二、进制转换方法

**任意进制 → 十进制**：按权展开求和

例：$(1011.01)_2 = 1×2^3 + 0×2^2 + 1×2^1 + 1×2^0 + 0×2^{-1} + 1×2^{-2} = 8+2+1+0.25 = 11.25$

**十进制 → 二进制**：整数部分"除2取余、逆序排列"；小数部分"乘2取整、顺序排列"

**二进制 ↔ 八进制**：每3位二进制对应1位八进制，从小数点向两边分组

**二进制 ↔ 十六进制**：每4位二进制对应1位十六进制，从小数点向两边分组

> 🗣️ **大白话**：为什么要学进制转换？因为计算机只认识二进制，而十六进制是人类读写二进制最方便的简写（每4位二进制=1位十六进制）。你会看到考题里各种 `0B1FH`、`FEH` 之类的东西，本质就是二进制的缩写。

### 三、真值与机器数

| 概念 | 含义 | 示例 |
|---|---|---|
| **真值** | 现实中带正负号的数值 | +15, -8 |
| **机器数** | 数在计算机中的二进制表示 | 0000 1111, 1111 1000 |

> ⚠️ **注意**：机器数的最高位是符号位（0=正，1=负），但"符号位"到底怎么处理，取决于用什么编码方式（原码/补码/反码/移码）。

---

## 2.2 定点数的编码表示

### 一、原码、反码、补码、移码

假设字长为 $n+1$ 位（1位符号位 + n位数值位）：

| 编码方式 | 正数 | 负数 | 表示范围 | 零的表示 | 特点 |
|---|---|---|---|---|---|
| **原码** | 符号位0 + 真值 | 符号位1 + 真值绝对值 | $-(2^n-1) \sim +(2^n-1)$ | +0和-0两种 | 直观，但加减运算复杂 |
| **反码** | 同原码 | 原码的符号位不变，数值位逐位取反 | 同原码 | +0和-0两种 | 是求补码的中间步骤 |
| **补码** | 同原码 | 反码末位+1 | $-2^n \sim +(2^n-1)$ | 唯一的0 | 加减运算统一，计算机中最常用 |
| **移码** | 补码的符号位取反 | 补码的符号位取反 | 同补码 | 唯一的0 | 用于浮点数的阶码 |

> 🗣️ **大白话**：
> - **原码**：最直观——正数前面放0，负数前面放1，后面照抄真值。缺点是做减法很麻烦。
> - **补码**：计算机的"统一货币"——把减法变成加法。负数的补码=把原码数值位取反再+1。计算机内部几乎所有整数都用补码存储！
> - **移码**：只用于浮点数的阶码。特点是**移码的大小可以直接比较大小**（越大数值越大），所以用来表示阶码很方便。

**手算补码的快速方法**：

方法一（标准）：原码 → 数值位取反 → 末位+1

方法二（**快捷法⭐**）：从右往左找到第一个1，这个1及其右边的位不变，左边的位逐位取反

例：$-52$ 的 8 位补码
- 52 的原码：0,0110100
- 取反：1,1001011
- 末位+1：1,1001100
- 即 $[-52]_{补}$ = **1100 1100** = CCH

> ⚠️ **补码的特殊值**：
> - 8位补码能表示 -128 ~ +127
> - $[+0]_{补} = 0000\ 0000$，$[-0]_{补} = 0000\ 0000$（补码的0是唯一的！）
> - $[-128]_{补} = 1000\ 0000$（这个值**没有对应的原码和反码**！是补码多出来的一个数）
> - 一般地：$n+1$ 位补码的范围是 $[-2^n, 2^n-1]$，正数比负数少一个

### 二、补码 ↔ 真值 ↔ 原码 的快速转换

```
已知 [X]补 = 1,0110100
      ↓
方法1：符号位为1 → 负数，求绝对值：数值位取反+1 → 1001100 = 76 → 真值 = -76
方法2（推荐）：[X]补 → [X]原 = 符号位不变，数值位取反+1 → 1,1001100 → 真值 = -76
```

> ⚠️ **极端重要**：补码→原码的方法和原码→补码的方法**完全相同**！都是"数值位取反+1"。这个是双向可逆的。

### 三、C语言中的整数类型

| 类型 | 32位系统位数 | 范围 | 存储方式 |
|---|---|---|---|
| `char` | 8 | -128~127 | 补码 |
| `unsigned char` | 8 | 0~255 | 无符号 |
| `short` | 16 | -32768~32767 | 补码 |
| `unsigned short` | 16 | 0~65535 | 无符号 |
| `int` | 32 | $-2^{31} \sim 2^{31}-1$ | 补码 |
| `unsigned int` | 32 | $0 \sim 2^{32}-1$ | 无符号 |

### 四、符号扩展与零扩展

**符号扩展**：将短类型转换为长类型时，**在高位补符号位**（有符号数扩展）

**零扩展**：将短类型转换为长类型时，**在高位补0**（无符号数扩展）

📝 **2009年真题**：x为int型，值为0x0000007F；y为short型，值为0xFFF7。执行z=x+y时，y需要从16位扩展到32位，由于y的符号位为1，所以**符号扩展**后y=0xFFFFFFF7。然后 0x0000007F + 0xFFFFFFF7 = 0x00000076（最高位进位丢弃）。答案D。

📝 **2024年真题**：`short si = -32767; unsigned int ui = si;` 执行后ui的值？
- si = -32767，16位补码 = 8001H
- si → int（符号扩展）：FFFF8001H → unsigned int（**不改变位模式**，仅重新解释）
- ui = FFFF8001H = $2^{32} - 32767 = 2^{32} - 2^{15} + 1$
- **答案：D. $2^{32}-2^{15}+1$**

📝 **2025年真题**：`int i = 32777; short si = i; int j = si;` 执行后j的真值？
- i = 32777 → 补码 = 0x00008009
- si = (short)i → 截断为16位 = 0x8009 → 符号位为1，是负数
- si的真值 = -(0x7FF7) = -(0111 1111 1111 0111) = -32759... 不对，让我重算
- 0x8009 = 1000 0000 0000 1001，取反+1 = 0111 1111 1111 0111 = 32759 → 真值 = -32759 ❌
- 重新精确计算：0x8009 的补码真值 = -32768 + 9 = -32759
- j = (int)si = 符号扩展 → j = -32759
- **答案：B. -32759**

---

## 2.3 补码的加减运算与溢出判断
![补码加减与标志位](图表/CO/CO-01_Flags.png)


### 一、补码加减运算规则

$$[A+B]_{补} = [A]_{补} + [B]_{补}$$
$$[A-B]_{补} = [A]_{补} + [-B]_{补}$$

其中 $[-B]_{补}$ 可由 $[B]_{补}$ 各位取反、末位加1得到（包括符号位！）

> 🗣️ **大白话**：补码的好处就是——不管是加法还是减法，都变成了加法！做减法时，只要把减数"连同符号位一起取反加1"就变成了加法。整个运算过程中，符号位和数值位一起参与运算，最终的结果自然就是正确的补码。

### 二、溢出判断（⭐必考）

**什么时候会溢出？** 同号相加才可能溢出（正+正 → 结果可能太大装不下；负+负 → 结果可能太小装不下）。异号相加永远不会溢出。

**三种判断方法**：

| 方法 | 原理 | 判断规则 |
|---|---|---|
| **一位符号位** | 看操作数和结果的符号位 | 两个正数相加结果为负 → 正溢；两个负数相加结果为正 → 负溢 |
| **双符号位法（变形补码）** | 用2位表示符号（00=正, 11=负） | 结果为01→正溢出，结果为10→负溢出，00或11→无溢出 |
| **进位判断法** | 看最高数值位的进位$C_n$和符号位的进位$C_{n+1}$ | $C_n \oplus C_{n+1} = 1$ → 溢出 |

> 🗣️ **大白话**：就好比一个杯子最多装500ml水，你倒了300ml再倒300ml，杯子就"溢出"了。计算机的寄存器位数固定，数字太大就装不下了。

### 三、标志位详解（⭐2024/2025年真题反复考）

执行运算 A op B 后，PSW中各标志位的设置规则：

| 标志位 | 含义 | 设置规则 |
|---|---|---|
| **OF** (Overflow) | 有符号数溢出 | $OF = C_n \oplus C_{n+1}$（最高位进位⊕符号位进位） |
| **SF** (Sign) | 结果的符号 | SF = 结果的最高位（即符号位） |
| **ZF** (Zero) | 结果是否为零 | 结果全0则ZF=1，否则ZF=0 |
| **CF** (Carry) | 无符号数溢出/进位/借位 | 加法：CF=最高位进位$C_{out}$；减法：CF=最高位借位（进位取反） |

> ⚠️ **核心区分**：
> - **OF**是给**有符号数**用的（判断有符号加减是否溢出）
> - **CF**是给**无符号数**用的（判断无符号加减是否溢出）
> - 同一个运算同时设置OF和CF，但你看哪个取决于你把操作数当有符号数还是无符号数

📝 **2025年真题**：x=A3H，y=75H，计算x-y，求真值和OF标志？

**手算过程**：
- x = A3H = 1010 0011（若为有符号数，真值 = -93）
- y = 75H = 0111 0101（若为有符号数，真值 = +117）
- $[x-y]_{补}$ = x + (-y)的补码
- [-y]补 = 0111 0101 → 取反加1 → 1000 1011
- x + [-y]补 = 1010 0011 + 1000 1011 = **0010 1110**（进位丢弃）= 2EH = +46
- 真值 = 46（但 -93 - 117 = -210，应该溢出了！）
- 验证OF：$C_7$（符号位进位）= 1（有进位），$C_6$（最高数值位进位）= 0
- $OF = C_7 \oplus C_6 = 1 \oplus 0 = 1$（确实溢出了！）
- **答案：真值46（溢出后的错误结果），OF=1**

---

## 2.4 定点数的移位运算

### 一、算术移位

| 操作 | 符号位 | 移出的空位 |
|---|---|---|
| **算术左移** | 不变 | 低位补0 |
| **算术右移** | 不变 | **高位补符号位** |

规则：**高位补符号位、低位补0**

等价意义：左移1位 ≈ ×2，右移1位 ≈ ÷2

### 二、逻辑移位

无论左移还是右移，空出的位一律补0。用于无符号数。

### 三、循环移位

移出的位从另一端移入，形成"旋转"效果。

> ⚠️ **考试注意**：算术移位可能导致精度丢失或溢出。左移时如果最高有效位被移出，就会溢出。

---

## 2.5 定点数的乘除运算（了解原理）

### 一、乘法运算

| 方法 | 说明 | 考试要求 |
|---|---|---|
| **原码一位乘法** | 符号位单独处理，数值位类似手工乘法 | 了解原理 |
| **补码一位乘法（Booth算法）** | 根据乘数末两位（$y_i y_{i-1}$）决定加/减/不操作 | 了解Booth编码 |
| **阵列乘法器** | 硬件并行实现，可在一个时钟周期内完成 | 了解即可 |

**原码一位乘法**（手工理解版）：

符号位 $= X_s \oplus Y_s$，数值部分按"**逐位相乘、移位累加**"计算（与手工十进制乘法完全类似）。

设被乘数 $|X| = 0.x_1x_2\cdots x_n$，乘数 $|Y| = 0.y_1y_2\cdots y_n$：
1. **部分积**初始化为 0
2. 从乘数最低位 $y_n$ 开始，若 $y_i = 1$ 则部分积 **加 $|X|$**，若 $y_i = 0$ 则加 0
3. 部分积**右移1位**
4. 重复 $n$ 次（$n$ 为数值位数）

**补码一位乘法（Booth算法）**（⭐ 唐朔飞详解版）：

| 步骤 | 判断 $y_i - y_{i-1}$（末两位之差） | 操作 |
|:---:|:---:|:---|
| 看 $y_i y_{i-1}$ | $0 - 0 = 0$ | **部分积不变**，右移1位 |
| | $0 - 1 = -1$ | 部分积 **$+[-X]_补$**（减X），右移1位 |
| | $1 - 0 = +1$ | 部分积 **$+[X]_补$**（加X），右移1位 |
| | $1 - 1 = 0$ | **部分积不变**，右移1位 |

> 💡 **Booth 算法核心**：在乘数 $Y$ 末尾附加一位 $y_{n+1} = 0$，从右到左逐位扫描 $y_i$ 和 $y_{i-1}$：
> - 从 0→1（即 $y_i=1, y_{i-1}=0$）：**加 $[X]_补$**
> - 从 1→0（即 $y_i=0, y_{i-1}=1$）：**加 $[-X]_补$**（即减 $X$）
> - 0→0 或 1→1：不操作
>
> 共执行 $n$ 次"判断+移位"，**最后一步只做加减不移位**（共 $n+1$ 步，$n$ 次移位）。

**详细手算示例**：求 $X \times Y$，其中 $X = -0.1101$，$Y = +0.1011$

$[X]_补 = 1.0011$，$[-X]_补 = 0.1101$，$[Y]_补 = 0.1011$

| 步骤 | 部分积（高位） | 乘数（低位+附加位） | $y_i y_{i-1}$ | 操作 |
|:---:|:---:|:---:|:---:|:---|
| 初始 | 0.0000 | 1011**0** | — | 附加位 $y_{n+1}=0$ |
| ① | | | **10** | $y_i - y_{i-1} = 1-0 = +1$ → **$+[X]_补$** |
| | 0.0000 + 1.0011 = 1.0011 | 10110 | | **右移1位** |
| | **1**.1001 | 1**1011** | | |
| ② | | | **11** | $1-1=0$ → **不操作** |
| | 1.1001 | 11011 | | **右移1位** |
| | **1**.1100 | 1**1101** | | |
| ③ | | | **01** | $0-1=-1$ → **$+[-X]_补$** |
| | 1.1100 + 0.1101 = 0.1001 | 11101 | | **右移1位** |
| | **0**.0100 | 1**1110** | | |
| ④ | | | **10** | $1-0=+1$ → **$+[X]_补$**（**最后一步不移位**） |
| | 0.0100 + 1.0011 = 1.0111 | 11110 | | 完成！ |

$[X \times Y]_补 = 1.01111110$，转真值 $= -0.10000010$

> ⚠️ **Booth 算法的右移**：是**补码算术右移**（符号位不变，符号位参与右移，高位补符号位）。
>
> ⚠️ **Booth 算法的优势**：直接用补码运算，**符号位自然参与运算**，不需要单独处理符号。而原码一位乘法需要先处理符号再处理数值。

![Booth算法逻辑表](图表/CO/CO-06_BoothAlgo.png)

> 📝 **2024年真题**：关于乘法运算，错误的是？→ **D. 两个变量的乘运算无法编译为移位及加法等指令的循环实现**。实际上，编译器可以将两个变量的乘法编译为循环的"移位+累加"来实现（类似手工乘法的过程）。

### 二、除法运算

| 方法 | 说明 |
|---|---|
| 恢复余数法 | 试商后如果不够减就恢复余数 |
| 加减交替法（不恢复余数法） | 通过余数的符号决定下一步操作 |

**恢复余数法**：用被除数（余数）减去除数：
- 余数 $\geq 0$：商上 1，余数左移，继续减除数
- 余数 $\lt 0$：商上 0，**加回除数恢复余数**，余数左移，继续减除数
- 缺点：不够减时需要额外一步"恢复"，效率低

**加减交替法（不恢复余数法）**（⭐ 唐朔飞详解版）：

核心思想：**不需要恢复余数**，根据余数符号直接决定下一步操作。

| 余数符号 | 操作 | 商 |
|:---:|:---|:---:|
| 余数 $\geq 0$ | 商上 **1**，余数**左移1位**，**减**除数 | 1 |
| 余数 $\lt 0$ | 商上 **0**，余数**左移1位**，**加**除数 | 0 |

> 🗣️ **大白话**：就像你掏钱买东西——如果余额够（≥0），就继续花（减除数）；如果余额不够（<0），就想办法挣回来（加除数），不需要"退货"（不需要恢复余数）。

**原码加减交替法示例**：$X = 0.1011$，$Y = 0.1101$，求 $X \div Y$

$|X| = 0.1011$，$|Y| = 0.1101$，$[-|Y|]_补 = 1.0011$

|  步骤  |              余数              | 操作                     |  商  | 备注           |
| :--: | :--------------------------: | :--------------------- | :-: | :----------- |
|  初始  |          0.**1011**          | $-                     |  Y  | （加 $[-Y]_补$） |
|  ①   | 0.1011 + 1.0011 = **1**.1110 | 余数\<0 → 商上 **0**，左移，$+ |  Y  | $0$          |
|  ②   | 1.1100 + 0.1101 = **0**.1001 | 余数≥0 → 商上 **1**，左移，$-  |  Y  | $01$         |
|  ③   | 1.0010 + 1.0011 = **0**.0101 | 余数≥0 → 商上 **1**，左移，$-  |  Y  | $011$        |
|  ④   | 0.1010 + 1.0011 = **1**.1101 | 余数\<0 → 商上 **0**，左移，$+ |  Y  | $0110$       |
| 末尾修正 |                              | 最终余数\<0 → 加 $          |  Y  | $ 恢复余数       |

商 $= 0.1100$（取4位有效数字），符号 $= X_s \oplus Y_s = 0$

> ⚠️ **原码 vs 补码除法**：
> - **原码除法**：符号位单独处理（$X_s \oplus Y_s$），数值部分用加减交替法
> - **补码除法**：符号位参与运算，规则稍有不同（同号做减法，异号做加法）
> - 考试主要考**原码加减交替法**，补码除法了解即可

> ⚠️ **除法溢出条件**：
> 1. **除数为0** → 除法异常
> 2. **被除数太大**（如 $[-2^{31}] \div [-1]$）→ 商超出表示范围 → 除法溢出异常

---

![IEEE 754编码拆解](图表/CO/CO-02_IEEE754Detailed.png)

## 2.6 IEEE 754 浮点数标准（⭐⭐⭐⭐⭐ 必考）

![IEEE754标准](图表/CO/CO-02_IEEE754.png)

### 一、浮点数的一般表示

$$N = (-1)^S \times M \times R^E$$

- S：符号（0正1负）
- M：尾数（Mantissa）
- R：基数/底（通常为2）
- E：阶码（Exponent，指数）

> 🗣️ **大白话**：浮点数就像科学计数法。比如 $-3.14 \times 10^5$，符号是"-"，尾数是3.14，底是10，阶码（指数）是5。计算机里底固定为2，只需要存符号、阶码、尾数。

### 二、IEEE 754标准格式

| 格式 | 总位数 | 符号S | 阶码E | 尾数M | 偏置值（Bias） |
|---|---|---|---|---|---|
| **单精度float** | 32 | 1位 | 8位 | 23位 | 127 |
| **双精度double** | 64 | 1位 | 11位 | 52位 | 1023 |

**真值 = $(-1)^S \times 1.M \times 2^{E-Bias}$**

> ⚠️ **关键理解**：
> 1. **隐藏的1**：规格化浮点数的尾数最高位一定是1，所以不存储，节省1位空间。实际尾数是 **1.M**（小数点前有个隐藏的1）
> 2. **阶码用移码**：实际指数 = 存储的阶码 - 偏置值。单精度偏置值=127，双精度偏置值=1023
> 3. 阶码全0和全1有特殊含义：
>    - 阶码全0、尾数全0 → 表示 **±0**
>    - 阶码全0、尾数非0 → 表示 **非规格化数**（尾数前是0而不是1）
>    - 阶码全1、尾数全0 → 表示 **±∞**
>    - 阶码全1、尾数非0 → 表示 **NaN**（Not a Number）

### 三、IEEE 754 转换——手算步骤（考试必备⭐）

**十进制 → IEEE 754**：

例：求 $-8.25$ 的单精度IEEE 754表示

1. 确定符号位：S = 1（负数）
2. 将绝对值转二进制：$8.25 = 1000.01_2$
3. 规格化：$1000.01 = 1.00001 \times 2^3$
4. 阶码E = 3 + 127 = 130 = $10000010_2$
5. 尾数M = 00001000000000000000000（去掉隐含的1，取小数部分，右边补0到23位）
6. 拼接：1 | 10000010 | 00001000000000000000000
7. 转十六进制：**C1040000H**

> 📝 **2011年真题**：float x = -8.25，求FR1的内容？ → **A. C1040000H**

**IEEE 754 → 十进制**：

例：单精度 4730 0000H 的真值

1. 转二进制：0 | 10001110 | 01100000000000000000000
2. S = 0（正数）
3. E = 10001110 = 142，实际指数 = 142 - 127 = 15
4. M = 1.011（加上隐含的1）
5. 真值 = $+1.011 \times 2^{15} = 1.375 \times 2^{15}$

> 📝 **2025年真题**：float类型机器数4730 0000H的真值？ → **D. $1.375 \times 2^{15}$**

### 四、浮点数加减运算（⭐必考）

**运算步骤**：

```
① 对阶：小阶向大阶看齐（小阶的尾数右移，阶码增大）
② 尾数加减：对阶后的尾数进行加减运算
③ 规格化：
   - 左规：尾数绝对值 < 1，尾数左移，阶码减小
   - 右规：尾数溢出（如01.xxx或10.xxx），尾数右移1位，阶码+1
④ 舍入：处理右移时丢失的低位（0舍1入法 / 恒置1法）
⑤ 判溢出：检查阶码是否溢出
```

> 🗣️ **大白话**：浮点加减就像做科学计数法加减——
> - $3.14 \times 10^5 + 2.0 \times 10^3$
> - 先对阶：把 $10^3$ 变成 $10^5$，所以 $2.0$ 变成 $0.02$
> - 再加减：$3.14 + 0.02 = 3.16$
> - 结果：$3.16 \times 10^5$

> ⚠️ **"小阶向大阶看齐"的原因**：如果大阶向小阶看齐，尾数要左移，可能导致高位有效数字丢失，损失更大。而小阶向大阶看齐，尾数右移，丢失的是低位，精度损失较小。

📝 **2009年真题**：X = 00,111;00,11101（阶码;尾数），Y = 00,101;00,10100。求X+Y？

**解**：
1. 对阶：X阶码=111(7)，Y阶码=101(5)，差=2，Y的阶码+2→尾数右移2位
   - Y对阶后 = 00,111;00,00101
2. 尾数相加：00,11101 + 00,00101 = 01,00010
3. 尾数符号位为01（正溢出），需右规：尾数右移1位→00,10001，阶码+1→01,000
4. 阶码01,000，符号位为01→阶码正溢出！→ **结果溢出**

---

## 2.7 数据的存储和排列

### 一、大端序与小端序

| 方式 | 规则 | 记忆方法 |
|---|---|---|
| **大端序 (Big-Endian)** | **高**位字节存放在**低**地址 | "大端=大头（高位）在前面（低地址）" |
| **小端序 (Little-Endian)** | **低**位字节存放在**低**地址 | "小端=小头（低位）在前面（低地址）" |

例：32位整数 0x12345678 在地址 0x100 开始存放：

| 地址 | 大端 | 小端 |
|---|---|---|
| 0x100 | 12 | 78 |
| 0x101 | 34 | 56 |
| 0x102 | 56 | 34 |
| 0x103 | 78 | 12 |

> 🗣️ **大白话**：
> - **大端序**就像正常读数字：最高位（最重要的）放在最前面（最小地址），就像我们写 "12345678"，1在最前面。
> - **小端序**就像倒着放：最低位（最不重要的）放在最前面，就像写成 "78563412"。

> 📝 **2024年真题**：通过分析lw指令中立即数 0x0A 的存放方式，判断系统采用**小端存储**。

### 二、边界对齐

**边界对齐（Alignment）**：数据的存放地址必须是其数据长度的整数倍。

- char（1字节）：可以在任意地址
- short（2字节）：地址必须是2的倍数
- int（4字节）：地址必须是4的倍数
- double（8字节）：地址必须是8的倍数

> 📝 **2024年真题**：struct record {int id; char name[10]; int salary;} employee[200]; 数组首地址为0000A0B0H。由于int占4字节、char name[10]占10字节，结构体需要边界对齐，所以每个struct record占 4+10+2(padding)+4 = 20字节。employee[1].id 的地址 = 0000A0B0H + 20 = 0000A0C4H。**答案：B**

---

## 📌 第二章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 补码运算与溢出判断 | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| IEEE 754浮点数表示 | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| C语言类型转换（符号扩展/截断） | ⭐⭐⭐⭐ | 选择题 |
| 标志位（OF/SF/ZF/CF）计算 | ⭐⭐⭐⭐ | 选择题 |
| 浮点数加减运算步骤 | ⭐⭐⭐⭐ | 选择题、大题 |
| 大端序/小端序 | ⭐⭐⭐ | 选择题、大题 |
| 边界对齐 | ⭐⭐⭐ | 选择题 |
| 移位运算规则 | ⭐⭐ | 选择题 |
| 原码/补码乘除法 | ⭐⭐ | 了解原理 |

---

## 第三章 存储系统

> **本章考情**：计组三大核心章之一，每年必考3~5道选择题 + 高频大题。Cache映射/命中率计算是408组原部分**考频最高**的考点（★★★★★）。存储芯片扩展设计也是大题高频考点。本章约占计组总分的28%左右。

## 3.1 存储器的基本概念

### 一、存储器的分类

**按存取方式分类**：

| 类型 | 全称 | 特点 | 示例 |
|---|---|---|---|
| **RAM** | Random Access Memory | 按地址随机存取，读写时间与位置无关 | SRAM, DRAM |
| **ROM** | Read Only Memory | 只读存储器（广义上也支持写） | PROM, EPROM, Flash |
| **SAM** | Sequential Access Memory | 顺序存取，需从头开始找 | 磁带 |
| **DAM** | Direct Access Memory | 先直接定位到某区域，再顺序查找 | 磁盘 |

> 📝 **2011年真题**：不采用随机存取方式的是？ → **B. CDROM**（CD-ROM属于光盘，采用直接存取方式，先寻道再读取）。EPROM、DRAM、SRAM都是随机存取。注意：ROM也是随机存取！

**按信息保持性分类**：

| 类型 | 特点 | 示例 |
|---|---|---|
| **易失性存储器** | 断电后信息丢失 | SRAM、DRAM |
| **非易失性存储器** | 断电后信息仍保持 | ROM、Flash、磁盘、SSD |

**存储器层次结构**：

```
    ┌────────┐  速度最快、容量最小、价格最贵
    │ 寄存器  │  ← CPU内部
    ├────────┤
    │ Cache  │  ← SRAM实现
    ├────────┤
    │  主存   │  ← DRAM实现
    ├────────┤
    │辅存/外存│  ← 磁盘、SSD、光盘
    └────────┘  速度最慢、容量最大、价格最便宜
```

> 🗣️ **大白话**：存储器层次就像你放东西——手边的桌子（寄存器）最方便但放不了多少东西，书架（Cache）放得稍多，房间（主存）更大，仓库（硬盘）最大但要走一趟才能拿到。CPU需要数据时总是先在"桌子"上找，找不到再去"书架"，再找不到去"房间"……

### 两个重要的层次

| 层次 | 目的 | 数据交换单位 | 由谁管理 |
|---|---|---|---|
| **Cache-主存** | 解决CPU与主存的**速度**矛盾 | Cache行/主存块（几十~几百字节） | **硬件**自动管理 |
| **主存-辅存** | 解决主存**容量**不够的问题 | 页/段（几KB~几MB） | **操作系统**（软件）管理 |

> 🔗 **跨科目联系**：
> - 主存-辅存层次 → **OS第三章**虚拟内存管理（请求分页、页面置换）
> - Cache层次 → 考试中经常与**虚拟存储器、TLB**结合出大题

---

## 3.2 SRAM与DRAM

### 一、SRAM vs DRAM 对比（⭐必考）

| 对比项 | SRAM（静态RAM） | DRAM（动态RAM） |
|---|---|---|
| **存储元件** | 双稳态触发器（6个MOS管） | 电容（1个MOS管+1个电容） |
| **是否需要刷新** | ❌ 不需要 | ✅ 需要定期刷新（通常2ms） |
| **存取速度** | 快（ns级） | 慢（比SRAM慢） |
| **集成度** | 低（每个存储单元占6个管子） | 高（每个单元只需1管+1电容） |
| **成本** | 高 | 低 |
| **功耗** | 大 | 小 |
| **用途** | **Cache** | **主存** |
| **是否易失** | 是 | 是 |

> 🗣️ **大白话**：SRAM就像用6把锁锁住一个保险箱，数据稳稳当当不会丢（不需要刷新），但太贵太占地方，只能少量使用（做Cache）。DRAM就像用一个漏水的杯子存水，便宜占地小但水会慢慢漏掉，必须隔一会儿就重新加满水（刷新），适合大量使用（做主存）。

### 二、DRAM的刷新

| 刷新方式 | 特点 | 优缺点 |
|---|---|---|
| **集中刷新** | 在一个刷新周期内集中安排一段时间依次刷新所有行 | 有"死区"（刷新期间不能访存） |
| **分散刷新** | 每次存取操作后紧跟一次刷新 | 无死区，但存取周期变长 |
| **异步刷新** | 将刷新分散到整个刷新周期中，每隔一段时间刷新一行 | 折中方案，死区时间很短 |

> ⚠️ **刷新要点**：
> 1. DRAM刷新以**行**为单位（不是按位、字节或列）
> 2. 刷新是由**存储器控制器**自动完成的，不需要CPU干预
> 3. 刷新操作类似于**读出后重新写入**（破坏性读出后恢复）
> 4. 刷新周期一般为**2ms**

### 三、ROM的类型

| 类型 | 全称 | 特点 |
|---|---|---|
| MROM | 掩模ROM | 出厂时就写好，不可更改 |
| PROM | 可编程ROM | 用户可以一次性编程 |
| EPROM | 可擦除可编程ROM | 紫外线擦除，可重复写入 |
| EEPROM | 电可擦除可编程ROM | 电信号擦除，可重复写入 |
| Flash | 闪存 | EEPROM的改进版，U盘/SSD的基础 |

> 📝 **2010年真题**：RAM和ROM的叙述，正确的是？
> - Ⅰ. RAM是易失性，ROM是非易失性 ✅
> - Ⅱ. RAM和ROM都采用随机存取方式 ✅
> - Ⅲ. RAM和ROM都可用作Cache ❌（Cache用高速SRAM）
> - Ⅳ. RAM和ROM都需要刷新 ❌（ROM不需要刷新，SRAM也不需要）
> - **答案：A. 仅Ⅰ和Ⅱ**

---

## 3.3 主存储器与CPU的连接（⭐大题高频）

### 一、存储器芯片的扩展

![总线仲裁-链式查询](图表/CO/CO-08_BusArbitration.png)

**位扩展（数据线扩展）**：用多个芯片**并联**，增加存储字长

- 例：用 $2K \times 4$ 位的芯片组成 $2K \times 8$ 位存储器 → 需要 **2片**并联
- 地址线、片选信号**共用**，数据线**各自分开**

**字扩展（地址线扩展）**：用多个芯片**串联**，增加存储单元个数
![主存扩展设计](图表/CO/CO-09_MemExpansion.png)


- 例：用 $2K \times 8$ 位的芯片组成 $8K \times 8$ 位存储器 → 需要 **4片**，用高位地址线做片选
- 低位地址线共用，**高位地址线用于片选**

**字位同时扩展**：既增加字数又增加位数

- 例：用 $2K \times 4$ 位的芯片组成 $8K \times 8$ 位存储器 → 需要 $\frac{8K}{2K} \times \frac{8}{4} = 4 \times 2 = 8$ 片

> 🗣️ **大白话**：
> - **位扩展**：一个芯片只有4位"宽"，你需要8位宽怎么办？两个芯片肩并肩站在一起，一个出高4位，一个出低4位。
> - **字扩展**：一个芯片只有2K个"格子"，你需要8K个格子？四个芯片首尾相连。地址的高2位决定选哪个芯片，低11位决定选芯片内的哪个格子。

📝 **2009年真题**：ROM区4KB，用2K×8位芯片，需要 $\frac{4K}{2K}=2$ 片（字扩展）。RAM区60KB，用4K×4位芯片，需要 $\frac{60K}{4K} \times \frac{8}{4}=30$ 片（字位同时扩展）。**答案D**。

📝 **2010年真题**：用2K×4位芯片组成8K×8位存储器，地址0B1FH所在芯片的最小地址？
- 每行2片并联（位扩展），共4行（字扩展）
- 第一行：0000H~07FFH，第二行：0800H~0FFFH，第三行：1000H~17FFH，第四行：1800H~1FFFH
- 0B1FH在0800H~0FFFH范围内（第二行）→ 最小地址 = **0800H**。答案D。

### 二、片选信号的产生

| 方式 | 说明 | 特点 |
|---|---|---|
| **线选法** | 用高位地址线直接作为片选信号 | 简单，但地址空间不连续 |
| **译码器法** | 用译码器将高位地址线译码产生片选信号 | 地址空间连续，实际常用 |

---

## 3.4 多模块存储器

### 一、高位交叉编址 vs 低位交叉编址

| 方式 | 地址分配 | 效果 |
|---|---|---|
| **高位交叉编址** | 高位为模块号，低位为模块内地址 | 顺序存储，**不能**提高带宽 |
| **低位交叉编址** | 低位为模块号，高位为模块内地址 | 交叉存储，**流水线方式**访问，提高带宽 |

> 🗣️ **大白话**：
> - **高位交叉**：就像把100本书分成4摞，第1~25本放第1摞，第26~50本放第2摞。要连续读前4本书，都在同一摞里，只能等一本读完再读下一本——没有任何加速。
> - **低位交叉**：第1本放第1摞，第2本放第2摞，第3本放第3摞，第4本放第4摞，第5本又放第1摞……要连续读4本书时，可以4摞同时开始读——流水线加速！

### 二、低位交叉编址的关键公式⭐

设主存存取周期为 $T$，总线传送周期为 $r$，共 $m$ 个模块：

$$m \geq \frac{T}{r}$$

连续读取 $m$ 个字的时间：$T + (m-1) \times r$

> ⚠️ **理解公式**：第1个字要等完整的存取周期T才能出来，但读第1个字的同时，第2个模块已经开始工作了。所以后续每个字只需要再等$r$的时间。

---

## 3.5 Cache（高速缓冲存储器）⭐⭐⭐⭐⭐

> ⚠️ **重中之重！** Cache是408组原部分考频最高的知识点，几乎每年都出选择题甚至大题。必须掌握到能手算所有细节的程度！

![Cache映射](图表/CO/CO-03_CacheMapping.png)

### 一、Cache的基本原理

**为什么需要Cache？** CPU速度越来越快，主存（DRAM）速度远远跟不上，形成"CPU等主存"的瓶颈。Cache用高速的SRAM做一个小容量的"缓冲"，把CPU近期可能用到的数据提前拷贝过来。

**工作原理**：基于**局部性原理**：
- **时间局部性**：如果一个数据现在被访问，那么将来它很可能再次被访问（如循环变量）
- **空间局部性**：如果一个数据现在被访问，那么它附近的数据很可能也会被访问（如数组遍历）

> 🗣️ **大白话**：你写作业时，常翻的参考书放在桌上（Cache），不常翻的放书架上（主存），极少看的放仓库（外存）。你的"桌面"就像Cache——虽然放不了几本书，但你正在用的书99%的时间都在桌上。

### 二、Cache的性能指标

$$命中率 H = \frac{N_{Cache}}{N_{Cache} + N_{主存}}$$

**平均访问时间**有两种计算公式（取决于是否"同时访问"）：

| 情况 | 公式 | 说明 |
|---|---|---|
| **先访问Cache，未命中再访问主存** | $t_{avg} = H \times t_c + (1-H) \times (t_c + t_m)$ | 未命中时两次时间都要算 |
| **同时访问Cache和主存** | $t_{avg} = H \times t_c + (1-H) \times t_m$ | 主流考试用这个公式 |

> ⚠️ **注意审题**：考题会说"Cache不命中时的访问时间为…"，有时候这个时间已经包含了Cache的查找时间，有时候没有。要看清是$t_m$还是$t_c + t_m$。

📝 **2009年真题**：访存1000次，Cache缺失50次，命中率？ → H = (1000-50)/1000 = **95%**。答案D。

![Cache地址分解](图表/CO/CO-05_CacheAddress.png)

### 三、Cache与主存的映射方式（⭐核心考点）

![Cache映射方式对比](图表/CO/CO-13_CacheMapping.png)


**主存地址结构**：

```
┌───────────┬──────────┬─────────┐
│  标记Tag   │ 行号/组号 │ 块内地址 │
└───────────┴──────────┴─────────┘
```

| 映射方式 | Cache位置决定 | Tag | 优点 | 缺点 | 适用 |
|---|---|---|---|---|---|
| **全相联映射** | 主存块可放Cache**任意行** | = 主存块号 | 命中率最高，空间利用率最高 | 比较器多，查找慢，成本高 | 小容量Cache |
| **直接映射** | Cache行号 = 主存块号 mod Cache行数 | = 主存块号的高位 | 查找最快（只需看一行） | 冲突率最高，空间利用率最低 | 大容量Cache |
| **组相联映射** | Cache组号 = 主存块号 mod Cache组数，组内任意放 | = 主存块号的高位 | 折中方案 | — | 最常用 |

**n路组相联**：每组有n行（n=1就是直接映射，n=全部行数就是全相联映射）

> 🗣️ **大白话**：
> - **直接映射**：像分配宿舍，按学号固定住哪个房间。简单，但可能两个人都被分到同一间，一个来了另一个就必须走。
> - **全相联映射**：想住哪间就住哪间，自由但找人的时候得挨个房间敲门问。
> - **组相联映射**：先分你到哪个楼层（确定组），同一层里随便住（组内自由），找人时只在这一层找。

📝 **2009年真题**：Cache共16块，2路组相联，则共8组。主存129号单元在第几块？129/块大小=第4块（假设每块32字节，129所在的主存块号=4）。4 mod 8 = 第4组。答案C。

**地址位数的分配（手算方法）⭐**：

假设主存地址为 $n$ 位，Cache数据区大小为 $C$，主存块大小为 $B$，$k$ 路组相联：

1. **块内地址位数** = $\log_2 B$
2. **Cache总行数** = $C / B$
3. **组数** = Cache总行数 / $k$
4. **组号位数** = $\log_2$(组数)
5. **Tag位数** = $n$ - 组号位数 - 块内地址位数

📝 **2025年真题**：32位地址，Cache数据区32KB，8路组相联，块大小64B。
- Cache总行数 = 32KB/64B = 512行
- 组数 = 512/8 = 64组
- 块内地址 = $\log_2 64 = 6$ 位
- 组号 = $\log_2 64 = 6$ 位
- Tag = 32 - 6 - 6 = **20位**

### 四、替换算法

当Cache满了需要换出旧数据时，用什么策略？

| 算法 | 全称 | 原理 | 特点 |
|---|---|---|---|
| **FIFO** | First In First Out | 替换最早调入的块 | 简单，可能Belady异常 |
| **LRU** | Least Recently Used | 替换最久未被访问的块 | ⭐最常考，效果好，需要计数器 |
| **LFU** | Least Frequently Used | 替换被访问次数最少的块 | 需要计数器，不一定好 |
| **随机替换** | — | 随机选一块替换 | 最简单，效果不稳定 |

> ⚠️ **LRU的实现（考试常考）**：
> - 对于2路组相联：每行只需1位LRU位（0/1标记哪个更旧）
> - 对于4路组相联：需要2位LRU计数器
> - 一般n路组相联需要 $\lceil\log_2 n\rceil$ 位
> - 规则：访问某行时，该行计数器清0，比它小的不变，比它大或相等的+1。计数器最大的就是下一个要被替换的。

> 🔗 **跨科目联系**：Cache替换算法与OS中的**页面置换算法**（FIFO、LRU、OPT）原理完全相同！

### 五、写策略

写操作需要特别处理，因为Cache和主存可能数据不一致。

**写命中时**：

| 策略 | 操作 | 特点 |
|---|---|---|
| **写回法 (Write-Back)** | 只修改Cache，设**脏位(dirty bit)**=1，替换时才写回主存 | 减少写主存次数，需要脏位 |
| **全写法 (Write-Through)** | 同时修改Cache和主存 | 保持一致性，写操作慢（常配写缓冲） |

**写不命中时**：

| 策略 | 操作 | 配对 |
|---|---|---|
| **写分配法 (Write-Allocate)** | 先将主存块调入Cache，再在Cache中修改 | 通常与**写回法**配合 |
| **非写分配法 (Not-Write-Allocate)** | 直接写主存，不调入Cache | 通常与**全写法**配合 |

> 🗣️ **大白话**：
> - **写回法**：在草稿纸（Cache）上改就行了，等草稿纸要被擦掉（替换出去）的时候才把改动抄到正式本子（主存）上。
> - **全写法**：每次改内容，草稿纸和正式本子上同时改，确保两边一直一样。

> 📝 **2024年真题**：Cache-主存层次可采用回写法(Write-Back)写策略，主存-外存层次通常也采用回写法 ✅。但主存-外存层次不可能采用直接映射 ❌（通常采用全相联映射）。答案D。

### 五补充、Cache缺失分类（3C模型）与性能优化

**3C 缺失分类模型**（CSAPP/体系结构经典框架）：

| 缺失类型 | 英文 | 原因 | 优化方法 |
|:---:|:---:|:---|:---|
| **强制缺失** | Compulsory (Cold) | **首次访问**某块，Cache中尚无数据 | 预取技术（Prefetching） |
| **容量缺失** | Capacity | Cache**总容量太小**，无法容纳工作集 | 增大Cache容量 |
| **冲突缺失** | Conflict (Collision) | **映射策略**导致多个块竞争同一组/行 | 提高相联度（直接→组→全相联） |

> 🗣️ **大白话**：
> - **强制缺失**：第一次访问一定不在 Cache 里，就像第一次去图书馆借书，书架上还没放这本书
> - **容量缺失**：你的书架太小，放满了就要扔掉旧书再放新书
> - **冲突缺失**：书架上明明还有空位，但规定只能放在特定位置，那个位置已经被占了

**提高 Cache 命中率的三板斧**：
1. **增大 Cache 容量** → 减少容量缺失（但成本增加、访问延迟增加）
2. **提高相联度** → 减少冲突缺失（$k$ 路组相联，$k$ 越大冲突越少）
3. **优化程序的局部性** → 这是**程序员能做的最重要的事**：
   - **时间局部性**：最近用过的数据很快再用 → 循环中复用变量
   - **空间局部性**：相邻地址的数据会被一起用 → 数组按行遍历（与存储顺序一致）

> 🔗 **【跨学科联动·OS】** OS 中的页面置换算法（LRU、FIFO、OPT）与 Cache 替换算法原理完全相同！
> - Cache 的 LRU 替换 ↔ OS 的 LRU 页面置换
> - Cache 的直接映射 ↔ OS 的页表直接索引（以虚拟页号为索引）
> - **区别**：Cache 替换由**硬件**自动完成（速度要求极高），OS页面置换由**操作系统软件**完成

### 五补充2、完整存储访问地址计算公式速查

**Cache 地址划分**（物理地址）：

$$\text{物理地址} = \underbrace{\text{Tag（标记）}}_{t \text{ 位}} + \underbrace{\text{Index（组号/行号）}}_{s \text{ 位}} + \underbrace{\text{Offset（块内偏移）}}_{b \text{ 位}}$$

- $b = \log_2 B$（$B$ = 块/行大小，字节数）
- $s = \log_2 S$（$S$ = Cache组数；直接映射 $S = \text{Cache行数}$；全相联 $S = 1$，$s = 0$）
- $t = \text{地址位数} - s - b$

**Cache 总容量**（含标记和有效位）：

$$\text{总容量} = \text{Cache行数} \times (B \times 8 + t + 1 + \text{脏位等})\ \text{bit}$$

**平均访问时间**：

$$T_{avg} = H \cdot T_c + (1-H) \cdot (T_c + T_m)$$

其中 $H$ = 命中率、$T_c$ = Cache 访问时间、$T_m$ = 主存访问时间。

> ⚠️ **注意上式的两种理解**：
> - **先访问Cache**（串行发送）：$T_{avg} = H \cdot T_c + (1-H) \cdot (T_c + T_m)$
> - **同时访问Cache和主存**（并行传送）：$T_{avg} = H \cdot T_c + (1-H) \cdot T_m$
> - 考试题目会明确指出"先访问Cache"还是"同时访问"，看清再用公式！

### 六、Cache综合计算大题（⭐⭐⭐ 历年真题精选）

📝 **2010年真题（大题）**：主存256MB，按字节编址，数据Cache 8行，每行64B，**直接映射**。数组 int a[256][256] 按行优先存放，首地址320。

**（1）数据Cache总容量？**
- 地址28位（$2^{28}=256M$），块内地址6位（$2^6=64$），Cache行号3位（$2^3=8$）
- Tag = 28 - 6 - 3 = **19位** ，加上**1位有效位**
- 数据Cache总容量 = 8 × (64B + 20/8 B) = 8 × (64 + 2.5) = **532B**

**（2）a[0][31]和a[1][1]对应的Cache行号？**
- a[0][31]地址 = 320 + 31×4 = 444，444/64 = 6余60 → 主存块号6 → Cache行号 = 6 mod 8 = **6**
- a[1][1]地址 = 320 + 256×4 + 1×4 = 1348，1348/64 = 21余4 → 主存块号21 → Cache行号 = 21 mod 8 = **5**

**（3）程序A（按行访问）和程序B（按列访问）的命中率？**
- 每个Cache行存64B/4B = 16个int元素
- **程序A（按行遍历）**：每16个元素中，第1个未命中（加载新Cache行），后15个命中 → 命中率 = **15/16 = 93.75%**
- **程序B（按列遍历）**：每列256个元素，一行 = 256×4B = 1KB，Cache总容量 = 64×8 = 512B，一行是Cache的2倍！同一列的不同元素映射到同一Cache行时会互相替换 → 命中率 = **0%**！

> ⚠️ **极其重要的结论**：按行优先存储的二维数组，按行遍历Cache命中率远高于按列遍历！这就是为什么C语言中遍历数组要把行索引放在外层循环。

📝 **2025年真题**：32位字长，数据Cache 32KB，8路组相联，块大小64B，2个时钟周期命中，200个时钟周期缺失。数组 int d[2048] 起始地址 0180 0020H。
- 块内地址6位，组号6位（64组）
- d[100]的VA = 0180 0020H + 100×4 = 0180 01B0H
- d[100]所在块的Cache组号：VA的第11~6位 = 000110 = **6**
- 每块存64/4=16个int → 每16个元素第1个未命中 → 缺失率 = 1/16 ≈ **6.25%**... 
- 但考虑到d[0]的块内偏移为0x20(32字节)，第一块只放了(64-32)/4=8个元素，后续每块放16个。所以实际未命中 = 2048/16 + 1 = 129次，总访问2048次，缺失率 = 129/2048 ≈ **6.30%**... 真题答案：缺失率 129/4096 ≈ **3.15%** (此处真题可能按其他细节计算)

---

## 3.6 虚拟存储器与TLB

### 一、虚拟存储器的基本概念

**虚拟存储器**：在主存-辅存层次中，通过硬件+操作系统的配合，给用户提供一个远大于实际主存的"虚拟"地址空间。程序使用**虚拟地址（VA）**，硬件（MMU）将虚拟地址翻译为**物理地址（PA）**。

> 🗣️ **大白话**：你的电脑只有8GB内存，但操作系统告诉每个程序"你可以用4GB空间"（32位系统）。怎么做到的？操作系统把暂时不用的页面换到硬盘上，需要时再换回来——这就是"虚拟内存"。

### 二、页式存储中的地址转换

![虚拟存储器访问流程](图表/CO/CO-05_MemoryAccessFlow.png)

```
虚拟地址（VA）= 虚拟页号 + 页内偏移
                    ↓ 查页表
物理地址（PA）= 物理页框号 + 页内偏移（不变）
```

![TLB-Page-Cache时序](图表/CO/CO-08_TLB_Page_Cache.png)

### 三、TLB（Translation Lookaside Buffer，快表/页表缓存）

> ⚠️ **3种高频大题陷阱 (TLB-Page-Cache 联动)**：
> 1. **TLB缺失 vs 缺页**：TLB缺失（硬件查TLB没找到）**不一定**缺页（可能页表里有但在内存里，只是没缓存到TLB）。但**缺页**发生时，**TLB和Cache一定都未命中**（因为缺页意味着数据不在内存，更不可能在Cache）。
> 2. **全相联TLB**：TLB通常采用全相联映射（因为容量小，为了提高命中率）。这意味着TLB不需要索引位（Index），只看标记位（Tag）。
![TLB地址变换流程](图表/CO/CO-14_TLBTranslation.png)

> 3. **TLB命中 -> Page Hit -> Cache可能Miss**：TLB只负责地址翻译，Cache负责数据存取。地址翻译对了，数据可能不在Cache里。

**TLB + Cache + Page的访问流程 (秒杀口诀)**：
1. **CPU** 给出一个虚拟地址 (VA)。
2. **先查TLB**：
   - 🎯 **Hit**：拿到物理页号 -> 拼成物理地址 (PA) -> **直接去查Cache**。
   - ❌ **Miss**：**查页表 (Page Table)**。
3. **查页表** (慢表，在主存中)：
   - 🎯 **Hit** (Valid=1)：读出页表项 -> **更新TLB** -> 拿到物理地址 -> **去查Cache**。
   - ❌ **Miss** (Valid=0)：触发 **缺页异常 (Page Fault)** -> 操作系统接管 -> 调页 -> 更新页表 -> 重新执行指令。

> ⚠️ **秒杀结论表**：

| TLB | Page Table | Cache | 状态描述 |
|:---:|:---:|:---:|---|
| Hit | (必Hit) | Hit | **最佳情况**，全中，速度最快 |
| Hit | (必Hit) | Miss | 地址翻译快，但取数要访存 |
| Miss | Hit | Hit | TLB缺失，多访一次存查页表，数据在Cache |
| Miss | Hit | Miss | TLB缺失，Cache缺失，最慢的硬件流程 |
| Miss | Miss | (必Miss) | **缺页异常**，发生缺页中断，软件介入 |

📝 **2010年真题**：以下TLB/Cache/Page的命中组合，**不可能发生**的是？
- A. TLB未命中，Cache未命中，Page未命中 ✅（可能发生）
- B. TLB未命中，Cache命中，Page命中 ✅（可能发生）
- C. TLB命中，Cache未命中，Page命中 ✅（可能发生）
- **D. TLB命中，Cache命中，Page未命中 ❌（不可能！TLB命中说明Page一定命中！）**

📝 **2024年真题**：不是在MMU地址转换过程中检测的是？ → **B. Cache缺失**。MMU负责虚→实地址转换，会检测访问越权、缺页、TLB缺失。Cache缺失是在获得物理地址后才由Cache控制器检测的。

📝 **2025年真题**：VA 32位，物理地址30位，页大小1KB，TLB有32个表项，4路组相联，TLB标记位最少多少位？
- 虚拟页号 = 32 - 10 = 22位
- TLB组数 = 32/4 = 8组
- TLB组号 = $\log_2 8 = 3$ 位
- **TLB标记 = 22 - 3 = 19位**
- 答案：C. 19

### 四、虚拟地址→物理地址→Cache 完整访问流程（⭐ 大题模板）

**408 大题中经常考查"给一个虚拟地址，求 TLB/Page/Cache 各步操作和时间"**。以下是标准解题模板：

```
步骤1：拆分虚拟地址
  VA = [虚拟页号 VPN (高位)] + [页内偏移 VPO (低位)]
  VPO 位数 = log₂(页大小)

步骤2：查 TLB（用 VPN 查找）
  TLB组号 = VPN 的低几位（组相联时）
  TLB标记 = VPN 的高位
  ├── TLB Hit → 直接得到 PPN（物理页框号）→ 跳到步骤4
  └── TLB Miss → 步骤3

步骤3：查页表（用 VPN 索引）
  ├── Valid=1 → 得到 PPN，更新 TLB → 跳到步骤4
  └── Valid=0 → 缺页异常！OS调页 → 更新页表 → 重新执行

步骤4：拼接物理地址
  PA = [PPN] + [VPO]  （页内偏移不变！）

步骤5：用 PA 查 Cache
  PA = [Cache标记 Tag] + [Cache组号 Index] + [块内偏移 Offset]
  ├── Cache Hit → 直接读数据（最快）
  └── Cache Miss → 访问主存，数据调入Cache
```

**时间计算模板**：

$$T_{\text{总}} = T_{\text{TLB}} + \begin{cases} 0 & \text{TLB命中} \\ T_{\text{访存查页表}} & \text{TLB未命中} \end{cases} + \begin{cases} T_{\text{Cache}} & \text{Cache命中} \\ T_{\text{Cache}} + T_{\text{主存}} & \text{Cache未命中} \end{cases}$$

> ⚠️ **关键注意点**：
> 1. **VPO = PPO**：页内偏移在虚→实转换中**不变**，因此 Cache 的 Index 和 Offset 位可以在 TLB 查询的**同时**开始 Cache 查找（VIPT 优化）
> 2. **多级页表**：若为 $k$ 级页表，TLB Miss 时需访存 $k$ 次查各级页表
> 3. **写操作**：写 Cache 命中时，还需考虑写策略（写回法 vs 全写法）的额外开销

---

## 3.7 磁盘存储器

### 一、磁盘性能指标

$$存取时间 = 寻道时间 + 旋转延迟 + 传输时间$$

- **寻道时间**：磁头移动到目标磁道所需时间
- **旋转延迟**：平均半圈旋转时间 = $\frac{1}{2n}$（n为转速，单位：转/秒）
- **传输时间**：读写数据的时间 = 数据量 / 数据传输率

$$数据传输率 = 转速 \times 每条磁道容量$$

> 🔗 **跨科目联系**：磁盘调度算法（FCFS、SSTF、SCAN、C-SCAN）→ **OS第四章**文件系统

📝 **2024年真题**：磁盘调度CSCAN算法，磁道0~399，完成200号后向磁道号变小方向…→ 这是操作系统与计组的交叉考点。

---

## 📌 第三章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| Cache映射方式与地址计算 | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| Cache命中率计算 | ⭐⭐⭐⭐⭐ | 大题 |
| Cache写策略 | ⭐⭐⭐⭐ | 选择题 |
| Cache替换算法LRU | ⭐⭐⭐⭐ | 选择题 |
| TLB/Cache/Page的命中组合 | ⭐⭐⭐⭐ | 选择题 |
| 存储芯片扩展设计 | ⭐⭐⭐⭐ | 选择题、大题 |
| SRAM vs DRAM对比 | ⭐⭐⭐ | 选择题 |
| DRAM刷新方式 | ⭐⭐⭐ | 选择题 |
| 低位交叉编址 | ⭐⭐⭐ | 选择题 |
| 磁盘存取时间计算 | ⭐⭐ | 选择题 |

---

## 第四章 指令系统

> **本章考情**：每年2~3道选择题 + 近年大题趋势。重点：寻址方式与有效地址计算（★★★★★）、扩展操作码设计（★★★★）、x86汇编与机器码（★★★★，近年新增重点）、CISC/RISC对比（★★★）。2024/2025年真题都出了大题考指令格式+机器码+数据通路。

## 4.1 指令的基本格式

### 一、指令的组成

$$指令 = 操作码(OP) + 地址码(A)$$

- **操作码**：指明"做什么操作"（如加法、减法、跳转）
- **地址码**：指明"操作数在哪里"（寄存器编号或主存地址）

### 二、按地址码个数分类

| 类型 | 格式 | 指令含义 | 访存次数（执行期间） |
|---|---|---|---|
| **零地址** | OP | 空操作/停机；或堆栈计算机隐含操作数 | 0 |
| **一地址** | OP + A1 | `(ACC) OP (A1) → ACC`（ACC隐含） | 取指1次 + 读A1一次 |
| **二地址** | OP + A1 + A2 | `(A1) OP (A2) → A1` | 取指1次 + 读A1 + 读A2 + 写A1 |
| **三地址** | OP + A1 + A2 + A3 | `(A1) OP (A2) → A3` | 取指1次 + 读A1 + 读A2 + 写A3 |

> ⚠️ **注意**：指令总长度固定时，地址码个数越多→每个地址码的位数越少→寻址能力越差

### 三、定长指令字 vs 变长指令字

| 方式 | 特点 | 代表 |
|---|---|---|
| **定长指令字** | 所有指令长度相同，取指简单快速 | RISC（如ARM、RISC-V） |
| **变长指令字** | 不同指令长度不同，灵活但取指复杂 | CISC（如x86） |

---

## 4.2 扩展操作码（⭐常考计算题）

### 一、设计思想

当指令字长固定、操作码位数不同时，如何在同一指令字中实现不同长度的操作码？

**核心原则**：
1. 短操作码不能是长操作码的**前缀**
2. 各指令操作码不能重复
3. 高频指令分配**短操作码**（类似哈夫曼编码的思想）

### 二、经典扩展操作码设计

**例**：指令字长16位，地址码每个4位

```
三地址指令：| 4位OP   | 4位A1 | 4位A2 | 4位A3 |  → 0000~1110（15条），1111留作扩展标志
二地址指令：| 8位OP          | 4位A1 | 4位A2 |  → 1111 0000~1111 1110（15条）
一地址指令：| 12位OP                  | 4位A1 |  → 1111 1111 0000~1111 1111 1110（15条）
零地址指令：| 16位OP                          |  → 1111 1111 1111 0000~1111 1111 1111 1111（16条）
```

**通用公式**：上一层留出 $m$ 种状态不用（作为扩展标志），下一层可以扩展 $m \times 2^n$ 种指令（$n$ 为一个地址码的位数）。

> 🗣️ **大白话**：就像电话号码分配——110、120、119这些短号留给常用服务；更多的号码用更长的数字表示。"1111"就像一个"扩展前缀"，告诉CPU"后面还有更多操作码位"。

---

## 4.3 指令寻址

### 一、指令寻址（找下一条指令的位置）

| 方式 | 说明 |
|---|---|
| **顺序寻址** | `(PC) + "1" → PC`（PC自动加一个指令字长） |
| **跳跃寻址** | 由转移指令修改PC值 |

> ⚠️ **"加1"的含义**：PC每次增加的不是"数字1"，而是**一条指令的长度**。如果按字节编址、指令长度为4字节，则 PC+4。如果按字编址，则 PC+1。

---

## 4.4 数据寻址方式（⭐
![寻址方式与EA计算](图表/CO/CO-10_AddressingModes.png)
⭐⭐⭐⭐ 核心考点）

### 一、十种寻址方式汇总表

| 寻址方式 | 有效地址EA | 执行期间访存次数 | 特点/适用场景 |
|---|---|---|---|
| **立即寻址** | 操作数直接在指令中 | 0 | 最快，用于常数赋值，范围受限于地址码位数 |
| **直接寻址** | EA = A（指令中给出的地址就是操作数地址） | 1 | 简单，寻址范围受限 |
| **间接寻址** | EA = (A)（A单元的内容才是真正的操作数地址） | ≥2 | 可扩大寻址范围，速度慢 |
| **寄存器寻址** | EA = Ri（操作数在寄存器中） | 0 | 最常用，速度快 |
| **寄存器间接寻址** | EA = (Ri)（寄存器内容是操作数的主存地址） | 1 | 比一般间接寻址快 |
| **隐含寻址** | 操作数地址隐含在操作码中 | 0 | 如ACC隐含为目的操作数 |
| **基址寻址** | EA = (BR) + A | 1 | BR由**OS管理**（不变），A是偏移量，便于多道程序重定位 |
| **变址寻址** | EA = (IX) + A | 1 | IX由**用户改变**，A是基地址（不变），适合遍历数组/循环 |
| **相对寻址** | EA = (PC) + A | 1 | 便于程序浮动，广泛用于**转移指令** |
| **堆栈寻址** | 由SP隐含指向栈顶 | 硬堆栈0次，软堆栈1次 | LIFO结构 |

> 🗣️ **大白话**：
> - **立即寻址**："我直接告诉你答案是5"——操作数就在指令里
> - **直接寻址**："答案在100号箱子里"——告诉你地址，你去拿
> - **间接寻址**："答案在100号箱子里写的那个地址所指的箱子里"——告诉你地址的地址
> - **寄存器寻址**："答案在我左手里"——直接从寄存器拿，不用去主存
> - **基址寻址**：OS说"你的程序从第1000号位置开始"，指令里写"偏移50"，实际地址=1000+50=1050
> - **变址寻址**：程序员说"数组从第500号开始"，循环中IX依次为0,1,2,...，实际地址=500+IX

### 二、偏移寻址对比（⭐高频考点）

| 对比项 | 基址寻址 | 变址寻址 | 相对寻址 |
|---|---|---|---|
| 寄存器 | BR（基址寄存器） | IX（变址寄存器） | PC（程序计数器） |
| 谁修改寄存器 | **操作系统** | **用户/程序员** | **CPU自动** |
| 什么不变 | A（形式地址/偏移量） | A（基地址/起始地址） | A（偏移量） |
| 什么可变 | BR (由OS在程序加载时设置) | IX (在循环中递增) | PC (自动变化) |
| 主要用途 | **多道程序重定位** | **数组遍历/循环** | **转移指令/程序浮动** |

> ⚠️ **2011年真题**：不属于偏移寻址的是？ → **A. 间接寻址**。偏移寻址包括基址寻址、变址寻址、相对寻址（都是"寄存器+偏移量"的形式）。

### 三、相对寻址的解题要点（⭐⭐⭐ 反复考！）
![相对寻址PC时序](图表/CO/CO-11_PCRelativeTiming.png)

**关键坑**：计算相对寻址的有效地址时，PC已经指向了**下一条指令**（因为取指阶段PC就已经自动加了指令长度！）

📝 **2009年真题**：转移指令由两个字节组成，存放在2000H和2001H地址中。转移指令的地址码A=06H。问：转移目标地址？
- 取指后PC = 2000H + 2 = **2002H**
- 目标地址 EA = (PC) + A = 2002H + 06H = **2008H**。答案C。

📝 **2024年真题**：jmp指令在地址00401079H，占2字节（EB 09），PC指向下一条指令00401079H+2=0040107BH。
- 目标地址 = (PC) + 09H = 0040107BH + 09H = **00401084H** ✅

---

## 4.5 x86汇编与机器级代码（⭐近年新增重点）

> ⚠️ 这一部分是2019年后408大纲新增的重点，2023年起几乎年年出大题！

### 一、x86常用指令

| 类别 | 指令 | 功能 | 说明 |
|---|---|---|---|
| **数据传送** | `mov d, s` | d ← s | 最常用 |
| | `push r` | ESP-4，M[ESP] ← r | 压栈 |
| | `pop r` | r ← M[ESP]，ESP+4 | 弹栈 |
| **算术** | `add d, s` | d ← d + s | 影响标志位 |
| | `sub d, s` | d ← d - s | |
| | `inc d` | d ← d + 1 | |
| | `dec d` | d ← d - 1 | |
| | `imul / mul` | 有符号/无符号乘法 | |
| | `idiv / div` | 有符号/无符号除法 | 见下详解 |
| | `neg d` | d ← -d（取补） | |
| | `lea d, [addr]` | d ← addr（仅计算地址，不访存） | 常用于快速算术，如 `lea eax,[eax+eax*2]` 即 eax×3 |
| **逻辑** | `and / or / xor / not` | 位运算 | |
| | `shl d, n` / `shr d, n` | 逻辑左移/右移 | |
| | `sal d, n` / `sar d, n` | 算术左移/右移 | sar保留符号位 |
| **比较/跳转** | `cmp a, b` | 计算a-b但不保存结果，只设置标志位 | |
| | `test a, b` | 计算a AND b但不保存结果 | |
| | `jmp target` | 无条件跳转 | |
| | `je/jne/jg/jl/jge/jle` | 条件跳转 | |
| **循环** | `loop target` | ECX←ECX-1；若ECX≠0则跳转 | 不影响标志位 |
| **函数** | `call target` | push 返回地址；jmp target | |
| | `ret` | pop PC（从栈中弹出返回地址到PC） | |
| | `enter n, 0` | push ebp; mov ebp,esp; sub esp,n | 等价于3条入口指令 |
| | `leave` | mov esp, ebp; pop ebp | 等价于清理栈帧 |

### 补充：div/idiv 详解（⭐2025真题考点）

| 指令 | 被除数 | 商 | 余数 | 说明 |
|---|---|---|---|---|
| `div r/m32` | **EDX:EAX**（64位无符号） | → EAX | → EDX | 无符号除法 |
| `idiv r/m32` | **EDX:EAX**（64位有符号） | → EAX | → EDX | 有符号除法 |
| `div r/m16` | **DX:AX**（32位无符号） | → AX | → DX | |
| `idiv r/m16` | **DX:AX**（32位有符号） | → AX | → DX | |

> ⚠️ **关键陷阱**：
> - 执行 `idiv` 前必须使用 `cdq`（将EAX符号扩展到EDX:EAX）或 `cwd`（AX→DX:AX），否则EDX中的"脏数据"会导致除法结果错误
> - 若商超出目标寄存器范围 → 触发 **除法溢出异常（#DE，Divide Error）**，属于**故障（Fault）**类异常
> - 除数为0 → 同样触发 **#DE** 异常

📝 **2025年真题**：`idiv` 指令执行中产生异常，需判断异常类型及处理方式——属内部异常中的故障（Fault），处理后**重新执行**该条指令。

### 补充：lea 指令（Load Effective Address）

`lea` 只计算地址表达式的值，**不访问内存**，常被编译器用作快速算术：

```
lea eax, [ebx+ecx*4+8]   ; eax = ebx + ecx×4 + 8（纯算术，不读内存）
lea eax, [eax+eax*2]      ; eax = eax × 3（比 imul 快）
lea eax, [eax*4]          ; eax = eax × 4
```

> 💡 **区分**：`mov eax, [ebx+8]` 是去内存地址 `ebx+8` **读取数据**；`lea eax, [ebx+8]` 是把 `ebx+8` 这个**地址值本身**放入 eax。

### 补充：C语言 → 汇编 翻译模板（⭐⭐⭐ 大题高频）

**1. if-else 结构**

```c
if (a > b)          // C 源码
    x = 1;
else
    x = 2;
```
```asm
    mov  eax, [ebp-4]     ; eax = a
    cmp  eax, [ebp-8]     ; a - b，设置标志位
    jle  ELSE_BRANCH      ; 若 a ≤ b 则跳到 else
    mov  dword [ebp-12], 1; x = 1
    jmp  END_IF
ELSE_BRANCH:
    mov  dword [ebp-12], 2; x = 2
END_IF:
```

> 💡 **规律**：C中 `if(a>b)` 对应汇编中跳转条件取**反**（`jle`），跳到 else 分支。

**2. for/while 循环**

```c
int sum = 0;         // C 源码
for (int i=0; i<n; i++)
    sum += a[i];
```
```asm
    mov  dword [ebp-4], 0  ; sum = 0
    mov  dword [ebp-8], 0  ; i = 0
LOOP_START:
    mov  eax, [ebp-8]      ; eax = i
    cmp  eax, [ebp+8]      ; i - n
    jge  LOOP_END           ; 若 i ≥ n 则退出循环
    mov  ecx, [ebp-8]      ; ecx = i
    mov  edx, [ebp+12]     ; edx = a 的首地址
    mov  eax, [edx+ecx*4]  ; eax = a[i]（int 占4字节）
    add  [ebp-4], eax      ; sum += a[i]
    inc  dword [ebp-8]     ; i++
    jmp  LOOP_START
LOOP_END:
```

> 💡 **规律**：循环条件 `i<n` 对应 `jge LOOP_END`（条件取反跳出循环）；数组访问 `a[i]` 对应 `[base+index*scale]`。

> 📝 **2024年真题**：`sum+=a[i]` 的机器码分析——`slli` 实现 `i×4`，`add` 计算 `a+i×4`，`lw` 加载 `a[i]` 到寄存器。本质就是上述循环体的 RISC-V 版本。

### 二、AT&T格式 vs Intel格式

| 对比项 | AT&T格式（Linux/GCC） | Intel格式（Windows/MASM） |
|---|---|---|
| 操作数顺序 | `op 源, 目的` | `op 目的, 源` |
| 寄存器 | `%eax, %ebp` | `eax, ebp` |
| 立即数 | `$985` | `985` |
| 访存 | `(%eax)` 或 `偏移(%基址)` | `[eax]` 或 `[基址+偏移]` |
| 操作长度 | 指令后缀：b(1B)/w(2B)/l(4B) | `byte/word/dword ptr` |

### 三、函数调用栈帧（⭐大题高频）
![x86函数栈帧布局](图表/CO/CO-12_StackFrame.png)


```
高地址
┌──────────────┐
│ 调用者的参数   │  [ebp+12] = 第2个参数
│              │  [ebp+8]  = 第1个参数
├──────────────┤
│  返回地址     │  [ebp+4] = call指令压入的返回地址
├──────────────┤
│  旧的ebp      │  ← ebp 指向这里（当前栈帧的"底"）
├──────────────┤
│  局部变量1    │  [ebp-4]
│  局部变量2    │  [ebp-8]
│  ...         │
├──────────────┤
│ （空闲区域）   │  ← esp 指向栈顶
└──────────────┘
低地址
```

**函数调用过程**：
1. 调用者：将参数**从右到左**压栈，然后 `call` 指令（压返回地址+跳转）
2. 被调用者**入口**：`push ebp; mov ebp, esp`（保存旧栈帧底，建立新栈帧）
3. 被调用者分配局部变量：`sub esp, n`
4. 被调用者**返回**：`mov eax, 返回值; leave; ret`

> 📝 **2024年真题**：C语言代码 `sum+=a[i]` 对应机器码的分析——slli指令实现地址偏移量计算（i×4），add指令计算有效地址（基址+偏移量），lw指令加载数据。a的首地址在R3，i在R2，sum在R1。

---

## 4.6 CISC与RISC（⭐常考对比）
![CISC与RISC对比](图表/CO/CO-14_CISC_RISC.png)

| 对比项 | CISC | RISC |
|---|---|---|
| **指令数目** | 多（>200条） | 少（<100条） |
| **指令字长** | 不固定（变长） | **定长** |
| **可访存指令** | 不加限制 | 只有**Load/Store**可访存 |
| **各指令执行时间** | 相差较大 | 绝大多数一个周期完成 |
| **通用寄存器数量** | 较少 | **多** |
| **控制方式** | **微程序控制**（主） | **硬布线控制**（组合逻辑） |
| **流水线** | 可以实现（较难） | **必须实现** |
| **程序兼容性** | 向后兼容 | 不一定兼容 |
| **代表** | x86（PC） | **ARM**（手机）、RISC-V |

> 🗣️ **大白话**：
> - CISC就像瑞士军刀——功能多（指令多），但每个功能不一定高效，而且刀身（指令长度）参差不齐。
> - RISC就像一套标准化螺丝刀——每把长度一样（定长指令），功能简单但很高效，可以流水线大批量生产（必须实现流水线）。

> 📝 **2009年真题**：RISC的特点是？ → **A.** 指令长度固定，格式和寻址种类少，只有Load/Store访存，寄存器多，硬布线为主。

> 📝 **2025年真题**：关于RISC说法错误的是？ → **C. 难以采用流水线数据通路实现微架构**。恰恰相反，RISC的定长指令、简单译码专为流水线而设计！

---

## 4.7 汇编零基础一个月速成（⭐⭐⭐⭐⭐ 北大冲刺专用）

> **适用对象**：跨考、无编程底层背景、几乎没学过汇编。
>
> **目标**：30天内把“看懂汇编 + 做对408真题 + 反推机器级行为”打通，做到第四章和第五章联动拿分。

### 一、先建立最小认知框架（第一天必须吃透）

**你只需要先记住一句话：**

$$\text{汇编题本质} = \text{寄存器变化} + \text{内存地址计算} + \text{标志位驱动分支}$$

408里绝大多数汇编题，最终都在问以下四类：
1. 某条指令执行后寄存器是多少
2. 某个内存地址是怎么计算出来的
3. 条件跳转到底跳不跳（由标志位决定）
4. 函数调用后栈帧如何变化（参数、返回地址、局部变量）

> ⚠️ **反直觉提醒**：汇编不是背语法，而是“状态机追踪题”。你每一步只要跟踪：PC/寄存器/内存/标志位，就不会丢分。

### 二、408最小寄存器集合（只背高频，不贪全）

| 寄存器 | 作用 | 高频考法 |
|---|---|---|
| EAX | 累加器，函数返回值常放这里 | 返回值判断、算术链 |
| EBX/ECX/EDX | 通用寄存器 | 临时量、循环计数 |
| ESI/EDI | 源/目标索引寄存器 | 字符串/数组拷贝语义 |
| EBP | 栈帧基址（帧指针） | 参数和局部变量定位 |
| ESP | 栈顶指针 | push/pop、call/ret联动 |
| EIP/PC | 下一条指令地址 | 跳转目标、顺序执行 |
| EFLAGS | 条件码寄存器 | cmp/test后条件转移 |

**你只要做到：看到 `[ebp+8]` 就知道是第1个参数，看到 `[ebp-4]` 就知道是局部变量。**

### 三、标志位速通（条件跳转的核心）

最常用只看 4 个：
- **ZF（Zero Flag）**：结果是否为0
- **SF（Sign Flag）**：结果符号位
- **CF（Carry Flag）**：无符号进位/借位
- **OF（Overflow Flag）**：有符号溢出

`cmp a, b` 本质执行的是 `a-b`（不保存结果，只改标志位）。

**条件跳转秒杀表（高频）**：

| 跳转指令 | 条件 | 语义 |
|---|---|---|
| je / jz | ZF=1 | 相等 |
| jne / jnz | ZF=0 | 不等 |
| jg | ZF=0 且 SF=OF | 有符号大于 |
| jge | SF=OF | 有符号大于等于 |
| jl | SF≠OF | 有符号小于 |
| jle | ZF=1 或 SF≠OF | 有符号小于等于 |
| ja | CF=0 且 ZF=0 | 无符号大于 |
| jb | CF=1 | 无符号小于 |

> ⚠️ **超级大坑**：`jg/jl` 是有符号比较，`ja/jb` 是无符号比较。题目一旦把数据类型换成 unsigned，答案会翻转。

### 四、寻址表达式一把梭（看到就能算EA）

统一写成：

$$EA = Base + Index \times Scale + Disp$$

其中 `Scale ∈ {1,2,4,8}`，常用于数组元素大小（int 常见乘4）。

**例子**：
- `[eax]`：EA = eax
- `[ebp+8]`：EA = ebp + 8
- `[eax+ecx*4+16]`：EA = eax + ecx×4 + 16

> 💡 **一眼识别数组访问**：出现 `index*4`、`index*8` 基本就是在算元素地址（4字节int、8字节double或long long）。

### 五、函数调用与栈帧（大题稳分模块）

标准序言/尾声：
- 入口：`push ebp; mov ebp, esp; sub esp, n`
- 退出：`leave; ret`

**速记定位**：
- 参数区：`[ebp+8]`, `[ebp+12]`, ...
- 返回地址：`[ebp+4]`
- 旧ebp：`[ebp]`
- 局部变量：`[ebp-4]`, `[ebp-8]`, ...

> ⚠️ **阅卷友好写法**：大题中先画一个小栈帧图，再写推导过程。通常能明显减少因地址偏移写错导致的连锁丢分。

### 六、机器码/反汇编题的“4步判题模板”

1. **先分块**：把每条指令拆成“操作 + 源 + 目的”。
2. **再定宽度**：本题是按字节、字、双字还是64位。
3. **后追踪状态**：按执行顺序维护“寄存器表 + 关键内存表 + 标志位表”。
4. **最后验边界**：检查是否有符号扩展、溢出、移位补位、PC已自增。

> 💡 **做题工具建议**：每题单独画三列表：步骤号、状态变化、当前结论。不要在脑内算。

### 七、30天执行计划（零基础可落地）

#### 第1周：指令识字周（建立语感）
- Day 1-2：寄存器 + 数据传送指令（mov/push/pop）
- Day 3-4：算术逻辑（add/sub/and/or/xor/shl/shr/sar）
- Day 5：cmp/test + 条件跳转表
- Day 6：40道小选择，要求“读题30秒内判方向”
- Day 7：复盘错题，整理“指令-标志位-跳转”对照表

#### 第2周：寻址与栈帧周（拿下大题基础）
- Day 8-9：EA计算专项（Base+Index×Scale+Disp）
- Day 10-11：函数调用、参数传递、栈帧恢复
- Day 12：汇编 ↔ C语句互译（循环/if/数组）
- Day 13：做1套第四章专题题（限时）
- Day 14：复盘并形成“栈帧万能草图”

#### 第3周：真题强化周（汇编 + 数据通路联动）
- Day 15-17：2023/2024/2025真题中汇编与机器码相关题
- Day 18-19：把每题映射到“取指-译码-执行-访存-写回”
- Day 20：做1次90分钟小模考（第四章+第五章）
- Day 21：错题重做，输出“二次错误清单”

#### 第4周：冲刺周（把会做变成做对）
- Day 22-24：混合题训练（寻址 + Cache + 流水线）
- Day 25-26：只刷错题和同类变式题
- Day 27：背诵“必写模板”（EA、栈帧、Load-Use、标志位）
- Day 28：全真限时1套（严格计时）
- Day 29：查漏补缺（只补短板，不开新坑）
- Day 30：轻量复盘 + 状态调整

### 八、汇编高频失分点清单（考前每天看1遍）

1. 把 `cmp` 当成“会写回结果”的指令（错）
2. 忘记区分有符号跳转和无符号跳转
3. 相对寻址时忘了 PC 已指向下一条指令
4. `sar` 与 `shr` 混淆（算术右移保留符号位）
5. 栈向低地址增长，`push` 是先减 ESP 再写内存
6. 函数参数偏移写错（`[ebp+8]` 才是第1参数）
7. 看见数组却没意识到比例因子与元素字节数对应

### 九、和第五章联动的得分策略（你会直接提分）

- 学会汇编后，**数据通路微操作序列**会从“背诵题”变成“理解题”
- 看懂 `load/store/add/branch` 后，**流水线冲突**判断速度会明显提升
- 能读寄存器和访存行为后，**Cache命中分析**会更直观

> ✅ **阶段验收标准（务必达成）**：
> 1. 给你10条混合汇编，能在3分钟内写出关键寄存器终值；
> 2. 给你一段函数调用，能在2分钟内画出栈帧并定位参数/局部变量；
> 3. 给你一题真题反汇编，能在8分钟内完成“状态跟踪+结论”。

---

## 📌 第四章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 寻址方式与EA计算 | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| 相对寻址（PC自增陷阱） | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| 扩展操作码设计 | ⭐⭐⭐⭐ | 选择题 |
| x86汇编与机器码 | ⭐⭐⭐⭐ | 大题（近年新增） |
| 函数调用栈帧 | ⭐⭐⭐ | 大题 |
| CISC vs RISC | ⭐⭐⭐ | 选择题 |
| 指令格式分类 | ⭐⭐ | 选择题 |

---

## 第五章 中央处理器（CPU）

> **本章考情**：计组三大核心章之一，每年必考2~3道选择题 + 高频大题。重点：数据通路与微操作序列（★★★★★，大题必考）、硬布线/微程序控制器对比（★★★★）、流水线与冲突（★★★★★，大题高频）。本章约占计组总分的25%。

## 5.1 CPU的功能和基本结构

### 一、CPU的功能

| 功能 | 说明 |
|---|---|
| **指令控制** | 控制程序的执行顺序（取指令、分析指令） |
| **操作控制** | 产生操作信号序列，送往相应部件 |
| **时间控制** | 严格控制信号的时序 |
| **数据加工** | 执行算术和逻辑运算 |
| **中断处理** | 处理异常情况和特殊请求 |

### 二、CPU的基本结构

**运算器组成**：ALU、通用寄存器组、暂存寄存器、ACC、PSW（程序状态字）、移位器

**控制器组成**：PC、IR、指令译码器(ID)、MAR、MDR、微操作信号发生器、时序系统

> ⚠️ **用户可见 vs 不可见寄存器**：
> - **可见**（程序员可以通过指令访问）：通用寄存器(R0~Rn)、PC、PSW、ACC
> - **不可见**（CPU内部使用，程序员不能直接操作）：MAR、MDR、IR、暂存寄存器

### 三、数据通路的连接方式

| 方式 | 特点 | 优缺点 |
|---|---|---|
| **CPU内部单总线** | 所有寄存器挂在一条总线上 | 结构简单，但**同一时刻只能有一个源和一个目的**，存在数据冲突 |
| **CPU内部多总线** | 使用两条或三条总线 | 可同时传送多组数据 |
| **专用数据通路** | 各部件之间有专用连线 | 性能最高，但硬件量大 |

> ⚠️ **2025年真题**：关于数据通路说法错误的是？ → **A. 通用寄存器包含PC**。PC属于控制器，不是通用寄存器！

---

## 5.2 指令执行过程（⭐大题核心）

### 一、指令周期的划分

![指令周期状态机](图表/CO/CO-09_InstructionFSM.png)

$$指令周期 = 取指周期 + [间址周期] + 执行周期 + [中断周期]$$

- **指令周期** > **机器周期（CPU周期）** > **时钟周期（节拍）**
- 一个指令周期由若干个机器周期组成，一个机器周期由若干个时钟周期组成

**四个子周期**：

| 子周期 | 目的 | 访存操作 | 标志 |
|---|---|---|---|
| **取指周期** | 取指令 | 读 | FE=1 |
| **间址周期** | 取有效地址（间接寻址时才需要） | 读 | IND=1 |
| **执行周期** | 执行指令（取操作数、做运算等） | 读/写 | EX=1 |
| **中断周期** | 保存断点，转向中断服务程序 | 写（保存断点到栈） | INT=1 |

### 二、取指周期的数据流（⭐每年必考）

```
C1: (PC) → MAR              // 控制信号：PCout, MARin
    1 → R                   // 读命令
C2: M(MAR) → MDR            // 控制信号：MemR, MDRinE
    (PC) + 1 → PC           // 控制信号：PC+1
C3: (MDR) → IR              // 控制信号：MDRout, IRin
C4: OP(IR) → CU             // 指令译码
```

> 🗣️ **大白话**：取指就3步——① PC告诉"去哪个地址取指令"（PC→MAR），② 去那个地址读出指令（存储器→MDR，同时PC+1），③ 把指令放进指令寄存器（MDR→IR），然后CU开始解读操作码。

### 三、中断周期的数据流

```
C1: (SP)-1 → SP, (SP) → MAR  // 栈指针-1，送MAR
    1 → W                     // 写命令
C2: (PC) → MDR               // 断点（当前PC值）送MDR
    (MDR) → M(MAR)           // 断点写入堆栈
C3: 向量地址 → PC            // 中断服务程序入口送PC
    0 → EINT                 // 关中断
```

---

## 5.3 数据通路——单总线微操作序列（⭐⭐⭐ 大题重中之重）

> ⚠️ 这是408考试中**出大题频率最高**的知识点之一。2009年大题就考了这个，之后几乎每2~3年出一次。

### 一、单总线结构的核心规则

1. **每个时钟周期，总线上只能有一个数据源**（只能有一个"XXXout"信号有效）
2. ALU的输入端A和B不能同时从总线获取数据 → 需要**暂存寄存器Y（或A）**接收一个操作数
3. ALU的输出要送到暂存寄存器Z（或AC），再从Z送到总线
4. 访存数据必须经过MDR（外部数据总线DB）
5. 访存地址必须经过MAR（外部地址总线AB）

### 二、经典例题：ADD (R1), R0（⭐2009年真题原型）

功能：`(R0) + ((R1)) → (R1)`，即R0的值加上R1所指内存单元的值，结果存回R1所指内存单元

**取指周期（公共操作，所有指令相同）**：

| 时钟 | 功能 | 控制信号 |
|---|---|---|
| C1 | MAR←(PC) | PCout, MARin |
| C2 | MDR←M(MAR)，PC←(PC)+1 | MemR, MDRinE, PC+1 |
| C3 | IR←(MDR) | MDRout, IRin |
| C4 | 指令译码 | — |

**执行周期**：

| 时钟 | 功能 | 控制信号 | 说明 |
|---|---|---|---|
| C5 | MAR←(R1) | R1out, MARin | 将R1内容作为地址送MAR |
| C6 | MDR←M(MAR) | MemR, MDRinE | 从内存读出((R1))到MDR |
| C7 | A←(MDR) | MDRout, Ain | 操作数送暂存器A |
| C8 | AC←(A)+(R0) | R0out, Add, ACin | R0送ALU的另一个输入端，做加法 |
| C9 | MDR←(AC) | ACout, MDRin | 结果送MDR |
| C10 | M(MAR)←(MDR) | MDRoutE, MemW | 结果写回内存（MAR中地址没变） |

> ⚠️ **优化方案**：C6和C7可以合并——在C6读内存的同时（通过外部DB到MDR），可以用内部总线将R0送入A（因为R0→A走的是内部总线，不冲突）：

> 💡 **解题技巧**：做这类大题的关键是理清数据流向——
> 1. 画出数据通路图（题目一般会给）
> 2. 分析每一步需要什么数据从哪里到哪里
> 3. 检查是否有总线冲突（同一时刻不能有两个out）
> 4. 需要ALU运算时，一个操作数先送A/Y暂存器
> 5. 计算结果通过Z/AC暂存器再送出

---

## 5.4 控制器

### 一、硬布线控制器 vs 微程序控制器（⭐必考对比）

| 对比项 | 硬布线控制器 | 微程序控制器 |
|---|---|---|
| **工作原理** | 组合逻辑电路直接产生微操作信号 | 微操作信号存储在**控制存储器(CM)**中，读出执行 |
| **执行速度** | **快** | **慢**（需要从CM读取微指令） |
| **规整性** | 不规整，设计困难 | 规整，设计容易 |
| **可扩充性** | **困难**（修改要改电路） | **容易**（修改只需改CM内容） |
| **适用场景** | **RISC** CPU | **CISC** CPU |

> 🗣️ **大白话**：
> - **硬布线**：把所有控制规则都"焊死"在电路里。速度快但改不了——就像刻在石头上的菜谱，做菜快但想换菜就得重新刻。
> - **微程序**：把控制规则存在一个专门的存储器（控存）里。改规则只需改存储内容——就像写在纸上的菜谱，做菜慢一点但想换菜只需改纸。

> 📝 **2009年真题**：硬布线控制器的特点？ → **D. 指令执行速度快，指令功能的修改和扩展难**。

### 二、微程序控制器的核心概念

![微程序控制器结构](图表/CO/CO-10_MicroController.png)

| 概念 | 说明 |
|---|---|
| **控制存储器(CM)** | 存放所有微程序的ROM，在CPU内部 |
| **微程序** | 由若干微指令组成，对应一条**机器指令** |
| **微指令** | 微程序中的一步，由操作控制字段+顺序控制字段组成 |
| **微操作** | 不可再分的最基本操作（如PC→MAR） |
| **微命令** | 控制部件产生的控制信号 |
| **CMAR** | 微地址寄存器（存放下条微指令的地址） |
| **CMDR** | 微指令寄存器（存放当前正在执行的微指令） |

**关键关系**：
- 一条CPU指令 → 对应一个微程序
- 一个微程序 → 由多条微指令组成
- 一条微指令 → 可以发出多个微命令（并行微操作）
- **取指微程序**：所有机器指令共用同一个取指微程序

### 三、微指令的编码方式

| 编码方式 | 特点 | 优缺点 |
|---|---|---|
| **直接编码（直接控制）** | 每一位对应一个微操作信号 | 简单快速，但微指令字太长 |
| **字段直接编码** | 互斥的微操作分在同一段，每段独立译码 | 缩短字长，**每段需留一个全0状态**表示"本段不操作" |
| **字段间接编码** | 一个字段的含义取决于另一字段 | 进一步缩短字长，但译码复杂 |

> ⚠️ **字段直接编码的关键**：n位可以表示$2^n$种状态，但必须留一种表示"什么都不做"，所以实际只能控制 $2^n - 1$ 个互斥微操作。

### 四、微程序控制器的工作过程

```
① 取指令 → 用取指微程序（所有指令共用）完成
   取指后 OP(IR) → 微地址形成部件 → 得到该指令对应微程序的首地址 → 送入CMAR
② 执行微程序 → 按CMAR从CM读出微指令 → 送入CMDR
   CMDR的操作控制字段 → 产生微命令
   CMDR的顺序控制字段 → 确定下一条微指令的地址
③ 循环②，直到该微程序结束
④ 回到①，取下一条机器指令
```

---

## 5.5 指令流水线（⭐⭐⭐⭐⭐ 核心考点）

![流水线冲突](图表/CO/CO-04_PipelineHazard.png)

### 一、流水线的基本概念

**基本思想**：将指令执行过程分成多个阶段，各阶段在时间上**重叠**（overlap）执行不同指令的不同阶段。

> 🗣️ **大白话**：就像工厂流水线——第一个工人做第一道工序的同时，第二个工人已经在做上一个产品的第二道工序了。不需要等一个产品完全做好才开始做下一个。

### 二、流水线性能指标（⭐必考公式）

设流水线分 $k$ 段，每段耗时 $\Delta t$，处理 $n$ 个任务：

| 指标 | 公式 | 当$n \to \infty$时 |
|---|---|---|
| **吞吐率 TP** | $TP = \frac{n}{(k+n-1)\Delta t}$ | $TP_{max} = \frac{1}{\Delta t}$ |
| **加速比 S** | $S = \frac{k \cdot n}{k+n-1}$ | $S_{max} = k$ |
| **效率 E** | $E = \frac{n}{k+n-1}$ | $E_{max} = 1$ |

**时空图法计算**：画出时空图（横轴为时间，纵轴为流水段），数占满的格子数÷总格子数=效率。

> ⚠️ **时钟周期的设置**：取**各段中最长耗时**为流水线时钟周期。如果各段耗时不同，短段要等长段→效率下降。

**非均匀流水线（各段耗时不同）的计算**：

设 $k$ 段流水线，各段耗时分别为 $\Delta t_1, \Delta t_2, \ldots, \Delta t_k$：
- 时钟周期 $\tau = \max(\Delta t_1, \ldots, \Delta t_k)$
- 理想化 $n$ 条指令的总时间 $T = k \cdot \tau + (n-1) \cdot \tau = (k+n-1) \cdot \tau$
- 非流水线执行时间 $T_0 = n \cdot \sum_{i=1}^{k} \Delta t_i$
- $S = T_0 / T$，$TP = n / T$，$E = S / k$

**考虑停顿的实际 CPI 计算**（⭐ 大题核心公式）：

$$CPI_{\text{实际}} = CPI_{\text{理想}} + \text{停顿周期数}$$

对于理想流水线 $CPI_{\text{理想}} = 1$（每个时钟周期完成一条指令），因此：

$$CPI_{\text{实际}} = 1 + P_{\text{stall}} \times C_{\text{stall}}$$

其中 $P_{\text{stall}}$ = 发生停顿的概率，$C_{\text{stall}}$ = 每次停顿的周期数。

**例**：5段流水线，Load 占 30%，其中 50% 紧跟使用结果的指令（Load-Use），无条件转移占 15% 且总是预测错误（罚2周期），有旁路，则：
- Load-Use 停顿：$0.30 \times 0.50 \times 1 = 0.15$
- 分支预测失败停顿：$0.15 \times 2 = 0.30$
- $CPI_{\text{实际}} = 1 + 0.15 + 0.30 = 1.45$
- 实际加速比 $S = CPI_{\text{非流水}} / CPI_{\text{流水}} = 5 / 1.45 \approx 3.45$

> 📝 **2009年真题**：时钟周期应以最长的执行时间为准。答案A。

### 三、流水线的三种冲突（⭐⭐⭐⭐⭐）
![流水线冲突示意图](图表/CO/CO-15_PipelineHazards.png)

| 冲突类型 | 原因 | 解决方法 |
|---|---|---|
| **结构冲突（资源冲突）** | 多条指令同时争用同一硬件资源 | ① 暂停一个时钟周期（插入气泡） ② **指令Cache + 数据Cache分离**（哈佛结构） |
| **数据冲突（数据相关）** | 后续指令需要前面指令的计算结果，但结果还没算完 | ① 暂停/插入NOP ② **数据旁路（转发/前推forwarding）** ③ 编译优化调整指令顺序 |
| **控制冲突（控制相关）** | 转移指令可能改变PC，之前预取的指令可能无效 | ① **分支预测**（静态/动态） ② 延迟转移 ③ 预取两个分支方向 |

> 🗣️ **大白话**：
> - **结构冲突**：两个人同时要用一把剪刀→得排队
> - **数据冲突**：下一步需要上一步的结果，但上一步还没做完→得等
> - **控制冲突**：走到岔路口不知道该往哪走→猜错了要退回来重走

> 📝 **2010年真题**：不会引起指令流水线阻塞的是？ → **A. 数据旁路（转发）**。旁路技术恰恰是用来**消除**数据冲突引起的阻塞的！

### 四、数据冲突类型

| 类型 | 含义 | 在顺序发射流水线中是否发生 |
|---|---|---|
| **RAW (Read After Write)** | 写后读——后面的指令要读前面还没写好的数据 | ✅ 会发生（最常见） |
| **WAR (Write After Read)** | 读后写 | ❌ 不会（顺序流水线中写一定在读之后） |
| **WAW (Write After Write)** | 写后写 | ❌ 不会（顺序流水线中后写覆盖前写没问题） |

> ⚠️ WAR和WAW只在**乱序执行**的流水线中才可能发生。408选择题常考："按序发射的流水线中，只可能发生__冲突？" → **RAW**

### 五、数据旁路（转发）技术

**原理**：当前面的指令在EX段算出结果后，不用等到WB段写回寄存器，而是直接通过旁路线路将结果**转发**到后面指令需要数据的EX段输入端。

```
不用旁路（需要暂停2个周期）：
  ADD R1, R2, R3    IF  ID  EX  M  WB
  SUB R4, R1, R5    IF  ID  ×  ×  EX  M  WB    ← 等R1写回才能读
  
用旁路（无需暂停）：
  ADD R1, R2, R3    IF  ID  EX  M  WB
  SUB R4, R1, R5    IF  ID  EX  M  WB          ← EX段的结果直接转发
                              └──→ 旁路
```

> ⚠️ **Load-Use冲突 (大题高频陷阱)**
![Load-Use Stall](图表/CO/CO-17_LoadUseStall.png)
> **秒杀模型**：
> 1. 判断：前一条指令是 `LOAD`，且**目的寄存器**（如 `R1`）
是后一条指令的**源寄存器**。
> 2. 结论：如果流水线设计为标准的 `IF->ID->EX->MEM->WB`：
>    - 即使有全功能的**数据旁路 (Forwarding)**，**也必须暂停 1 个时钟周期**！
>    - 原因：`LOAD` 的数据在 **MEM段末尾** 才产生，而后续指令在 **EX段开头** 就需要。MEM在EX后面，时间不能倒流，必须等 1 周期让数据"追上来"。
>    - 代码中常见：`lw t0, 0(t1)` 后紧跟 `add t2, t0, t3` -> **必停！**

---

## 5.6 五段式指令流水线（⭐⭐⭐ 大题重点）
![五段流水线数据通路](图表/CO/CO-16_PipelineDataPath.png)

### 一、五个阶段


`IF → ID → EX → MEM → WB`

| 阶段 | 全称 | 功能 |
|---|---|---|
| **IF** | Instruction Fetch | 取指令，PC+4 |
| **ID** | Instruction Decode | 译码 + 读寄存器 |
| **EX** | Execute | ALU运算 / 计算有效地址 / 比较 |
| **MEM** | Memory Access | 访存（Load/Store时使用） |
| **WB** | Write Back | 写回寄存器 |

### 二、不同指令类型的流水段使用

| 指令类型 | IF | ID | EX | MEM | WB |
|---|---|---|---|---|---|
| **运算类** (ADD等) | 取指 | 读寄存器 | ALU运算 | **空段** | 写回结果 |
| **LOAD** | 取指 | 读基址寄存器 | 计算有效地址 | **从Cache读数据** | 写回寄存器 |
| **STORE** | 取指 | 读基址+数据 | 计算有效地址 | **写入Cache** | **空段** |
| **条件转移** (BEQ等) | 取指 | 读寄存器 | 比较+计算目标地址 | 修改PC | **空段** |
| **无条件转移** (JMP) | 取指 | 读偏移量 | 修改PC | **空段** | **空段** |

> ⚠️ **关键规则**：
> 1. 当前指令进入**ID段**后，下一条指令才能进入**IF段**（否则会覆盖IF/ID锁存器)
> 2. **运算类指令在EX段末尾**产生结果 → 转发到后续指令的EX段输入
> 3. **LOAD指令在MEM段末尾**产生结果 → 转发至少需要1个空周期

### 三、流水线冲突综合例题

![流水线冲突与旁路技术](图表/CO/CO-11_Forwarding.png)

```
指令1: LOAD R1, 0(R2)     IF  ID  EX  MEM  WB
指令2: ADD  R3, R1, R4    IF  ID  stall EX  MEM  WB    ← Load-Use，暂停1周期
指令3: SUB  R5, R1, R6        IF  stall ID  EX   MEM  WB  ← 受指令2暂停影响
指令4: AND  R7, R1, R8            stall IF  ID   EX   MEM  WB
```

> 📝 **2024年真题**：5段流水线RISC说法错误的是？ → **C. 所有数据冒险都可以通过加入转发（旁路）电路解决**。Load-Use冒险即使有旁路也需要暂停1个周期！

---

## 5.7 流水线多发技术与多处理器（了解）

### 一、多发技术

| 技术 | 原理 | 特点 |
|---|---|---|
| **超标量** | 每个时钟周期**发射多条**独立指令（需要多套功能部件） | 不能调整指令顺序，靠编译器优化 |
| **超流水** | 一个时钟周期内**分更多段**（如3段），一个功能部件使用多次 | 段间寄存器延迟增加 |
| **超长指令字(VLIW)** | 编译器把多条可并行的操作打包成一条**超长指令** | 依赖编译器，硬件简单 |

### 二、Flynn分类

| 类型 | 全称 | 特点 | 示例 |
|---|---|---|---|
| **SISD** | Single Instruction, Single Data | 传统单处理器 | 经典冯·诺依曼机 |
| **SIMD** | Single Instruction, Multiple Data | 一条指令处理多个数据 | GPU、向量处理器 |
| **MISD** | Multiple Instruction, Single Data | 多条指令处理一个数据 | 理论上不存在 |
| **MIMD** | Multiple Instruction, Multiple Data | 多条指令处理多个数据 | 多核CPU、集群 |

### 三、硬件多线程

| 类型 | 特点 |
|---|---|
| **细粒度多线程** | 每个时钟周期切换一个线程 |
| **粗粒度多线程** | 遇到长延迟事件（如Cache未命中）才切换线程 |
| **同时多线程(SMT)** | 每个周期可以从多个线程发射指令（Intel超线程技术） |

---

## 📌 第五章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 单总线微操作序列（数据通路+控制信号） | ⭐⭐⭐⭐⭐ | **大题**（几乎每2~3年考一次） |
| 流水线性能指标计算（TP/S/E） | ⭐⭐⭐⭐⭐ | 选择题、大题 |
| 三种冲突及解决方法 | ⭐⭐⭐⭐⭐ | 选择题 |
| 五段式流水线各段功能 | ⭐⭐⭐⭐ | 选择题、大题 |
| 硬布线 vs 微程序控制器 | ⭐⭐⭐⭐ | 选择题 |
| 微指令编码方式 | ⭐⭐⭐ | 选择题 |
| 数据旁路/转发技术 | ⭐⭐⭐ | 选择题 |
| Flynn分类 | ⭐⭐ | 选择题 |

---

## 第六章 总线

> **本章考情**：2025年大纲删除了"总线仲裁方式"和"总线标准"两个考点，使本章内容大幅精简。每年0~1道选择题，约占计组分值的3~5%。重点：总线带宽计算（★★★★）、定时方式（★★★）。

## 6.1 总线基本概念

### 一、总线的定义

📖 **总线**（Bus）：一组能为多个部件**分时共享**的公共信息传送线路。

两个关键特征：
- **分时**：同一时刻只允许一个部件向总线发送信息（但可以多个部件同时接收）
- **共享**：总线上可挂接多个部件

> 🗣️ **大白话**：总线就像一条单车道的马路——同一时间只能有一辆车在上面跑（发送数据），但路两边的人都可以看到车经过（接收数据）。

> ⚠️ **数据通路 ≠ 数据总线**：
> - 数据通路：数据流经的**路径**（逻辑概念，可能经过多种部件和线路）
> - 数据总线：承载数据的**物理介质**（一组导线）

### 二、总线分类

| 分类标准 | 类型 | 说明 |
|---|---|---|
| 按功能级别 | **片内总线** | CPU内部，寄存器↔ALU |
|  | **系统总线** | CPU↔主存↔I/O接口（最重要） |
|  | **通信总线（外部总线）** | 计算机系统之间 |

**系统总线的三类线**：

| 线路类型 | 方向 | 功能 |
|---|---|---|
| **数据总线(DB)** | **双向** | 传送数据，宽度=机器字长 |
| **地址总线(AB)** | **单向**（CPU→存储器/I/O） | 传送地址，宽度决定寻址范围 |
| **控制总线(CB)** | 双向 | 传送控制信号（读/写、中断请求等） |

### 三、系统总线结构

| 结构 | 特点 |
|---|---|
| **单总线** | CPU、主存、I/O设备都挂在一条系统总线上。简单，但带宽低、有瓶颈 |
| **双总线** | 主存总线 + I/O总线，通过通道或桥接器连接 |
| **三总线** | 主存总线 + I/O总线 + DMA总线 |
| **四总线(南北桥)** | 北桥→高速设备(内存/显卡)，南桥→低速设备(USB/声卡) |

---

## 6.2 总线性能指标与带宽计算（⭐⭐⭐⭐ 必考计算）

### 一、核心性能指标

| 指标 | 含义 | 关系 |
|---|---|---|
| **总线时钟频率** $f$ | 时钟振荡频率（如66MHz） | 基础参数 |
| **总线工作频率** $f_w$ | 每秒实际传送数据的次数 | 单沿：$f_w=f$，双沿：$f_w=2f$ |
| **总线宽度** $W$ | 一次能传输的数据位数（=数据线根数） | 如32位、64位 |
| **总线带宽** $B$ | 数据传输率（B/s或MB/s） | $B = f_w \times W/8$（B/s） |
| **总线周期** $T$ | 一次总线操作的时间 | $T = 1/f_w$ |

### 二、带宽计算公式

$$B = f_w \times \frac{W}{8} \quad (\text{B/s})$$

或等价地：$B = \frac{W}{T}$

### 三、经典例题

**例1**：总线时钟频率66MHz，每个时钟周期传送**两次**数据（双沿触发），数据线32根。

- 总线工作频率 $f_w = 2 \times 66 = 132$ MHz
- 总线带宽 $B = 132 \times 10^6 \times \frac{32}{8} = 528$ MB/s

**例2（突发传输/猝发传输）**：在上述总线上突发传输128位数据，总线周期 $T=1/132MHz \approx 7.6ns$

- 第1个总线周期：传送首地址
- 第2~5个总线周期：连续传送 $128/32=4$ 次数据
- 总传输时间 $= 5 \times 7.6ns \approx 38ns$

> ⚠️ **突发传输（猝发传输/Burst）**：只需传送一次首地址，之后**连续传**若干数据。适用于连续地址访问（如Cache行填充）。

> 📝 **2009年真题**：总线标准规定同时传输8bit数据，总线时钟频率66MHz → 带宽=66MB/s。注意题目问的是"同时传输"的位数，不是总线宽度！

> 📝 **2025年真题**：关于总线说法正确/错误的判断 → 要区分总线时钟频率与工作频率的差异（单沿/双沿）。

---

## 6.3 串行总线 vs 并行总线

| 对比项 | 并行总线 | 串行总线 |
|---|---|---|
| 传输方式 | 多根线同时传送 | 单根线按位传送 |
| 低频优势 | 速度快 | 速度慢 |
| 高频表现 | 线间干扰严重，频率受限 | 可不断提高频率 |
| **发展趋势** | — | ✅ **串行取代并行** |

> 🗣️ **大白话**：并行像8车道公路，车少时确实快；但车多到一定程度，各车道的车会互相干扰（线间串扰），反而堵住了。串行像单车道高铁，一条轨道上不断提速，最终比8车道公路还快。所以现在 USB、PCIe、SATA 都是串行！

---

## 6.4 总线定时方式（⭐⭐⭐）

| 方式 | 特点 | 优点 | 缺点 |
|---|---|---|---|
| **同步定时** | 统一时钟信号控制 | 简单、速度快 | 速度以**最慢设备**为准，可靠性差 |
| **异步定时** | "握手"信号，无统一时钟 | 自适应不同速度设备 | 控制复杂，速度较慢 |
| **半同步** | 统一时钟 + WAIT信号 | 兼顾同步简单性和异步灵活性 | — |
| **分离式** | 各模块独立申请总线 | 总线利用率**最高** | 控制最复杂 |

### 异步定时的三种握手方式

| 方式 | 过程 | 可靠性 | 速度 |
|---|---|---|---|
| **不互锁** | 双方各自定时，互不等待 | 最差 | 最快 |
| **半互锁** | 主方等从方回答后才撤销请求 | 中 | 中 |
| **全互锁** | 双方互相等待对方信号 | **最好** | 最慢 |

---
![总线仲裁链式查询](图表/CO/CO-17_DaisyChain.png)

> ⚠️ 2025年大纲已**删除**总线仲裁方式和总线标准，但偶尔仍可能出现在选择题选项中作为干扰项，了解即可。


> ⚠️ 2025年大纲已**删除**总线仲裁方式和总线标准，但偶尔仍可能出现在选择题选项中作为干扰项，了解即可。

| 方式 | 控制线数 | 优先级 | 特点 |
|---|---|---|---|
| 链式查询（菊花链） | 3 | 固定（近者优先） | 简单，但对故障敏感 |
| 计数器查询 | $\lceil\log_2 n\rceil + 2$ | 较灵活 | 可通过初值改变优先级 |
| 独立请求 | $2n+1$ | 最灵活 | 响应最快，但控制线多 |

---

## 📌 第六章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 总线带宽计算 | ⭐⭐⭐⭐ | 选择题（公式计算） |
| 串行/并行总线趋势 | ⭐⭐⭐ | 选择题 |
| 定时方式对比 | ⭐⭐⭐ | 选择题 |
| 总线基本概念（分时/共享） | ⭐⭐ | 选择题 |
| 总线仲裁（已删，了解） | ⭐ | — |

---

## 第七章 输入/输出系统

> **本章考情**：每年必考1~2道选择题 + 高频大题。重点：**程序中断方式**（★★★★★，大题必考之一，常与CPU时间/屏蔽字结合）、**DMA方式**（★★★★★，大题常考，尤其CPU占用时间计算）、四种I/O方式对比（★★★★）。本章约占计组总分的20%。

## 7.1 I/O系统概述

### 一、I/O控制方式发展（⭐⭐⭐⭐ 必考对比）

| 方式 | CPU参与度 | 数据传送单位 | 数据流向 | 适用场景 |
|---|---|---|---|---|
| **程序查询** | CPU全程"踏步"等待 | 字/字节 | I/O→CPU→内存 | 最简单，效率最低 |
| **程序中断** | 指令执行完毕后检测 | 字/字节 | I/O→CPU→内存 | 低速设备（键盘） |
| **DMA** | 仅预处理+后处理 | **数据块** | I/O→**内存**（不经CPU) | 高速设备（磁盘） |
| **通道** | 发I/O指令后完全不管 | 一组数据块 | 通道控制全流程 | 大型机 |

> 🗣️ **大白话**：
> - **程序查询**：你站在快递点门口一直等，什么也不干——等快递到了你亲自搬回家
> - **程序中断**：你回家干自己的事，快递到了打电话叫你——你再去搬
> - **DMA**：你告诉快递员"直接送到我家某个房间"——快递员自己送，送完打电话告诉你一声就行
> - **通道**：你请了个管家，告诉他"我需要某某东西"——管家全权负责，什么都不用你管

> ⚠️ **核心区别**：
> - 程序查询和中断：数据传送都要经过CPU（I/O→CPU→内存），区别在于CPU是否"等"
> - DMA：数据**不经过CPU**，由DMA控制器直接搬到内存
> - 中断方式中，CPU的响应发生在**每条指令执行完毕后**
> - DMA方式中，CPU的响应发生在**每个机器周期（存取周期）结束时**

---

## 7.2 I/O接口
![IO接口通用结构](图表/CO/CO-18_IOInterface.png)

### 一、I/O接口的功能


1. **数据缓冲**：协调CPU与外设的速度差异
2. **错误/状态检测**：监测外设的工作状态
3. **控制和定时**：接收CPU的控制命令并执行
4. **数据格式转换**：串→并、并→串的转换
5. **地址译码/选择**：识别本接口是否被选中

### 二、I/O接口的组成

| 组成 | 功能 | 统称 |
|---|---|---|
| 数据寄存器(DBR) | 暂存传输数据 | I/O端口 |
| 状态寄存器 | 记录设备状态（忙/闲/错误） | I/O端口 |
| 控制寄存器 | 存放CPU的控制命令 | I/O端口 |

### 三、I/O端口编址方式（⭐必考对比）

| 对比项 | 统一编址（存储器映射） | 独立编址（I/O映射） |
|---|---|---|
| **地址空间** | I/O端口与内存**共享**同一地址空间 | I/O端口有**独立**地址空间 |
| **访问方式** | 用**访存指令**（MOV等）访问 | 用**专用I/O指令**（IN/OUT）访问 |
| **区分方式** | 通过**不同地址码**区分 | 通过**不同指令**区分 |
| **优点** | 不需要专用I/O指令，灵活 | 程序清晰，不占用内存地址 |
| **缺点** | 占用内存地址空间，译码较慢 | 指令类型受限 |
| **典型应用** | **RISC处理器**（ARM，MIPS） | **x86处理器** |

> 📝 **2024年真题**：RISC-V处理器采用统一编址（MMIO），通过访存指令lw/sw访问I/O端口。

---

## 7.3 程序查询方式

CPU不断**轮询**设备状态寄存器，检查设备是否准备好。

```
loop:
   IN   AL, 状态端口      // 读取设备状态
   TEST AL, 80H            // 检查准备就绪位
   JZ   loop               // 没就绪就循环等
   IN   AL, 数据端口      // 就绪了，取数据
```

> ⚠️ **踏步等待**：CPU在检测循环中空转，做不了其他任何事情。这就是程序查询效率最低的原因。

---

## 7.4 程序中断方式（⭐⭐⭐⭐⭐ 大题最高频考点之一）

### 一、中断的基本概念

📖 **中断**：CPU在执行程序过程中，遇到急需处理的事件时，暂停当前程序，转去处理该事件，处理完毕后返回继续执行原程序。

### 二、中断分类

| 分类 | 类型 | 来源 | 示例 |
|---|---|---|---|
| **外部中断（硬件中断）** | 外部事件引发 | I/O设备、定时器 | 键盘输入、磁盘完成 |
| **内部异常** | 指令执行中产生 | CPU内部 | 除零、溢出、缺页 |

**内部异常的三种子类型（⭐2025真题考点）**：

| 子类型 | 英文 | 返回地址 | 处理后行为 | 典型示例 |
|---|---|---|---|---|
| **故障（Fault）** | Fault | 指向**引发异常的指令** | **重新执行**该指令 | 缺页异常、除法溢出(#DE)、段错误 |
| **陷阱（Trap）** | Trap | 指向**下一条指令** | 继续执行后续指令 | 系统调用(int 80h/syscall)、断点(int 3) |
| **终止（Abort）** | Abort | 不保存有意义的返回地址 | **终止进程**，不可恢复 | 硬件故障、控制器错误 |

> ⚠️ **考试区分要点**：
> - **Fault vs Trap 的本质区别**：Fault 返回重执行（因为操作"没做成"，如缺页后重新访存）；Trap 返回下一条（因为操作"已做完"，如系统调用已发起）
> - **缺页 = Fault**：OS 从磁盘调入页面后，**回到原指令重新执行**
> - **除法异常 = Fault**：`idiv` 除零或溢出时，返回到 `idiv` 指令处
> - **int 指令 = Trap**：`int 80h` 完成调用后，继续执行 `int` 后面的指令

📝 **2025年真题**：`idiv` 指令执行产生除法异常 → 属于**故障（Fault）**，中断处理后返回到 `idiv` 指令**重新执行**。

> ⚠️ **高频考点**：
> - **键盘输入** → 外部中断（I/O设备中断请求）
> - **除以零** → 内部异常
> - **缺页** → 内部异常
![中断处理全流程](图表/CO/CO-19_InterruptFlow.png)

> - **整数溢出** → 内部异常
> - **DMA传送完成** → 外部中断（DMA控制器发中断请求）

### 三、中断响应条件（3个条件缺一不可）

1. **有中断请求**（中断请求触发器=1）
2. **CPU处于开中断状态**（EINT=1，即中断允许触发器为1）
3. **当前指令执行完毕**

### 四、中断处理的全过程（⭐⭐⭐⭐⭐ 必背）

```
第一阶段：中断隐指令（硬件自动完成，非真正的指令）
    ① 关中断（IF=0）           → 防止中断处理被其他中断打断
    ② 保存断点（PC→栈/特定地址） → 记住断点以便返回
    ③ 获取中断服务程序入口地址 → 送入PC
       · 软件查询法：依次查询各中断源
       · 硬件向量法：由中断向量表直接提供（快！）
    
第二阶段：中断服务程序（软件执行）
    ④ 保护现场（PUSH 通用寄存器和PSW）  → 保存CPU现场
    ⑤ 中断服务（核心处理逻辑）           → 执行中断处理
    ⑥ 恢复现场（POP 通用寄存器和PSW）    → 恢复CPU现场
    ⑦ 中断返回（IRET，PC←断点地址）      → 返回被中断程序
```

> 🗣️ **大白话**：
> 你正在写作业（执行程序），突然电话响了（中断请求）。
> 1. 你先在作业本上**记下写到哪了**（保存断点）
> 2. 把你手上的笔和橡皮放好（保护现场）
> 3. 去接电话（中断服务）
> 4. 打完电话，拿回笔和橡皮（恢复现场）
> 5. 看看刚才写到哪了，继续做（中断返回）

> ⚠️ **"保存断点"和"保护现场"的区别**：
> - 保存断点：**硬件自动**完成，保存的是**PC**的值（回到哪条指令）
> - 保护现场：**软件（中断服务程序）**完成，保存的是**通用寄存器和PSW**（之前的运算状态）

### 五、中断判优——优先级规则

```
硬件故障 > 软件中断（异常）
非屏蔽中断(NMI) > 可屏蔽中断(INTR)
DMA请求 > I/O中断请求
高速设备 > 低速设备
输入设备 > 输出设备
```

### 六、单重中断 vs 多重中断（中断嵌套）（⭐⭐⭐⭐）

| 步骤 | 单重中断 | 多重中断 |
|---|---|---|
| 中断隐指令 | **关中断**、保存断点、送入口地址 | 同左 |
| 保护现场 | 保存通用寄存器 | 保存通用寄存器 |
| 保护现场**之后** | — | **开中断**（允许更高优先级中断嵌套进来） |
| 中断服务 | 执行 | 执行（可能被更高优先级打断） |
| 恢复现场**之前** | — | **关中断**（防止恢复现场被打断） |
| 恢复现场 | 恢复通用寄存器 | 恢复通用寄存器 |
| 恢复现场**之后** | **开中断**、中断返回 | **开中断**、中断返回 |

> ⚠️ **核心口诀**：
> - 单重中断：**保护现场之后不开中断** → 处理完一个再说
> - 多重中断：**保护现场之后开中断** → 允许高优先级打断
> - 两者都是在**恢复现场之前关中断**（恢复动作不能被打断！）

### 七、中断屏蔽技术（⭐⭐⭐⭐⭐ 大题重点）

![I/O中断处理流程](图表/CO/CO-07_InterruptFlow.png)

每个中断源对应一个**屏蔽字**（mask word），用来控制哪些中断源可以打断当前的中断服务。

**屏蔽字规则**：
- 中断屏蔽字中 **1=屏蔽（不允许中断）**，**0=允许**
- 屏蔽字中**"1"越多 → 优先级越高**（能屏蔽的中断越多）
- 每个中断源的屏蔽字**至少有一个"1"**（屏蔽自身，防止自己打断自己）

### 八、中断屏蔽字设计经典大题（⭐真题原型）

**题目**：4个中断源A、B、C、D，**硬件排队优先级**为A>B>C>D。现要求**中断处理次序**为D>A>C>B。设计各中断源的屏蔽字。

**分析**：处理次序D>A>C>B意味着：
- D能打断A、C、B（最高）
- A能打断C、B
- C能打断B
- B谁也打断不了（最低）

| 中断源 | 对A | 对B | 对C | 对D | 屏蔽字 | 含义 |
|---|---|---|---|---|---|---|
| A | **1**(自身) | **1**(屏蔽B) | **1**(屏蔽C) | 0(允许D) | **1110** | A屏蔽自身+B+C，允许D打断 |
| B | 0(允许A) | **1**(自身) | 0(允许C) | 0(允许D) | **0100** | B只屏蔽自身，其他都能打断 |
| C | 0(允许A) | **1**(屏蔽B) | **1**(自身) | 0(允许D) | **0110** | C屏蔽自身+B，允许A和D打断 |
| D | **1**(屏蔽A) | **1**(屏蔽B) | **1**(屏蔽C) | **1**(自身) | **1111** | D屏蔽所有，最高优先级 |

> 💡 **解题技巧**：列出处理次序后——
> 1. 对角线全部填1（每个屏蔽自身）
> 2. 某源X"优先于"某源Y → 在Y的屏蔽字中，X对应位填0（允许X打断Y）
> 3. 反之填1
> 4. 验证：屏蔽字中"1"的个数 = 处理次序中该源的级别

### 九、中断+DMA的CPU时间计算（⭐⭐⭐⭐⭐ 大题经典）

![中断vsDMA时间对照](图表/CO/CO-20_InterruptVsDMA.png)

> 📝 **2009年真题（大题）**：
> 
> 某处理器主频50MHz，CPI=4，设备D采用中断方式与CPU进行数据交换。
> 每次中断：中断响应需10个时钟周期，中断服务程序包含20条指令。
> 设备D每0.5ms发出一次中断请求。
> 
> (1) 对于设备D，CPU用于该设备I/O的时间占CPU总时间的百分比？
> 
> **解答**：
> - 总时钟周期：$50MHz \times 0.5ms = 25000$ 个时钟周期（两次中断之间）
> - 每次中断开销：响应 $10$ 周期 + 服务 $20 \times 4 = 80$ 周期 = $90$ 个周期
> - 占比 = $90 / 25000 = 0.36\%$
> 
> (2) 若改用DMA方式，每次DMA传送1000个字，DMA预处理和后处理各需500个时钟周期和100个时钟周期。CPU用于该设备的时间占比？
> 
> **解答**：
> - 传送1000个字需要 $1000 \times 0.5ms = 500ms$
> - 在500ms内，CPU只需要：预处理500周期 + 后处理100周期（含一次中断）= 600周期
> - 500ms内总周期：$50MHz \times 500ms = 25,000,000$ 周期
> - 占比 = $600 / 25,000,000 = 0.0024\%$
> 
> **真题启示**：DMA方式CPU占用率比中断方式低了**两个数量级**！这就是为什么高速设备必须用DMA。

> 📝 **2010年真题**：磁盘中断方式 vs DMA方式各占CPU时间百分比的计算。解法同上——列出各步骤的时钟周期数，求占比。

---
![DMA控制器结构](图表/CO/CO-15_DMAController.png)


## 7.5 DMA方式（⭐⭐⭐⭐⭐）

### 一、DMA控制器的组成

| 组件 | 功能 |
|---|---|
| **主存地址寄存器(AR)** | 存放当前要访问的主存地址 |
| **字计数器(WC)** | 记录还需传送多少个字 |
| **数据缓冲寄存器(DR)** | 暂存I/O设备与内存之间传输的数据 |
| **DMA请求触发器** | 每传完一个字，设备就发一次DMA请求 |
| **控制/状态逻辑** | 控制DMA传送过程 |
| **中断机构** | 传完一整块后，向CPU发中断（通知后处理） |

### 二、DMA传送过程

```
① 预处理（CPU执行）：
   · 设置 AR = 主存起始地址
   · 设置 WC = 传送字数
   · 设置传输方向（读/写）
   · 启动设备

② 数据传送（DMA控制器自动完成，CPU不参与！）：
   · 每个机器周期：设备→DR→内存（或反向）
   · 每次传完一个字：AR+1, WC-1
   · WC=0时 → 全部传完

③ 后处理（CPU执行，通过中断通知）：
   · 校验数据是否正确
   · 是否继续传送（有无后续数据块）
   · 异常处理
```

### 三、DMA与CPU共享主存的三种方式（⭐⭐⭐⭐）

| 方式 | 原理 | 优缺点 |
|---|---|---|
| **停止CPU访存** | CPU不访存，总线完全让给DMA | 简单，但CPU大量空闲 |
| **DMA与CPU交替访存** | 每个存取周期分成C1(DMA用)和C2(CPU用) | 不需要申请总线，但要求CPU时钟≥2倍存取频率 |
| **周期挪用（周期窃取）** | DMA需要时从CPU"偷"一个存取周期 | **最常用**，DMA传送不连续时效率高 |

> 🗣️ **大白话**：
> - **停止CPU**：你上厕所时把整个卫生间锁了，别人都不能进——霸道但简单
> - **交替访存**：你和室友约定"奇数分钟你用、偶数分钟我用"——互不干扰但要求时间精确
> - **周期挪用**：你正好要用卫生间的时候，发现室友占了一下——等他用完你再用，平时互不影响

### 四、DMA vs 中断方式对比（⭐⭐⭐⭐ 必考）

| 对比项 | 中断方式 | DMA方式 |
|---|---|---|
| **数据传送** | **软件**控制（CPU执行中断服务程序搬数据） | **硬件**控制（DMA控制器直接搬） |
| **响应时间** | **一条指令执行结束后**才能响应 | **每个机器周期结束**都可以响应 |
| **数据流向** | I/O → CPU → 内存 | I/O → **内存**（不经CPU） |
| **CPU参与** | 全程参与数据搬运 | 仅预处理和后处理 |
| **优先级** | 低于DMA | **高于中断** |
| **能否处理异常** | ✅ 能（中断服务程序可以做任何事） | ❌ 不能（只搬数据） |
| **适用设备** | 低速（键盘、打印机） | 高速（磁盘、网卡） |

> ⚠️ **为什么DMA优先级高于中断？** 因为DMA挪用的是**存取周期**，如果不及时响应，设备的数据缓冲区会溢出，数据就丢了。而中断只要在指令间隙响应即可，没那么紧急。

> 📝 **2009年真题Q22**：以下叙述中正确的是？ → **D. DMA方式中，数据传送由DMA控制器完成**。

---

## 7.6 磁盘存储器与RAID（⭐⭐⭐ 计算与核心概念）

### 一、磁盘存储器性能指标

**1. 存储容量**
- **非格式化容量** = 面数 × 磁道数 × 内圈周长 × 最大位密度
- **格式化容量（考点）** = 面数 × 磁道数 × 每道扇区数 × 扇区字节数
- > ⚠️ **注意**：格式化后容量比非格式化小（因为有间隔和控制信息）。

**2. 存取时间 $T_a$**
$$T_a = T_s + \frac{1}{2r} + T_t$$
- **寻道时间 $T_s$**：磁头移动到目标磁道（**最慢**，机械运动，ms级）
- **旋转延迟 $\frac{1}{2r}$**：平均转半圈的时间（$r$为转速）
- **传输时间 $T_t$**：读写数据本身的时间 = $\frac{b}{N \times r}$（$b$为字节数，$N$为每道字节数）

**3. 数据传输率 $D_r$**
$$D_r = r \times N$$
（转速 × 每道容量）

> 🗣️ **大白话**：你去图书馆找书。
> 1. **寻道**：走到正确的书架（最慢，腿断了）。
> 2. **旋转**：眼神扫描找到那本书（转半圈）。
> 3. **传输**：把书拿下来（很快）。

**4. 硬盘相关概念补充**
- **ZBR（区域位记录）**：外圈磁道周长长，扇区比内圈多（数据密度一致），外圈速度更快。
- **交替编号**：扇区物理编号间隔排列（1, 3, 5, ...），给控制器处理留时间，减少旋转等待。

### 二、RAID（廉价冗余磁盘阵列）

![RAID级别对比：0 vs 1 vs 5](图表/CO/CO-12_RAID.png)

| RAID级别 | 名称 | 原理 | 冗余/容错 | 空间利用率 | 读写性能 |
|---|---|---|---|---|---|
| **RAID 0** | 条带化 | 数据分块存到不同盘 | **无冗余**（坏一块全完） | 100% | 极高（并行） |
| **RAID 1** | 镜像 | 数据完全备份到另一块盘 | **100%冗余**（坏一块没事） | 50% | 读高，写慢 |
| **RAID 4** | 专用校验 | 专门一块盘存校验位 | 允许坏1块 | $(N-1)/N$ | 写性能差（校验盘瓶颈） |
| **RAID 5** | 分布校验 | 校验位分散在各盘 | 允许坏1块 | $(N-1)/N$ | 读写均衡，最常用 |

> 📝 **2025年真题**：关于RAID说法正确的是？ → RAID 5把校验块分散存储，避免了RAID 4的校验盘瓶颈。RAID 0无冗余。

### 三、显示器相关计算（偶而考）

$$\text{VRAM容量} = \text{分辨率} \times \text{灰度级位数}$$

$$\text{VRAM带宽} = \text{分辨率} \times \text{灰度级位数} \times \text{帧频}$$

例：1440×900分辨率，24位真彩色，60Hz
→ VRAM带宽 = $1440 \times 900 \times 24 \times 60 \div 8 \text{ (bit转Byte)} \approx 233,280,000 \text{ B/s} \approx 222 \text{ MB/s}$

---

## 📌 第七章 小结

| 考点 | 重要程度 | 常见题型 |
|---|---|---|
| 四种I/O方式对比 | ⭐⭐⭐⭐ | 选择题 |
| 中断处理全过程 | ⭐⭐⭐⭐⭐ | 选择题 + 大题 |
| 单重/多重中断对比 | ⭐⭐⭐⭐ | 选择题 |
| 中断屏蔽字设计 | ⭐⭐⭐⭐⭐ | 大题 |
| 中断/DMA的CPU时间占比 | ⭐⭐⭐⭐⭐ | 大题 |
| DMA vs 中断对比 | ⭐⭐⭐⭐ | 选择题 |
| DMA传送过程与三种共享方式 | ⭐⭐⭐⭐ | 选择题 |
| I/O端口编址方式 | ⭐⭐⭐ | 选择题 |

---

## 📊 全书总结：历年真题高频考点矩阵

| 章节 | 核心考点 | 出题形式 | 分值占比 | 考频 |
|---|---|---|---|---|
| 第一章 | 冯·诺依曼体系5大特点、性能指标CPI/MIPS | 选择 | ~2% | ★★ |
| 第二章 | 补码运算+溢出判断、IEEE754转换、类型转换 | 选择+大题 | ~25% | ★★★★★ |
| 第三章 | Cache映射/替换/写策略、TLB+Page+Cache三级 | 选择+大题 | ~25% | ★★★★★ |
| 第四章 | 扩展操作码设计、寻址方式(偏移)、CISC/RISC | 选择 | ~8% | ★★★ |
| 第五章 | 数据通路微操作、流水线冲突与性能计算 | 选择+大题 | ~25% | ★★★★★ |
| 第六章 | 总线带宽计算、定时方式 | 选择 | ~3% | ★★ |
| 第七章 | 中断处理+屏蔽字、DMA与CPU时间占比 | 选择+大题 | ~12% | ★★★★★ |

### 考试策略建议

1. **大题三大核心**（几乎年年出2道）：
   - 数据通路+微操作序列（第五章）
   - Cache/虚存地址计算（第三章）
   - 中断/DMA的CPU时间和屏蔽字（第七章）

2. **选择题高频陷阱**：
   - PC属于**控制器**，不是运算器！不是通用寄存器！
   - IEEE754的隐含"1"和偏移量（单精度127，双精度1023）
   - 补码的-128没有原码和反码
   - 相对寻址EA计算时，PC已经指向**下一条指令**
   - Cache写策略：写回法不立即改主存，全写法同时改
   - Load-Use冒险即使有旁路也需暂停1周期
   - DMA请求优先级**高于**中断请求（但DMA传完后用**中断**通知CPU）
   - RISC→硬布线控制器，CISC→微程序控制器

3. **计算题必备公式**：

| 公式 | 适用场景 |
|---|---|
| $CPU时间 = 指令数 \times CPI \times T$ | 性能比较 |
| $MIPS = \frac{f}{CPI \times 10^6}$ | 性能指标 |
| $H = \frac{N_c}{N_c + N_m}$ | Cache命中率 |
| $t_{avg} = H \times t_c + (1-H) \times t_m$ | 平均访存时间 |
| $TP = \frac{n}{(k+n-1)\Delta t}$ | 流水线吞吐率 |
| $S = \frac{kn}{k+n-1}$ | 流水线加速比 |
| $B = f_w \times W/8$ | 总线带宽 |

4. **🔗 与其他科目的联系**：

| 计组考点 | 关联科目 | 关联知识点 |
|---|---|---|
| Cache/虚存 | 操作系统 | 页面置换算法(LRU/FIFO)、段页式管理 |
| 中断 | 操作系统 | 进程切换、系统调用（陷入指令→内部异常） |
| 总线/DMA | 操作系统 | 设备管理、SPOOLing技术 |
| 指令流水线 | 操作系统 | 进程调度时需要保存/恢复流水线状态 |
| 存储层次 | 操作系统 | 文件系统的磁盘管理 |
| 浮点数表示 | 数据结构 | 数值算法的精度分析 |
| 补码运算 | 数据结构 | 哈希函数中的整数运算 |

5. **零基础跨考生30天计组冲刺执行法（重点）**：

   - **第1阶段（1-10天）**：只做“高频硬核”——补码/IEEE754/Cache映射/EA计算/基础汇编
   - **第2阶段（11-20天）**：专项突破大题模板——Cache计算、数据通路、流水线冲突、中断+DMA
   - **第3阶段（21-30天）**：全真限时 + 错题回炉，按“错因类型”复盘（概念错/计算错/审题错）
   - 每天固定输出一页“今日必背清单”：公式5条、陷阱3条、错题2道
   - 目标不是“看懂”，而是“限时做对”——计组冲刺期必须时间化训练

> ⚠️ **北大上岸导向提醒**：计组想成为拉分科目，关键不是再增加知识点，而是把高频模型训练到“秒判+稳算+少错”。第四章（汇编/寻址）和第五章（数据通路/流水线）是最容易形成竞争优势的组合。
## 七、408计算机组成原理高频失分陷阱速查表（⭐ 考前必看）

| # | 陷阱描述 | 正确结论 | 章节 |
|:---:|:---|:---|:---:|
| 1 | 补码 $-128$ 没有对应原码 | $[-128]_补 = 1000\ 0000$（8位），原码无法表示 $-128$ | Ch2 |
| 2 | 移码 = 补码符号位取反 | **仅对整数阶码成立**，且移码偏置值 = $2^{n-1}$（非IEEE偏置127） | Ch2 |
| 3 | IEEE 754 偏置值是 $2^{n-1}-1$ 而非 $2^{n-1}$ | 单精度偏置 = **127**（不是128），双精度 = **1023** | Ch2 |
| 4 | 浮点数对阶可以大阶向小阶 | 对阶时**小阶向大阶看齐**（右移尾数、丢失精度最少），不能反过来 | Ch2 |
| 5 | OF 和 CF 混淆 | **OF** = 有符号溢出，**CF** = 无符号进位/借位。同一运算可能 OF=1 而 CF=0 | Ch2 |
| 6 | 混淆 Cache "行" 和 "组" | **行(Line)** = 最小存储单元；**组(Set)** = $k$ 行的集合（$k$ 路组相联） | Ch3 |
| 7 | Cache 容量只算数据部分 | 总容量 = 行数 × (**数据** + **标记** + **有效位** + 脏位等)，不漏标记位！ | Ch3 |
| 8 | TLB 命中就不会缺页 | ✅ 正确！反之：**缺页 → TLB一定Miss且Cache一定Miss** | Ch3 |
| 9 | 直接映射冲突率最低 | **直接映射冲突率最高**（只有一个候选位置！），全相联最低 | Ch3 |
| 10 | 扩展操作码"留码"算错 | 高位用掉的编码数 → 留给下层 → **先算留码空间再扩展** | Ch4 |
| 11 | `lea` 和 `mov` 混淆 | `lea eax,[ebx+4]` → eax=ebx+4（**不访存**）；`mov eax,[ebx+4]` → **要访存** | Ch4 |
| 12 | 忘记 `div` 隐含操作数 | x86 `div r32` 被除数在 **EDX:EAX**（64位÷32位）；`div r8` 被除数在 **AX** | Ch4 |
| 13 | 旁路能解决所有数据冲突 | **Load-Use** 即使有旁路也需**暂停1周期**（MEM段末才出数据） | Ch5 |
| 14 | 按序流水线有WAR/WAW冲突 | ❌ 按序流水线**仅有RAW**。WAR/WAW只在**乱序执行**出现 | Ch5 |
| 15 | 中断响应 = 中断处理 | **响应**（硬件自动）≠ **处理**（软件执行中断服务程序） | Ch7 |
| 16 | DMA 完全不需要CPU | DMA **预处理和后处理由CPU完成**，仅数据传送阶段不需CPU | Ch7 |
| 17 | 总线带宽 = 频率 × 数据宽度 | DDR 上升沿+下降沿各传一次 → **×2**；QDR → **×4** | Ch6 |
| 18 | 机器字长=存储字长=指令字长 | 三者**可以不同**！分别取决于 ALU/通用寄存器、MDR、指令格式 | Ch1 |