Skip to content

指令字段与机器码:切开位串、数出字段宽、加出下一条地址(专题总纲)

Intro

这一类题有两副长相。一副是给你一张字段定义表,标着 [15,12] OP[11,9] Ms[8,6] Rs;另一副是甩给你一段 x86 反汇编,每行写着虚拟地址、机器码字节和汇编助记符,让你在里面找答案。

看着像两类题,其实手上做的是同一件事。因为一条指令在机器里只有两样东西:

一串被字段切开的位,和一个占若干字节的地址。

小问基本都在这两样之间来回换算——少数几问是别的章节挂上来的,最后一节会点出来。两副长相的区别只在于字段的位置和长度是谁告诉你的:给字段表的那五道,题面直接画了位区图;给反汇编的那几道,你得自己从「两行虚拟地址差了多少」和「这一行机器码写了几个字节」里量出来。下文把这件事简称为量尺子。量出尺子之后,两组题就是同一道题。

字段只有三个属性,所以题只能问三种事

字段的属性手上的动作题面长什么样
它有宽度2 = 这一段能编多少个东西最多多少条指令、多少个通用寄存器、偏移量范围多大
它有位置:按位区切开读编号,或把编号填回去写出机器码、给出机器码问功能、判断某寻址方式
它有含义:编号指向的偏移量参与地址运算转移目标地址、访存有效地址、下一条指令地址

数、切、加——九道真题的大部分小问落在这三个动作里。但不是全部:有相当一部分分值是别的章节挂在指令格式这副骨架上的,本文最后一节会列清楚哪些是外挂、该翻哪一章。以 2024-43 为例,13 分里有 9 分(标志位、控制信号)并不属于这三个动作。

数:2 里的「宽」取哪一段,是第一个坑

2010 年那道题的操作数字段占 6 位,但它是 寻址方式 3 位 + 寄存器编号 3 位 拼起来的。问「最多多少个通用寄存器」,取的是寄存器编号那 3 位:

23=8 个

不是 26先看清这一段是不是还能再拆。

切:正着填和反着读,是同一张表

正向是「汇编 → 机器码」:把每个助记符换成编号,按位区拼起来。反向是「机器码 → 功能」:先展开成二进制,再按位区截断。

反向那一步有个额外用处——判一条机器码到底是哪条指令。2024 年那道给出 A040 A103H,问为什么它一定是 lw:把低 7 位取出来是 0000011,只有 lw 的操作码是这个值;addslli 要求高 7 位是 0000000,而这里是 1010000,对不上。排除法用的仍然是同一张字段表。

加:基准永远是「下一条指令的地址」

相对寻址算目标地址,基准是取完这条指令之后 PC 指向的位置。拿当前这条指令的地址去加,是这一步最常见的丢分处。三道真题三种写法,说的是同一件事:

  • 2013 年:题面直接写成 (PC)+2+2×OFFSET——那个 +2 就是跳过本条指令;
  • 2023 年:jmp00401079H、机器码 EB 09 两字节,目标 = 0040107BH+09H=00401084H
  • 2019 年:call00401025H、机器码五字节,偏移量 = 目标 − 下一条 = 00401000H0040102AH=2AH

没给字段表的那四道,尺子藏在两个地方

反汇编那一组里有三道(2017-44、2019-45、2023-44)没有字段定义表,但题面把尺子交给你了:

  1. 每行的机器码有几个字节 → 这条指令占几字节 → 下一条的地址;
  2. 多字节字段在内存里的排列顺序 → 大端还是小端。

(第四道 2024-44 是个例外:它给的是四条类 RISC-V 汇编,既没有虚拟地址也没有机器码字节,不用量尺子,直接把每条指令翻成 C 语义反推寄存器的角色。)

2019 年那道把两件事串成一问:call 的机器码是 E8 D6 FF FF FF,后四字节是偏移量。按上面算出偏移量真值是 FFFF FFD6H,而内存里从低地址往高地址读到的是 D6 FF FF FF——最低有效字节 D6 落在最低地址,所以这台机器是小端。

判大小端不需要额外知识,把算出来的数和题面印的字节顺序对一下就行。

必错点

MAR 和 MDR 的位数有两种算法,看题面给了什么。 题面给了系统总线宽度,就跟总线走;没给,才用地址空间反推。

2021 年(给了总线)2010 年(没给总线)
MAR20 位 = 地址线宽度16 位 = log2(64K 字)
MDR8 位 = 数据线宽度16 位 = 字长

2021 年那道的 MDR 是 8 位,哪怕字长是 16 位——代价是取一条 16 位指令要访存两次。别看见字长就往 MDR 上填。

自增量跟着编址单位走。 2010 年那道按字编址,(Rn)+ 执行后 Rn 加 1;同样的助记符放在按字节编址、字长 4 字节的机器上就是加 4。

补码偏移量两头不对称,而且「能跳过多少条」还要看从哪儿数起。 8 位补码的范围是 [128,127],向后比向前多一个。2013 年那道向后最远 OFFSET=128,目标 = PC254;换算成条数时,标准答案取的是「距当前转移指令」这个基准,答 127 条把算式 (PC)+2+2×(128)=PC254254÷2=127 写出来,阅卷认的是这条链。

