简介:这份计算机组成原理课后习题答案面向学习唐朔飞《计算机组成原理》第三版的高校学生与备考读者,用于对照教材章节核查概念理解、梳理课后题思路并查漏补缺。压缩包内仅含1个docx文档,大小约7.8MB,集中整理第一章概论等章节的习题解答,覆盖计算机系统层次结构、高级语言与汇编语言及机器语言的区别、计算机组成与体系结构、冯·诺依曼计算机特点、硬件组成框图与技术指标、主机与CPU及主存等核心概念。文档以问答形式呈现,便于按知识点检索和复习,也可作为课程作业校对与考前强化的参考。目前已有25711人学习,适合需要系统理解硬件基础、巩固教材重点的读者使用。
1. 一份答案册真正的用法,是当校验器而不是抄写本
期中考前一周,实验室里最常见的画面是三个人对着同一道存储器扩展题算出三个不同片数。这时候一份完整的计算机组成原理课后习题答案是刚需,但更刚需的是知道答案里哪一步能直接信、哪一步必须自己复算。这份资源对应那本被大量院校选作教材的《计算机组成原理》第三版,逐章覆盖概论、系统总线、存储器、指令系统与 CPU 结构,问答题给的是成段的标准表述,计算题给的是带中间步骤的推导。它适合三类人:赶考期需要对照自查的在校生、跨考补硬件基础的备考者、以及临时接手习题课想快速对齐口径的助教。概念题可以直接背,计算题不行——总线带宽和存储器扩展这两块,抄错一步整题归零,后面几章我按题型拆开讲怎么复核。
2. 从层次结构到主机框图:概念题怎么落到信息流上
概念题在这本教材里占的分值不低,但很多人背完就忘,原因是把「层次结构」当成六条并列的名词记,没有把它当成一条自上而下的解释链。真正能拿分的记法是:每一级都问一句「这一级的语句由谁来解释执行」,答案自然就出来了。下面三节分别处理层次结构、语言翻译链和体系结构边界,最后落回主机框图的信息流,这一条线走通,概论章的问答和画图题基本不会失分。
2.1 五级层次不是背诵条目,是排错顺序
教材给出的层次从下往上是:微程序机器级、传统机器级、操作系统级、汇编语言机器级、高级语言机器级,往上还可以有面向问题的应用语言机器级。判断某一级的归属,只看一个东西——解释器在哪一层。微程序机器级的微指令由硬件直接执行,没有解释器;传统机器级的机器指令由微程序解释;操作系统级用机器语言程序去解释作业控制语句;汇编语言机器级靠汇编程序把符号指令翻成机器指令;高级语言机器级靠编译程序往下翻。这条链的实务价值在于排错:当一段程序跑不出预期结果,先定位它停在哪一级,比盲目改代码高效得多。
| 层级 | 该级的语句形态 | 解释/翻译者 | 典型可见性 |
|---|---|---|---|
| 微程序机器级 | 微指令 | 硬件直接执行 | 对汇编程序员透明 |
| 传统机器级 | 机器指令 | 微程序 | 机器语言程序员可见 |
| 操作系统级 | 作业控制语句 | 机器语言程序 | 系统管理员可见 |
| 汇编语言机器级 | 汇编指令 | 汇编程序 | 汇编程序员可见 |
| 高级语言机器级 | 高级语言语句 | 编译程序 | 应用开发者可见 |
| 应用语言机器级 | 面向问题的语句 | 专用解释器 | 领域用户可见 |
这张表建议自己默写一遍,尤其是「解释者」那一列。很多人能背出六级的名字,却答不出「传统机器级由谁解释」,选择题一变形就翻车。还有一个常见追问是「每一级都能进行程序设计吗」,答案是能,因为每一级都有自己的指令系统和程序员视角,只是抽象程度不同。把这个结论和上表一起记,答「如何理解层次结构」这类大题时就有骨架了。
需要提醒的是,层次越往上,程序的执行效率通常越低但开发效率越高,这不是教材的废话,而是后面讲虚拟存储器、Cache 透明性时的伏笔。层次结构的本质是「用低级的复杂性换高级的易用性」,理解到这一层,再去看编译优化、指令集设计这些话题,就不会觉得是两门课。
2.2 三段翻译链:高级语言到机器语言之间到底发生了什么
机器语言是硬件唯一能直接识别的形式,二进制编码,操作码加地址码;汇编语言是机器语言的符号化表示,把操作码换成助记符、把地址换成符号,一一对应;高级语言面向算法而不是面向硬件,一条语句可能展开成几十条机器指令。教材给的路径是:高级语言源程序先翻译成汇编语言程序,再由汇编程序汇编成机器语言目标程序,才能被硬件执行。
这个模型在概念题上必须按这个顺序答,但动手验证时你会发现现代编译器的实现路径并不总是「先落一份汇编文本再汇编」。常见的做法是直接生成目标文件,中间那一步的汇编只是逻辑层级而不是物理产物。这不矛盾——教材描述的是翻译的逻辑层级,编译器可以合并步骤。我一般会让学生做一次对照实验,把同一段循环分别写成高级语言和汇编,观察指令条数的膨胀比例,这个体感比背定义管用。
# 把一段 C 源码编译到汇编,观察高级语言语句被展开成多少条汇编指令 gcc -O0 -S demo.c -o demo.s # -O0 关闭优化,保留最直白的展开结果 gcc -O2 -S demo.c -o demo_o2.s # -O2 打开优化,对比指令条数差异 wc -l demo.s demo_o2.s # 行数差就是优化带来的压缩量这段命令的用途是拿实物对照教材的翻译链。-O0保留未优化的直译结果,适合看清「一条高级语言语句对应多少条机器级操作」;-O2打开常规优化,用来解释为什么同样的算法在不同编译选项下指令条数会差出几倍。注意这里比较的是指令条数而不是运行时间,指令条数受寄存器分配和循环展开影响很大,不能直接当成性能结论,这本身也是一个常见的答题陷阱。
三条语言的联系要答成一句完整的话:高级语言程序处于最高层,必须翻译成汇编语言,再经汇编程序汇编成机器语言目标程序之后才能执行。差别则从三个维度切——与硬件的距离、可移植性、执行效率。机器语言与硬件强绑定、换机器就得重写、但执行最快;高级语言可移植、开发快、但要靠翻译器付出开销。答到这三个维度,评分点基本齐了。
2.3 组成与体系结构的边界:一条「是否对程序员透明」的判断准则
这两个概念最容易混。体系结构是程序员能看到的属性,包括指令集、数据类型、存储器寻址技术、I/O 机理这类偏抽象的东西;组成是实现这些属性的具体硬件方案,里面大量细节对程序员是透明的,比如乘法到底用专用乘法器还是用加法器加移位实现。判断准则只有一条:机器语言程序员写代码时能不能感知到。感知得到,归体系结构;感知不到,归组成。
按这条准则做几道判断题会很快:
| 属性 | 归类 | 理由 |
|---|---|---|
| 有没有乘法指令 | 体系结构 | 指令集是程序员直接调用的 |
| 乘法用专用乘法器还是移位加法实现 | 组成 | 实现方式对程序员透明 |
| 是否设置 Cache | 组成 | 程序员看到的是统一的主存空间 |
| 指令的寻址方式有几种 | 体系结构 | 写汇编时必须有感知 |
| Cache 的替换算法用哪种 | 组成 | 完全透明 |
| 主存容量多大 | 体系结构 | 影响可编程的地址空间 |
边界上有一处常被争论:虚拟存储器算哪边。按「程序员可见的存储空间」这条线,它偏体系结构,因为它扩展了程序员可用的地址空间;但页面调度算法、TLB 组织这些实现细节又归组成。答题时最好把这两半都说出来,只答一边容易被扣分。
2.4 主机框图的信息流与寄存器位数的推导
画图题的核心不是画得像,而是标对每一步的数据流向。以存数指令和加法指令为例,取指阶段是所有指令共用的:程序计数器送出地址到存储器地址寄存器,存储器按地址读出内容送到数据缓冲寄存器,再送指令寄存器;指令寄存器的操作码部分送控制单元译码,地址码部分送地址寄存器。执行阶段才分叉——存数指令把累加器内容经数据缓冲寄存器写回主存,加法指令则从主存读出操作数送操作数寄存器,运算后结果回累加器。
寄存器位数的推导有个固定套路:地址寄存器和程序计数器的位数由存储字个数决定,数据缓冲寄存器、指令寄存器、累加器、操作数寄存器的位数由存储字长决定。教材那道 256M×32 位的题,条件是指令字长、存储字长、机器字长三者相等,于是数据侧一律 32 位,地址侧看 256M 是 2 的多少次方。
import math words = 256 * 1024 * 1024 # 存储字个数 = 256M,即 2^28 data_bits = 32 # 存储字长 = 机器字长 = 指令字长 = 32 位 addr_bits = int(math.log2(words)) # PC 与 MAR 的位数 print(f"PC/MAR = {addr_bits} 位, ACC/X/IR/MDR = {data_bits} 位") # 输出:PC/MAR = 28 位, ACC/X/IR/MDR = 32 位这段推导的关键参数是words,它取的是存储字的个数而不是字节数,因为地址寄存器编的是字地址。如果题目改成按字节编址,256M×32 位就等于 1G 字节,地址线要 30 根,这是最容易错的一处。data_bits之所以能一次性套给四个寄存器,前提是题干明确说了指令字长、存储字长、机器字长相等;只要这三个长度不等,就要分开算,指令寄存器跟指令字长走,数据缓冲寄存器跟存储字长走。做题时先圈出这句话,再动笔。
指令和数据都存在存储器里,靠什么区分?两个判据:一是时间,取指阶段取出的是指令,执行阶段取出的是数据;二是地址来源,由程序计数器给出的地址取的是指令,由指令地址码给出的地址取的是操作数。这两条要一起答,只答时间维度不完整。
3. 总线计算题:带宽、判优与通信控制的三个口径
总线这一章的计算题看似简单,实际是全书单位错误最集中的地方。带宽题失分几乎都不是不会算,而是位和字节没换、时钟周期和传输周期没分清、波特率和比特率混着用。下面三节把三类题的算式统一到一套口径上,再给出判优方式和通信方式的选择表,最后那个串行传送的题单独拎出来讲,因为它的错误率最高。
3.1 总线带宽:先统一「一个传输周期占几个时钟」
带宽的定义是单位时间内总线上传送的数据位数,算式只有一个:总线宽度除以总线传输周期。变化全在传输周期上——有时一个总线周期等于一个时钟周期,有时题干会说最短传输周期包含若干个时钟周期。所以做题第一步永远是把传输周期换算成秒,第二步再拿位宽去除。
教材那两道题正好覆盖两种情形。第一道:时钟频率 8MHz,一个总线周期等于一个时钟周期,并行传送 16 位,带宽就是 16 除以(1/8M)秒,得 128Mbps。第二道:32 位总线,时钟 66MHz,最短传输周期为 4 个时钟周期,带宽是 32 除以(4/66M)秒,得 528Mbps。第二道题的后半问「想提高数据传输率可采取什么措施」,标准答法是提高时钟频率、增大总线宽度、减少传输周期包含的时钟周期数,这三条正好对应算式里的三个变量。
def bus_bandwidth(width_bit, freq_hz, cycles_per_transfer=1): """width_bit: 总线宽度(位) freq_hz: 总线时钟频率(Hz) cycles_per_transfer: 一个总线传输周期占几个时钟周期""" period = cycles_per_transfer / freq_hz # 一次传输耗时,单位秒 return width_bit / period # 单位 位/秒 bw1 = bus_bandwidth(16, 8e6, 1) # 16 位 / 一个时钟周期 bw2 = bus_bandwidth(32, 66e6, 4) # 32 位 / 四个时钟周期 print(bw1 / 1e6) # 128.0 Mbps print(bw2 / 1e6) # 528.0 Mbps print(bw1 / 8 / 1e6) # 16.0 MB/s,位转字节必须除以 8这段脚本把两道题压进同一个函数,参数含义直接对应题干里的三个量。cycles_per_transfer是最容易漏的参数,默认值给 1 只适用于「一个总线周期等于一个时钟周期」的题面,一旦题干写「最短传输周期为 4 个时钟周期」就必须显式传 4。最后一行演示位与字节的换算,128Mbps 等于 16MB/s,很多答案只写 128 就交卷,遇到要求以字节为单位的题目直接判错。
还有一个容易忽略的点:题目问的是「最大数据传输率」还是「总线带宽」,两者在这类题里是同一个量,但「最大」意味着取最短传输周期,如果题干给的是「平均传输周期」就不能套同一个数。另外总线宽度指数据线根数,不是地址线加数据线的总和,这一点在概念题里考过一次,在计算题里也常被误用。
3.2 波特率与比特率:串行传送里最容易错的一步
异步串行传送那道题,字符格式是 1 个起始位、8 个数据位、1 个校验位、2 个终止位,每秒传送 120 个字符。波特率按一帧的总位数算,一帧 1+8+1+2 等于 12 位,所以波特率是 12×120 等于 1440bps;比特率只算有效数据位,8×120 等于 960bps。这两个数的差别就是帧开销,1440 减 960 等于 480bps 全花在起止位和校验位上,开销比例达到三分之一。
这个比例不是随便设的,起止位负责帧同步,校验位负责差错检测,把开销压到零就没法在一条线上分清哪几位属于哪个字符。理解到这一层,再遇到「为什么波特率高于比特率」的问答题就能答得有内容,而不是干巴巴地重复定义。
| 概念 | 计算口径 | 本题取值 |
|---|---|---|
| 一帧位数 | 起始位 + 数据位 + 校验位 + 终止位 | 1+8+1+2 = 12 位 |
| 波特率 | 一帧位数 × 每秒字符数 | 12 × 120 = 1440 bps |
| 比特率 | 有效数据位数 × 每秒字符数 | 8 × 120 = 960 bps |
| 帧开销 | 波特率 − 比特率 | 480 bps |
顺带把总线带宽和这两个概念区分开:带宽说的是并行总线上单位时间传送的位数,波特率说的是串行线上单位时间的信号码元数,比特率说的是单位时间的有效数据位数。三者单位都是 bps,但含义完全不同,答题时把定义先写一句,再代数字,比直接抛结果安全。
3.3 判优与通信控制:三类查询、四种通信方式怎么选
多个主设备同时申请总线时必须仲裁,这叫总线判优控制。集中式有三种:链式查询、计数器定时查询、独立请求。链式查询线少、易扩充,但优先级固定且对电路故障敏感,一个环节断了后面的设备全部失联;计数器定时查询的优先级可以通过计数器初值改变,也可以做成循环方式让各设备优先级相等,代价是多几根控制线、控制逻辑复杂一些;独立请求每台设备一对请求线和授权线,响应最快、优先级最灵活,但线数随设备数线性增长,控制也最复杂。
| 方式 | 控制线数量 | 优先级灵活性 | 响应速度 | 故障敏感度 |
|---|---|---|---|---|
| 链式查询 | 最少 | 固定 | 较慢 | 最敏感 |
| 计数器定时查询 | 中等 | 可通过初值改变 | 中等 | 一般 |
| 独立请求 | 最多 | 最灵活 | 最快 | 不敏感 |
这张表要能默写。常见的变体题会把「响应时间最快」和「对电路故障最敏感」单独拎出来问,答案分别是独立请求和链式查询,这两个结论在表里是两端的极值,记住极值比记整张表省力。
通信控制分四类,判断依据是「有没有统一时钟」和「是否等待应答」。同步通信靠统一时钟,控制简单但对速度差异大的设备不友好;异步通信靠应答,分不互锁、半互锁、全互锁三种,区别在于请求和回答信号是否互相保持;半同步通信在同步的基础上加一根等待信号线,用插入时钟周期的办法兼容慢速设备,等于把两者的优点各取一半;分离式通信则让各模块在准备数据期间不占用总线,获得使用权后限时传完就走,不等待应答,把总线的空闲时间压到最低,主要用在大型系统里。
选择逻辑可以简化成三个问题:设备速度是否接近?接近就同步,差异大就异步或半同步。系统对可靠性要求高不高?要求高优先半同步。追求吞吐还是追求简单?追求吞吐且是大型系统就考虑分离式。这三个问题答完,选型基本就定了。
4. 存储器扩展:片数、地址线与刷新间隔的复算方法
存储器这一章是全书计算量最大的一章,题型集中在三类:给定目标容量和芯片规格求片数与地址分配、给定存储基元总数求地址线数据线的最优拆分、给定芯片内部结构求三种刷新方式的间隔。这三类题都有固定的通式,把通式记住再套数字,比背例题稳。下面按片数、线数、刷新顺序拆开。
4.1 片数通式与六种芯片规格的对照
片数只有一个式子:总片数等于目标总容量除以单片容量,两边都先换算成位。目标是 16K×32 位,等于 512K 位,然后拿六种芯片规格分别去除,得到不同的片数。这一步之后还要判断哪些是位扩展、哪些是字扩展——位扩展是把多片同地址的芯片并联加宽字长,字扩展是把多组芯片串联扩大字数,两者混了,片数算对也画不出正确的逻辑图。
def chip_count(target_words, target_word_bits, chip_words, chip_word_bits): """target_words × target_word_bits:目标存储器的字数与字长 chip_words × chip_word_bits:单片芯片的字数与字长""" total_bits = target_words * target_word_bits chip_bits = chip_words * chip_word_bits return total_bits // chip_bits specs = [(1, 1024, 4), (2, 2048, 8), (4, 4096, 4), (16, 16384, 1), (4, 4096, 8), (8, 8192, 8)] # 元组含义:(标签, 芯片字数, 芯片位宽) for tag, cw, cb in specs: n = chip_count(16 * 1024, 32, cw, cb) print(f"{tag}K×{cb}位 -> {n} 片")这段的输出依次是 128、32、32、32、16、8 片。target_words传 16×1024 是因为目标容量写成 16K×32 位,K 按 1024 算。chip_count内部先统一成位再相除,避免了字数位宽混算。参数上唯一需要注意的坑是不同教材对 K 的定义,本教材一律按 1024 处理,如果题干写的是「16K」而芯片写的是「16384」,那说明出题人用的是 1024 进制,直接相除即可。
光有片数不够,还得说清怎么排。以 16K×32 位为例,用 1K×4 位的芯片,需要 16 组字扩展、每组 8 片位扩展,总共 128 片。用 8K×8 位的芯片,只需 2 组字扩展、每组 4 片位扩展,总共 8 片。片数从 128 降到 8,靠的就是单片容量变大,这也是实际选型时优先挑大容量芯片的原因——片数少了,译码电路和布线复杂度都会下降。
4.2 地址线与数据线总和最小化:一次穷举就够
存储基元总数固定时,字数和位宽怎么分配会让地址线加数据线的总数最小?这类题的实质是一个带约束的极值问题:设地址线 a 根、数据线 b 根,则 2 的 a 次方乘以 b 等于基元总数。教材那道题基元总数是 64K×8 等于 512K 位,也就是 2 的 19 次方。把 a 从 1 枚举到 19,逐个算 b 和总和,答案就出来了。
TOTAL = 2 ** 19 # 存储基元总数,512K 位 results = [] for a in range(1, 20): if TOTAL % (2 ** a) == 0: # 必须整除,否则位宽不是整数 b = TOTAL // (2 ** a) results.append((a + b, a, b)) # (线数总和, 地址线, 数据线) results.sort() for total, a, b in results[:4]: print(f"地址线 {a:>2} 根, 数据线 {b:>2} 根, 总和 {total} 根")循环里% (2 ** a) == 0这个判断是必要的,不整除说明这种拆分在位宽上不成立,直接跳过。排序后取前四组,输出是 (19,1)、(18,2) 各 20 根,(17,4) 是 21 根,(16,8) 是 24 根。所以最小值 20 根,且有两种解答——这一点很多人只答一种,题目既然问「有几种解答」,就必须把所有取到最小值的组合列全。从工程角度看,这两种解分别是「极长字、一位宽」和「长字、二位宽」,前者地址译码简单但数据线只有一根,实际芯片不会这么设计,题目考的是数学极值而不是可实现性。
4.3 三种刷新方式的间隔:数值从哪来
以 8K×8 位的动态芯片为例,内部排列成 256×256,读写周期 0.1 微秒。刷新是按行来的,256 行就是 256 次刷新操作。集中刷新把 256 次刷新集中在 2 毫秒的刷新间隔内做完,死时间等于 256 乘 0.1 微秒,得 25.6 微秒,这段时间 CPU 完全不能访存;分散刷新在每个读写周期后面插一个刷新周期,等于把读写周期拉长到 0.2 微秒,刷新完 256 行需要 256 乘 0.2 微秒,得 51.2 微秒,好处是没有死时间,代价是整体变慢;异步刷新把 2 毫秒除以 256,均匀地每隔约 7.8 微秒刷一行,兼顾两者。
rows = 256 # 芯片内部行数,也是需要刷新的次数 t_rc = 0.1 # 读/写周期,单位微秒 refresh_window = 2000 # 最大刷新间隔 2ms = 2000μs print(rows * t_rc) # 25.6 μs 集中刷新的死时间 print(rows * (t_rc + t_rc)) # 51.2 μs 分散刷新的刷新一遍耗时 print(refresh_window / rows) # 7.8125 μs 异步刷新的均匀间隔三个参数的含义要分清:rows是行数不是总字数,8K×8 排成 256×256,行数和列数都是 256,但刷新只按行,所以取 256;t_rc是读写周期不是存取时间,存取周期包含恢复时间,题目给了哪个就用哪个;refresh_window是最大刷新间隔,通常由器件手册给出 2 毫秒,题目直接给。这三种方式没有绝对优劣,集中刷新适合允许短时停顿的批处理场景,分散刷新适合对响应敏感但吞吐要求不高的场合,异步刷新是通用做法。
4.4 三级结构存储器的画图落点
64K×8 位用 1024×4 位芯片搭,要求分成 4 个页面、每页 16 组,总片数是 128 片。这个数字怎么来的:64K×8 等于 512K 位,1024×4 等于 4K 位,相除得 128。但画图不能只标 128 片,题目要求三级结构,就得把页面、组、片三层都标出来。
页面容量等于总容量除以页面数,64K×8 除以 4 得 16K×8;组容量等于页面容量除以组数,16K×8 除以 16 得 1K×8;组内片数等于组容量除以片容量,1K×8 除以 1K×4 得 2 片,这两片是位并联,把 4 位加宽到 8 位。四级地址分配依次是页面选择、组选择、组内字选择、片内位选择。画图时把这三层用不同的框线区分开,标注清楚每层的地址位,比只画一个大方框要稳得多。
同类型的还有模块板结构的题:地址码 18 位,用 4K×4 位芯片组板,每板 32K×8 位。最大主存空间由地址码决定,2 的 18 次方等于 256K,8 位机按字节编址就是 256KB;模块板数量等于 256K 除以 32K,得 8 块;每板片数等于 32K×8 除以 4K×4,得 16 片;总片数 8 乘 16 等于 128 片。这类题的关键是别把地址码位数直接当成板数,先算总空间再除以单板容量。
5. 避坑与排查:五类高频翻车现场
答案册用得久了会发现,错的地方高度集中在几个固定位置,而且错法几乎一模一样。下面这五条都是从对照复算里攒出来的血泪经验,每条按现象、原因、解决三步写,对着排查基本能定位到具体哪一步断的。
5.1 片数算对了,逻辑图还是画错
现象:总片数写的是 128 片,画图时却把 128 片全部并排挂在同一组地址上,被问「这样能寻址吗」就答不上来。
原因:把位扩展和字扩展当成了同一件事。位扩展是同一地址上多片并联、共同加宽字长;字扩展是不同地址上多组串联、扩大字数。128 片这个数字是两者的乘积,不是并列关系。
解决:先算总片数,再拆成「组数 × 组内片数」。组数由字数比决定,组内片数由位宽比决定。以 16K×32 位用 1K×4 位芯片为例,字数比 16K 比 1K 是 16 组,位宽比 32 比 4 是 8 片每组,16 乘 8 得 128。画图时先画 16 组,每组内部再画 8 片并联,层次不会乱。
5.2 地址线根数照抄,忘了片内低位不参与片选
现象:算多板存储器的地址分配时,把 18 位地址全部接到片选译码器上,导致每块板都被同时选中。
原因:没有区分片内地址和片间地址。低位地址用于选中芯片内部的某个存储单元,高位地址才用于选板或选片。
解决:先按单板容量算出片内地址位数。32K 字需要 15 根片内地址线,18 位总地址减去 15 位,剩下 3 位用于选 8 块板。这个拆分逻辑对所有多级存储器都成立:总地址位数等于片内位数加片选位数,片选位数等于以 2 为底板数的对数。
5.3 带宽单位从 Mbps 直接写成 MB/s
现象:算出 128Mbps,答案写 128MB/s,或者算完 160M 位每秒直接当 160MB/s 用。
原因:位和字节差 8 倍,而 Mbps 和 MB/s 在书写上只差一个字母大小写,抄的时候极易漏掉。
解决:算完先看题目要求的单位,位就写 bps,字节就写 B/s,中间强制做一次除以 8 的换算。存储器带宽那道题算出来是每秒 1.6 亿位,换算成字节是 20MB/s,再换算成 32 位字是每秒 5M 字,三个单位都能互相印证,做完顺手验一遍就不会错。
5.4 波特率当比特率,或者把存取周期当存取时间
现象:串行传送题把 1440bps 当成有效数据速率,或者存储器带宽题用存取时间代替存取周期代进公式。
原因:前者没有扣掉起止位和校验位的帧开销,后者忽略了存取周期还包含恢复时间。
解决:串行题先算一帧总位数得到波特率,再用有效数据位数得到比特率,两个数都要写。存储器题先确认题干给的是哪个量,存取周期等于存取时间加恢复时间,给的若是周期就直接用周期的倒数,给的若是时间且没提恢复时间,就按时间算并在答案里注明假设。
5.5 层次结构顺序颠倒,或者把透明性用反
现象:答层次结构时把操作系统级放在汇编语言机器级之上,或者答「Cache 对程序员是否透明」时说不透明。
原因:层次结构是靠「谁解释谁」串起来的,顺序一旦靠记忆而不靠推导就容易反;透明性则是把「看不见」理解成「不存在」。
解决:层次顺序从解释关系推——硬件直接执行微指令,微程序解释机器指令,机器语言程序解释作业控制语句,汇编程序支持汇编级,编译程序支持高级语言级,顺序自然出来。透明性的判断标准固定为「机器语言程序员是否需要感知」,Cache 的存在不需要感知,所以是透明的;虚拟存储器扩展了可见地址空间,所以不透明。
6. 把答案变成自测工具:三道工序与一个验算习惯
答案册最容易的用法是对着抄,最有效的用法是把它当题库的参考答案来反推考点。我一般会走三道工序。第一道是遮答案自测,把每章的计算题单独抄到一张纸上,只抄题干不抄解答,限时做完再对;对不上时不要立刻看答案,先回到教材找对应的公式段落,看是公式记错还是参数代错。第二道是按题型归档,把所有计算题分成带宽类、片数类、刷新类、位数推导类四堆,每堆抽三道做一遍,能全对说明这一类通了,错一道就说明这一类还有盲区。第三道是反向出题,拿答案里的最终数字去倒推题干条件,比如已知片数是 128,问目标容量和芯片规格有几种可能组合,这一步能逼出对通式的真正理解。
验算习惯只有一个:所有涉及「位 / 字节 / 字」的量,算完必须换两个单位各写一遍。128Mbps 写成 16MB/s,再写成每秒 4M 个 32 位字,三个数能对上,答案就基本没错。这个习惯救过我很多次,尤其是存储器带宽那类题,教材专门标注「字长 32 位不是 16 位」,说明出题人知道这里必错。
| 工序 | 具体做法 | 判断通过的标准 |
|---|---|---|
| 遮答案自测 | 只抄题干,限时作答 | 计算题全对,问答题要点覆盖三条以上 |
| 按题型归档 | 四类题型各抽三道 | 每类正确率 100% |
| 反向出题 | 由结果倒推条件组合 | 能列出全部可能解,不漏不多 |
最后补一个技巧:概念题别背整段,背关键词骨架。比如「冯·诺依曼特点」记五个点——五部件、指令数据同存、二进制表示、操作码加地址码、顺序执行可条件跳转,答题时把骨架展开成句子,比背整段更抗遗忘,也更像自己的话。这份答案的价值不在于给出标准表述,而在于让你有一个可以反复校准的参照物。从那以后我每次带人复习硬件课,都强制先做一遍遮答案自测再谈看答案,因为看懂了和做对了是两件事。希望帮到你。
本文还有配套的精品资源,点击获取