计算机组成原理模块。计组的“字母表”:后续指令系统(CO-2)、CPU(CO-4)、存储(CO-3)中一切地址、数据、标志位的计算都建立在本模块之上。
核心问题
这一部分为什么存在?
硬件只能存储和翻转 0/1。要让电路做数学,必须先回答一连串“编码决策”:
- 负数怎么表示:直接用符号位(原码)会让 0 有两种表示、加减要分情况设计两套电路——硬件太贵。需要一种“加减统一、0 唯一”的编码 → 补码。
- 加减结果超范围怎么办: 位只能表示有限个数,运算可能溢出,硬件必须能检测并报告 → 溢出判断逻辑(OF)。
- 很大/很小的数怎么表示:定点数范围与精度互相锁死 → 用“科学计数法”把指数也存进去 → 浮点数(IEEE 754)。
- 多个字节怎么排:一个 int 占 4 字节,高字节放低地址还是高地址 → 大端/小端;按几字节对齐存放 → 边界对齐。
每一个决策都直接决定运算器(ALU)怎么造、标志位怎么设、指令怎么设计。没有统一的编码约定,后续一切硬件设计无从谈起。
概念体系
flowchart TD
A["硬件只有 0/1"] --> B["负数编码:原码→反码→补码<br/>(加减统一、0 唯一)"]
A --> C["浮点:IEEE 754<br/>符号 | 阶码(移码) | 尾数(隐藏 1)"]
B --> D["n 位范围有限<br/>→ 溢出判断 OF"]
B --> E["移位 = 快速 ×2 / ÷2<br/>算术 vs 逻辑"]
C --> F["浮点加减五步<br/>对阶→尾数加减→规格化→舍入→判溢出"]
A --> G["多字节存储约定<br/>大端/小端 + 边界对齐"]
B & C --> H["C 类型转换<br/>位扩展/截断/精度丢失"]
核心概念:
| 概念 | 要点 | 易考点 |
|---|---|---|
| 原/反/补/移码 | 补码:负数 = 按位取反 + 1;移码 = 补码符号位取反,用于阶码 | 补码范围 ,负数比正数多一个(2022-13); 位中“3 个 1、5 个 0”的最小补码是 −125(2015-13) |
| 溢出 | 结果超出 位表示范围;只有同号相加/异号相减才可能溢出 | 与进位 CF 无关:CF 服务无符号数,OF 服务带符号数(2018-19) |
| 机器字长 | CPU 一次能处理的位数;ALU 与通用寄存器宽度 = 机器字长,指令寄存器/浮点寄存器不一定(2020-12) | |
| IEEE 754 单精度 | 1 符号 + 8 阶码(移码偏置 127)+ 23 尾数(隐含 1.);值 | 规格化范围:最小规格化正数 (2018-14);最大约 (2012-14) |
| 非规格化数 | 阶码全 0:表示 0 附近的极小值,无隐含 1 | 2023-14(8020 0000H = ) |
| 大端/小端 | 大端:高字节放低地址;小端相反 | 按字节编址下求“某字节的内容/地址”(2016-14、2019-15) |
实现机制
1. 补码运算与溢出判断(来源:复习资料 P2 §5)
补码的精髓:减法 = 加“取反加 1”,带符号与无符号加法的位级运算完全相同,可用同一套加法器(2011-43 结论);区别只在标志解释——带符号看 OF,无符号看 CF。
溢出判断两法:
| 方法 | 规则 |
|---|---|
| 单符号位(最高进位法) | (符号位进位 ⊕ 最高数值位进位) |
| 双符号位(变形补码) | 结果双符号 00/11 正常,01 正溢出、10 负溢出 |
口诀:正 + 正 = 负、负 + 负 = 正 → 溢出;正 + 负永不溢出。真题:2010-13(r1×r2 等四则运算谁溢出)、2014-13(x=103, y=−25 的 8 位补码运算)、2021-13(FFFDH 等机器数判关系)、2018-19(sub 后 CF 与 OF 各是多少)。2022 年大题更要求写出 、 关于 的逻辑表达式——把“口诀”落实到门电路。
2. 移位:廉价的乘除 2
| 逻辑移位 | 算术移位 | |
|---|---|---|
| 用途 | 无符号数、位操作 | 带符号数 |
| 左移 | 补 0(=×2,可能溢出) | 补 0 |
| 右移 | 补 0 | 补符号位(=÷2 向下取整) |
陷阱:负数算术右移补 1——−1088(FBC0H)算术右移 4 位 = FFBCH(−68),不是 0FBCH(来源:复习资料 P2 §5.2,7 月月考 13 题错点)。
3. IEEE 754 浮点加减五步(2009-13 模板,来源:复习资料 P2 §6)
- 对阶:小阶向大阶看齐(为什么:对齐小数点才能加尾数;小阶改是因为大阶改会丢高位),阶差 → 小阶尾数右移 位;
- 尾数加减(补码);
- 规格化:尾数溢出(双符号 01/10)→ 右规(右移 1 位、阶码 +1);不够规格 → 左规;
- 舍入:0 舍 1 入 / 恒置 1 / 截断(舍入可能再次破坏规格化,需复检);
- 判溢出:看阶码是否超范围(双符号阶码 01/10)。
关键认识(2015-14):尾数溢出不一定真溢出(右规可挽救),阶码上溢才是真溢出;右规和舍入都可能引起阶码上溢。float 不能精确表示 1.2(二进制小数无限循环)但可以表示 1.25、2.5(2021-14)。
4. C 类型转换(大题常客)
- int → float:32 位 int 的全部位都“有效”,float 尾数只有 24 位(含隐含 1)→ 大整数会舍入失真;int → double 无失真;float → int 直接截断小数(可能整体溢出)。
- 2017 年大题:f2(127) 机器数 7F80 0000H( 的下一值?实为 量级溢出点)→ 不溢出最大 n、精确(无舍入)最大 n 的两问,考的就是“float 精度 24 位”这一本质。
- 无符号 ↔ 带符号同长转换:位模式不变,解释改变(2016-13:
unsigned short usi = si得 32769);短 → 长:带符号数符号扩展,无符号数零扩展。
5. 大端/小端与对齐
小端机器 double 1122 3344 5566 7788H 存于 8040H 起,8046H 单元内容 = 33H(2016-14:低地址存低字节 88,77,66,55,44,33,22,11)。大端 + 基址寻址综合:2019-15 求操作数 LSB 所在地址(先算有效地址,再按大端推出 LSB 在 EA+3)。
方案比较
| 编码 | 0 的表示 | 加减电路 | 范围( 位) | 用途 |
|---|---|---|---|---|
| 原码 | 两种(±0) | 需分正负两套逻辑 | 浮点尾数 | |
| 反码 | 两种 | 循环进位,仍麻烦 | 同原码 | 过渡 |
| 补码 | 唯一 | 加减统一一套加法器 | 定点整数(默认) | |
| 移码 | 唯一 | 便于比大小(保序) | 同补码 | 浮点阶码 |
定点 vs 浮点:定点电路简单、运算快、精度均匀但范围小;浮点以“尾数精度”换“指数范围”,但数轴上分布不均匀(越靠近 0 越密)——所以 float 能精确表示 2.0 却不能精确表示 1.2,大整数 int→float 会失真。
大端 vs 小端(易混对):为什么易混——只是字节排列顺序,数值完全相同。判别线索:题目给“内存单元地址从低到高的字节序列”→ 小端要倒着读;x86 默认小端,网络字节序(计网报文)是大端——这是与 CN 的隐性连接。
应用与考法
形态一:机器数 ↔ 真值换算(每年必考):2011-13(−8.25 → C104 0000H)、2013-13(C640 0000H 求真值)、2014-14(两个 float 机器数比大小)、2018-13(x−y 机器数与溢出)、2020-13(C800 0000H 是 int 还是 float)、2022-14(−0.4375 → BEE0 0000H)、2023-14(非规格化数)。
形态二:溢出与标志位:2010-13、2014-13、2015-14、2018-19、2021-13;大题 2011-43(溢出判断 + 无符号/带符号共用加法器)、2019 大题(imul 溢出条件与异常处理指令)、2020 大题(umul/imul 的 2n 位乘积与溢出判断)、2022 大题(SF/OF 逻辑表达式)。
形态三:浮点运算流程:2009-13(五步全算)、2015-14(叙述辨析)、2012-14(最大规格化数)、2018-14(最小规格化正数 )。
形态四:类型转换与存储:2010-14(int/float/double 关系表达式)、2016-13/14、2017 大题(float 精度与溢出边界)。
做题触发词:看到“机器数 + 补码/IEEE 754”→ 先切字段再代入公式;看到“8 位运算”→ 警惕溢出;看到“寄存器内容 + float”→ 按 S|E|M 还原;看到“ unsigned 与 int 混合”→ 隐式转换为无符号(补充理解:C 规则,真题大题常据此设坑)。
来源:真题markdown/2009-2024统考真题.md 对应题号;复习资料 P2 §5–6。
前后联系
- 向前依赖:CO-0(机器字长、性能指标——FLOPS,2011-12、2021-12)。
- 向后引出:
- 补码偏移量 → 指令系统的相对寻址/基址寻址(CO-2;2010-16? 实为 2014-17、2019-15 均综合补码偏移);
- ALU 与标志位 → CO-4 数据通路(运算器是数据通路核心;条件转移依赖 CF/ZF/SF/OF,2011-17);
- 地址本质是补码/无符号整数 → Cache 地址切分(CO-3)、虚存地址(X-1);
- 大端/小端 → 计网“网络字节序 = 大端”(CN 隐性连接);
- int→float 精度问题 → DS/程序设计中浮点比较陷阱(理解级)。
闭卷回忆链
- 为什么不用原码做加减?补码解决了哪两个问题?(两套电路 → 一套;±0 → 唯一)
- 补码怎么快速求负? 位补码范围?为什么负数多一个?
- 带符号和无符号加法硬件上有何关系?各自看哪个标志?
- 什么情况下才可能溢出?两种判断法分别怎么看?
- 算术右移补什么?负数右移的陷阱是什么?
- IEEE 754 单精度三个字段各多少位?值怎么算?为什么用移码存阶码?
- 最大/最小规格化正数是多少?阶码全 0 表示什么?
- 浮点加减为什么先对阶?向谁看齐、为什么?
- 尾数溢出和阶码溢出哪个是真溢出?右规和舍入会引发什么?
- 为什么 float 表示不了 1.2 却能表示 1.25?int 转 float 何时失真?
- 大端小端差在哪?给定字节序列怎么读一个 int?
- 这些编码决策如何进入指令寻址、ALU 标志位和条件转移?(接 CO-2/CO-4)