Appearance
数据表示与运算:换副眼镜读同一串位,用加减和移位拼出乘除(专题总纲)
Intro
这一类题的题面看着五花八门:有时候是一段 C 程序,有时候是一个求和函数,有时候直接甩给你一张除法器的逻辑结构图。
但机器里只有三样东西:
一串位、一个解释这串位的约定、和一个只会做加减和逻辑运算的 ALU,外挂一个移位器。
于是小问也只有两个去向:要么在问换个约定去读这串位会读出什么、这个约定读到头是多少,要么在问只有加减和移位,怎么把乘除拼出来。
四道真题按主场分:
- 2011-43 的 (1)(2)(4) 三问在第一边——同一串 8 位在 unsigned 与 int 两副眼镜下读出两个值;
- 2017-43 的五问全在第一边——unsigned 减法回绕、int 与 float 两套表示能力、IEEE 754 的特殊编码,都是「换约定读」;
- 2020-43 主场在第二边——没有乘法指令怎么用加和移位实现,以及乘积截断之后按两副眼镜各读一遍;
- 2025-44 主场也在第二边——补码除法器的初值怎么装、ALUop 只需要控制哪几种运算。
两处例外要说清楚。 2011 那道的第 (3) 问(四种运算能否共用一个加法器)其实站在第二边:加法器只做模
四个动作,可以数得清
| 手上拿到的 | 动作 | 题面长什么样 |
|---|---|---|
| 一串位 + 一个约定 | 读:按约定把位串翻成真值,或把真值码成位串 | 机器数是什么(用十六进制表示)、7F800000H 对应的值是什么 |
| 一串位 + 两个约定 | 换:位串一位不动,只换读法 | int m = x; 之后 m 是多少、截低 32 位后 umul 与 imul 谁溢出 |
| 一个约定 | 量边界:这个约定装得下的最大 / 最小是多少 | 最大的 n 是多少、结果会不会溢出、什么时候还精确 |
| 只会加减和移位的 ALU | 拼:把乘、除拆成一串加减和移位 | 没有乘法指令为什么也能做乘法、除法器的 R/Q/Y 装什么 |
读、换、量边界、拼——四道真题的大部分小问落在这四格里。落在格外的约 7 分:2020 的 (2)(3) 问乘法器的控制逻辑与三种实现的快慢(控制器那一章)、2025 的 (2) 后半问异常响应过程(CPU 的异常与中断机制)。本文最后一节把它们单列出来。
换:位串一位不动,只换读法
这是整个专题的地基。int m = x; 在机器层面只是寄存器到寄存器的拷贝,位模式原样搬过去,变的只有解释规则:
- 2011 年那道:
1000 0110B当 unsigned 读是 134,当补码读是; - 2017 年那道:
FFFFFFFFH当 unsigned 读是,当 int 读是 ; - 2020 年那道:
FFFF FFFEH当 unsigned 读是 4294967294(合法),当 int 读是(与真实乘积差得远)。
差别只在最高位的位权:无符号把它算作
量边界:先问「卡在哪个字段上」
「最大的 n 是多少」这种问法,答案完全取决于卡住它的是哪一段位。2017 年那道在同一小问里问了两次:
| 问的是 | 卡在哪 | 边界 | 答案 |
|---|---|---|---|
| f2(n) 不溢出 | 阶码字段 | 有限数的阶码最大到 254 | |
| f2(n) 精确(无舍入) | 尾数字段 | 23 位显式加 1 位隐含 = 24 位有效精度 | |
| f1(n) 与 f(n) 相等 | int 的位数 |
三问三个数,因为卡点是三个不同的字段。先定卡点,再算数。
拼:ALU 只会加减和移位
2020 年那道的题面把这个前提直接写了出来——「假定某计算机 M 中 ALU 只能进行加减运算和逻辑运算」。于是乘法只能拆成逐位扫乘数、遇 1 就累加被乘数的左移版本;实现层次由此排成三档:软件循环(每次乘法要跑数十条指令)、单条乘法指令内部跑 n 次加与移位、阵列乘法器把这些加与移位全展开成组合逻辑一拍出结果。
除法同理。2025 年那道给的补码除法器里,
边界必错点
2025 年那道的两个操作数,一个补 1、一个补 0。 被除数 d[i] = 0x87654321 最高位是 1,按题面标的 SEXT 扩成 64 位,高 32 位全补 1,所以 R 的初值是 FFFFFFFFH、Q 的初值是 87654321H;而除数题面写作 x = 0xff,x 在程序段里声明为 int,它的值就是 255,装进 32 位的 Y 得 000000FFH。同一条 idiv、两个操作数、两种补法。(顺带一提:这道题的题面开头是与上一题共用的 Cache 与虚存材料,它自己问的是除法器。)
2017 年那道的「最大的 n」一共问了三次,(4) 一次、(5) 两次,卡点不同。 上面那张表已经列清楚:不溢出看阶码、精确看尾数,答案是 126 和 23。把两条边界混成一条,两问都会错。
2011 年那道的 k1 必须真算一遍。 k1 = m - n 看着像「两个负数」很危险,实际是
2020 年那道的两个 2n 位乘积相同,是这一道的条件给的。 题面取 imul 与 umul 的 64 位结果位级完全一致。这条结论跟着本题的条件走:换一个负的操作数进去,两个 2n 位乘积立刻分家。
一道题的答卷长什么样
以 2011 年那道为例,四小问全写出来。这一类题的给分点几乎都落在中间量上,机器数和进位都要摆在卷面上。
第 0 步,先把两个数写成 8 位机器数。 后面每一问都要用:
x = 134 = 1000 0110B = 86H
y = 246 = 1111 0110B = F6H第 (1) 问,三个寄存器的内容。 一次加法一个竖式,两个进位单独标出来:
R1 = x = 1000 0110B = 86H
R5 = z1 = x − y,走 x + (256 − y):
1000 0110 (x = 134)
+ 0000 1010 (256 − 246 = 10)
─────────────
(0)1001 0000 C8 = 0, C7 = 0 → 90H(十进制 144)
R6 = z2 = x + y:
1000 0110 (x = 134)
+ 1111 0110 (y = 246)
─────────────
(1)0111 1100 C8 = 1, C7 = 0 → 7CH(十进制 124)C8 是最高位向外的进位、C7 是次高位向最高位的进位,顺手记下来,第 (4) 问要用。
第 (2) 问,同一串位换副眼镜。 m 与 k1 都是 int,按补码读:
m = R3 = 1000 0110B 最高位 1 → 负
取反 0111 1001 → 加 1 → 0111 1010B = 122 → m = −122
k1 = R7 = 1001 0000B 最高位 1 → 负
取反 0110 1111 → 加 1 → 0111 0000B = 112 → k1 = −112R7 的位模式和 R5 一模一样——z1 = x - y 与 k1 = m - n 在硬件里是同一次减法,只是读法换了。取反之后那个「加 1」千万别漏,漏掉就成了
第 (3) 问,四种运算能否共用一个加法器。 答「能」,理由写成两句:
- n 位加法器物理上只完成模
的二进制加法,它看不出输入是无符号还是补码; - 减法走
,只需在加法器外挂一组取反加末位加 1 的电路生成 。
第 (4) 问,判溢出,再逐条排查。 两套规则写一套即可,然后把四条算式列全:
规则① 符号判别法:两加数同号、结果异号 → 溢出
规则② 进位异或法:C8 ⊕ C7 = 1 → 溢出
z1 = x − y 无符号 → 溢出概念不适用(产生借位)
z2 = x + y 无符号 → 溢出概念不适用(产生进位)
k1 = m − n 带符号 → −122 − (−10) = −112 ∈ [−128, 127]
C8 = 0, C7 = 0,异或 0 → 不溢出
k2 = m + n 带符号 → −122 + (−10) = −132 < −128
C8 = 1, C7 = 0,异或 1 → 溢出第 (1) 问里算出来的两组进位在这里直接复用——竖式只列一次,两问共用。
第二组的卷面:简答题写到什么程度算够
第二组(2020、2025)全是简答和读图,「该写几句」比第一组难自估。以 2020 年那道为例。
(1) 为什么没有乘法指令也能做乘法——答的是分解方式,不是背定义:
乘法 = 逐位扫描乘数,遇 1 就把被乘数左移相应位数后累加
所以只要有「加 / 减 / 移位 / 条件跳转」四种指令就能实现(3) 三种实现哪个快哪个慢——先排序,再逐条给理由,一条理由对一档分:
软件循环 ① < 硬件乘法器 ② < 阵列乘法器 ③
① 每次乘法要执行数十条指令,还带取指译码开销
② 一条指令,但要走多个周期
③ 全展开成组合逻辑,一个周期出结果(4) 是全题最容易算错的一问,
64 位乘积 = 0000 0000 FFFF FFFEH ← 带符号与无符号在位级上完全一样
umul:取低 32 位 = FFFF FFFEH = 4294967294,在 unsigned 范围内 → 不溢出
imul:同一串位按 int 读是 −2,而真值应为 4294967294 → 溢出
无符号的溢出判断:2n 位乘积的高 n 位全为 0 才不溢出⚠️ 「乘积的位串只有一个,溢不溢出取决于用哪副眼镜读它」——这正是本专题第一组那句话, 在第二组里又出现了一次。两组在这里合上。
真题的两种形态
第一组 · 换约定读位串(2011-43、2017-43)——给一段 C 程序,让你在 unsigned、int、float 几套约定之间来回换算:写机器数、写真值、判某个运算会不会溢出、问某个约定的边界落在哪个 n 上。这一组的手上动作是读、换、量边界,全程不需要设计任何电路。
第二组 · 用加减和移位拼出乘除(2020-43、2025-44)——题面先声明 ALU 只会做加减(或直接给一张乘法器 / 除法器的结构图),然后问:为什么没有乘法指令也能做乘法、控制逻辑在里面干什么、几种实现哪个快哪个慢、寄存器初值怎么装、ALUop 需要控制几种运算、什么输入会触发异常。这一组的手上动作是拼。
两组在「溢出」这一问上会合。 2020 那道要用 2n 位乘积的高 n 位是否全 0 来判无符号截断溢出,2025 那道要指出
这一组也挂着别的章节
和指令格式那一类题一样,数据表示这副骨架上常常挂着别的章节的问法。认出来就知道该翻哪一章:
- 异常响应中 CPU 要完成哪些操作(2025-44 第 (2) 问后半)——中断与异常,答的是关中断、保护断点、保护程序状态、切换内核态、跳转异常处理程序入口这几步硬件动作;
- 三种乘法实现的执行时间排序(2020-43 第 (3) 问)——指令周期与硬件成本,比的是取指译码开销、多周期迭代、组合逻辑一拍;
- 控制逻辑在乘法器里干什么(2020-43 第 (2) 问)——控制器,答的是循环计数、按位决策、状态维护。
骨架部分的分照样要拿,这些外挂问通常独立给分。
交卷前扫一眼
先写出机器数再动别的 · 换眼镜时位串一位不动 · 「最大的 n」先问卡的是哪个字段 · 乘除只有加减和移位可用 · 无符号越界叫进位,带符号越界才叫溢出
配套内容
- 真值与机器数:四种编码的定义|定点数编码的转换与书写|进位计数制与转换
- 补码加减运算与溢出判别|算术逻辑单元(ALU)|定点数的移位运算
- 浮点数表示(IEEE 754)|浮点数的加减运算|C语言中的数据类型与转换
- 乘除运算的基本原理与实现结构|Booth 乘法(补码一位乘)|恢复余数除法|不恢复余数除法(加减交替法)
- 第 (2) 问后半那条外挂:异常和中断机制
大纲这几条的其余打法、这 4 道真题没有正面考过的(专题的巩固栏里配了题):
- 原码、反码、移码的编码与互换——大纲里「定点数的编码表示」这一条,四道真题全程只用了补码和无符号二进制,另外三种编码一次没露面
- 四个标志位的完整生成规则——大纲里「标志位的生成」这一条,2011 那道只问了「怎么判断带符号加减是否溢出」,CF、SF、ZF 各自怎么生成、减法的 CF 为什么要取进位的反,都没问过
- 用标志位的逻辑组合判两个数谁大——无符号看 CF 与 ZF、带符号要用 SF 异或 OF,四道真题没有一问要求写出标志位的逻辑组合表达式(比较语义本身在 2017 那道的 (1) 问考过)
- 双符号位(变形补码)判溢出——2011 那道的通行答案给的是符号判别法与进位异或法两套,第三套方法没出现过
- 窄化转换之后再宽回去(int → short → int)——2020 那道让取 2n 位乘积的低 n 位,擦到了截断的边;但把截断后的值符号扩展回原宽度、看它与原值差多少,没考过
- IEEE 754 双精度格式——2017 那道的题面写明「float 采用 IEEE754 单精度标准」,11 位阶码、偏置 1023 这一套没出现
- 浮点加法的对阶、尾数相加、规格化三步——2017 那道问到了舍入的边界(精确的最大 n),但没有一道题让完整走一次浮点加法
- 乘法电路的逐周期演算——2020 那道问的是「为什么能用加和移位实现」以及控制逻辑干什么,没让按 Booth 这类算法一周期一行把部分积走完
- 除法电路的逐周期演算与试商溢出判断——2025 那道给了除法器结构、问了初值和 ALU 运算种类,32 次迭代本身没让走,「试商后余数非负即溢出」这条硬件规则也没问
- IEEE 754 的其余特殊值——2017 那道只问到阶码全 1 加尾数全 0 的
,非规格化数、NaN、 三种编码没考过(暂无配套巩固题)
逐题精讲(建设中)——真题作答与 AI 判分入口见站内大题专题。