shamt 这类字段的宽度要从「能取几个值」倒推。 2024 年那道问「为什么 shamt 占 5 位」:字长 32 位,有意义的移位量是 0~31 共 32 个值,所以需要 log232=5 位。别直接背「等于字长取对数」——64 位机的 shamt 是 6 位,那是因为移位量变成了 0~63,还是同一条倒推。

一道题的答卷长什么样

以 2010 年那道的第 (3) 问为例——把 add (R4), (R5)+ 翻成机器码并追踪执行。字段表是题面给的:[15,12] OP[11,9] Ms[8,6] Rs[5,3] Md[2,0] Rd

第一步,按位区把编号码回去。 一行一段,别在脑子里拼:

OP  = 0010    (add)
Ms  = 001     (寄存器间接,源)
Rs  = 100     (R4)
Md  = 010     (寄存器间接、自增,目的)
Rd  = 101     (R5)
→ 0010 0011 0001 0101B = 2315H

第二步,逐层拆间址。 寄存器间接是两层:寄存器里装的是地址,地址里装的才是操作数。写成两行不会绕晕:

源:  (R4) = 1234H  →  M[1234H] = 5678H   ← 源操作数
目:  (R5) = 5678H  →  M[5678H] = 1234H   ← 目的操作数
和:  5678H + 1234H = 68ACH

第三步,写清楚谁被改了。 这一步最容易丢分——结果写回的是目的操作数所在的主存单元,不是寄存器:

位置改变前改变后
主存 5678H1234H68ACH
R55678H5679H

R4 不变(源只被读);主存 1234H 也不变(它只是被当作地址读了一次)。(R5)+ 的自增是指令的后效,写回之后才发生,两件事都要写上。

真题的两种形态

第一组 · 题面给指令格式表(2010-43、2013-44、2021-43、2024-43、2026-43)——给一张或几张字段定义表,多数会先问规模(多少条指令、多少寄存器、各寄存器多少位),再问机器码的正反翻译,最后挂一问执行追踪。(2013 年那道是这一组里的另类:它不问规模也不问机器码翻译,问的是编址单位、跳转条数、检测位怎么设、以及数据通路部件。)近几年的题面越来越像真实 ISA:2021 年那道是类 MIPS 的 R/I/J 三型,2024 年那道直接用了 RISC-V 的 add/slli/lw

第二组 · 题面给反汇编(2017-44、2019-45、2023-44、2024-44)——给一段带虚拟地址的机器级代码,问指令地址、跳转目标、寻址方式、字节序,以及这段汇编对应的源程序在做什么。

两组的交界处有一类问法值得单独记:从汇编反推每个寄存器装的是什么角色。2024 年那道给出四条指令 slli/add/lw/add,靠「乘 4 = int 步长」「加基址 = 取地址」这样的语义线索,就能定出哪个寄存器是数组首地址、哪个是下标、哪个是累加和。

这类题是拼盘题的宿主

指令格式是骨架,其他章节的知识常常挂上来。认出哪一问是外挂,就知道该翻哪一章:

  • 溢出与标志位(2024-43 问 add 之后的 OF/CF、2019-45 问 imul 何时 OF=1 与 13! 为什么算错、2017-44 问 cmp 之后的 CF)——数据表示与运算;
  • 控制信号取值(2024-43 问 ExtALUctrALUBsrc)——数据通路;
  • 数据通路部件填空(2013-44 第 (4) 问)——数据通路;
  • 缺页判定与页号计算(2023-44 问取指会不会缺页、2024-44 问 a[i] 所在页号与数组跨几页)——虚拟存储器;
  • 读懂程序在做什么(2019-45 问递归调用几次、哪条一定跳转)——机器级程序表示。

骨架部分的分照样要拿。 这些外挂问通常独立给分,指令格式那几问答对就是稳的。

交卷前扫一眼

数:2 的「宽」取哪一段 · 切:一行一段码回去 · 加:基准是下一条指令的地址 · MAR/MDR 先看题面给没给总线宽度

配套内容

考纲要求、但这 9 道真题没有正面考过的(专题的巩固栏里配了题):

  • 逐级扩展操作码——真题考过操作码空间怎么分配(2021 年那道把 000000 留给 R 型、剩下 63 个编码给 I/J 型),但没考过三地址用剩的编码借给二地址、二地址用剩的再借给一地址这种变长操作码
  • 定长编码与变长编码的平均指令长度——真题只让判 CISC 还是 RISC,没让算过变长能省下多少存储空间
  • 各种寻址方式各要访存几次的横向对比——真题问过的寻址方式有寄存器直接、寄存器间接、自增、相对、变址、以及立即(2023 年那道判过源操作数是立即寻址),但从没让把它们的访存次数摆在一起比过;直接寻址、间接寻址、堆栈寻址也没正面出现过
  • 移位代替乘除在带符号数上的校正——2017 年那道只问了浮点数不能用 shl,没问带符号整数算术右移的取整偏差怎么补

逐题精讲(建设中)——真题作答与 AI 判分入口见站内大题专题

真题练习