考研学习
解题方法计算机组成原理

计算机组成原理第 4 章:指令系统

408 计算机组成原理「指令系统」复习:核心知识点、真题题型、通用解法与易错点。

Last updated on

本章依据两套材料整理:408 真题 → 计算机组成原理 → 第 4 章 指令系统,以及408 模拟选择题 → 计算机组成原理 → 第 4 章 指令系统。网站真题页把本章划分为:指令格式、数据对齐与大/小端、指令寻址与数据寻址、CISC/RISC、高级语言与机器级代码对应。近年的综合题明显越来越喜欢把本章和数据表示、存储系统、操作系统页式存储、CPU 标志位一起考。(Any Docs)

内容按 408 高频题型与解法 组织,而不是机械按教材知识点展开。


一、先建立整章框架

这一章表面知识不多,但属于408计组里最容易出综合计算题的章节之一。

真正需要掌握的是下面 8 类问题:

题型重要程度核心能力
指令字段位数计算★★★★OP、地址码、寄存器编号
扩展操作码★★★★★不同地址数指令共存
大小端与边界对齐★★★★★地址→字节内容
各种数据寻址方式★★★★★EA 与操作数
PC 相对寻址与转移★★★★★“下一条指令地址 + 位移”
机器码/汇编/C语言互译★★★★★看懂真实机器代码
CALL、RET、栈★★★返回地址与 SP
RISC/CISC、ISA 概念★★选择题记忆

其中最值得重点投入时间的是:

扩展操作码 + 寻址方式 + 大小端 + 机器级程序。


二、题型一:指令格式与字段位数


1. 指令到底由什么组成?

最基本形式:

操作码告诉 CPU:

做什么。

例如:

  • ADD
  • SUB
  • LOAD
  • STORE
  • JMP

地址码告诉 CPU:

对谁做。


2. 操作码至少需要多少位?

如果有 种不同操作,则操作码至少需要:

例如 48 条指令:

所以至少:


三、经典题型:扩展操作码

这是本章第一大重点。


真题 1:2017 年 408

题目

某计算机:

  • 按字节编址;
  • 指令字长固定;
  • 只有三地址和二地址两种格式;
  • 三地址指令 29 条;
  • 二地址指令 107 条;
  • 每个地址字段 6 位。

问:

指令字长至少多少位?

选项:

A. 24 位 B. 26 位 C. 28 位 D. 32 位

网站答案为 A。(Any Docs)


第一步:先看三地址指令

三个地址字段占:

29 条三地址指令至少需要:

位操作码。

因此理论指令长度:

位。

但是问题来了:

为什么答案不是 23?

因为机器按字节编址,指令需要按完整字节存放,因此至少:


第二步:确认剩余编码够不够扩展

5 位 OP:

种编码。

29 种给三地址指令,因此还剩:

种。

每一种剩余操作码都可以把一个 6 位地址字段“抢过来”继续当操作码。

于是可编码二地址指令:

而需要:

条,所以够用。

因此:


四、扩展操作码的本质

不要死背公式。

需要理解:

地址越少,腾出来给操作码的位越多,所以可以定义更多操作。

例如:

三地址:

OP | A1 | A2 | A3

如果某个 OP 编码不用来表示三地址指令,就规定:

一旦看到这个 OP,后面的 A1 不再是地址,而是 OP 的继续部分。

于是变成:

OP扩展 | A2 | A3

这样就是二地址指令。

继续扩展:

OP进一步扩展 | A3

就是一地址指令。

最后所有地址字段都拿来扩展:

OP

就是零地址指令。


五、真题 2:2022 年扩展操作码

题目

16 位定长指令:

  • 地址码 6 位;
  • 有零地址、一地址、二地址指令;
  • 二地址指令 12 条;
  • 一地址指令 254 条。

问:

零地址指令最多多少条?

答案:

(Any Docs)


第一步:二地址格式

两个地址字段:

所以基本操作码:

位。

共有:

种基本编码。

12 条给二地址指令,剩:


第二步:扩成一地址

每一个剩余编码再结合 6 位:

条一地址指令。

实际使用:

条。

所以还剩:

个一地址扩展编码。


第三步:再扩成零地址

再释放最后一个 6 位地址字段:

所以:


六、扩展操作码万能解法

遇到这种题,固定做四步:

第一步:从地址最多的格式开始

例如三地址。

先求基础 OP 位数。

第二步:算该级剩多少编码

第三步:少一个地址,就多出地址字段那么多位给 OP

若地址字段长度为 :

第四步:扣除下一类指令,再继续扩展

一直做到题目问的那一级。


七、模拟题中的高质量变式

网站模拟题有一道:

单地址指令 260 条,二地址指令 12 条,每个地址字段 6 位,求最短指令字长。

如果 OP 只有 4 位:

12 条二地址占掉 12 个,剩 4 个。

最多扩展:

条单地址指令。

但题目需要:

所以 4 位不够。

改为 5 位:

所以最短:

这道题非常适合检查是否真正理解扩展操作码,而不是只会套真题。(Any Docs)


八、题型二:ISA 到底规定什么?

2022 年真题

题目问哪些属于 ISA:

I. 指令字格式和指令类型 II. CPU 时钟周期 III. 通用寄存器数量和位数 IV. 加法器进位方式

答案:

(Any Docs)


怎么判断?

ISA 可以理解成:

软件和硬件之间公开的合同。

程序员、编译器能够“看见”的东西,通常属于 ISA。

例如:

  • 有哪些机器指令;
  • 指令格式;
  • 寻址方式;
  • 寄存器多少个;
  • 寄存器多宽;
  • 数据类型;
  • 异常机制;
  • 可见状态。

而:

  • CPU 多少 GHz;
  • ALU 内部怎么进位;
  • 流水线几级;
  • Cache 具体怎么做;

属于:

微体系结构实现。


九、题型三:大端、小端

这一部分和第 2 章数据表示经常一起考。


十、大小端到底是什么?

假设一个 32 位数据:

12 34 56 78H

它包含四个字节:

12
34
56
78

其中:

  • 12 是最高有效字节 MSB;
  • 78 是最低有效字节 LSB。

大端 Big Endian

低地址放高有效字节:

地址    内容
1000    12
1001    34
1002    56
1003    78

小端 Little Endian

低地址放低有效字节:

地址    内容
1000    78
1001    56
1002    34
1003    12

十一、2016 年真题:直接读某个字节

题目

机器数:

1122334455667788H

从地址:

00008040H

开始存储。

采用小端。

问:

00008046H

存什么?

(Any Docs)


小端从低地址开始:

8040  88
8041  77
8042  66
8043  55
8044  44
8045  33
8046  22
8047  11

所以:


十二、2018 年真题:补码 + 小端 + 机器码

原机器代码:

C7 45 FC 00 00 00 00

对应:

int i = 0;

若改为:

int i = -64;

问机器代码。

(Any Docs)


第一步:求 -64 的 32 位补码

因此:


第二步:小端排列

32 位立即数:

FF FF FF C0

内存从低地址到高地址为:

C0 FF FF FF

所以:

C7 45 FC C0 FF FF FF

即:


十三、注意一个超级易错点

“数值的十六进制表示”和“内存中的字节顺序”不是一回事。

例如 CPU 中一个寄存器值:

6481FEFDH

它还是:

6481FEFDH

不会因为小端就变成:

FDFE8164H

只有问:

它在内存中如何排列

才反过来。

网站模拟题正好有一题:

add r1,r2,-259

拼出的 32 位指令字为:

6481FEFDH

但若问小端机器的内存中字节序列,就是:

FD FE 81 64

(Any Docs)

这个区别必须牢牢记住。


十四、题型四:边界对齐

边界对齐和大小端经常捆绑。


基本原则

一般情况下:

  • char:1 字节边界;
  • short:2 字节边界;
  • int:4 字节边界;
  • double:常见 8 字节边界。

假如 int 要按 4 字节对齐,那么它的首地址应满足:

short:


十五、2012 年经典真题

struct {
    int a;
    char b;
    short c;
} record;

record.a = 273;

首地址:

0xC008

问:

  1. 0xC008 内容;
  2. c 的地址。

网站答案:

0x11
0xC00E

(Any Docs)


1. 先分析 a

小端存储:

C008  11
C009  01
C00A  00
C00B  00

所以:


2. b

char 占 1 字节:

C00C

3. c

short 必须偶地址开始。

下一个地址:

C00D

是奇数。

所以填一个 padding:

C00D:填充

然后:

C00E:c

因此:


十六、2020 年真题:边界对齐 + 小端

struct record {
    short x1;
    int x2;
} a;

首地址:

2020FE00H

x2 机器数:

12340000H

问 34H 所在地址。

(Any Docs)


布局:

FE00 x1
FE01 x1
FE02 padding
FE03 padding
FE04 x2
FE05 x2
FE06 x2
FE07 x2

12340000H 小端:

FE04 00
FE05 00
FE06 34
FE07 12

所以:


十七、这种题的固定模板

看到:

struct + 地址 + 大小端

先不要碰数值。

先做:

第一步:布局

确定成员地址。

第二步:padding

确定边界对齐产生的空洞。

第三步:再处理字节序

最后才把具体数据拆成字节。

顺序不能反。


十八、题型五:数据寻址方式

这是本章最大核心。

建议把下面这张表背到看到题就能写。

寻址方式有效地址/操作数
立即寻址操作数 = A
直接寻址
间接寻址
寄存器寻址操作数 =
寄存器间接
基址寻址
变址寻址
相对寻址
堆栈寻址操作数在栈顶附近

十九、最重要的区别:EA 和操作数

这个坑每年都能坑人。

例如:

并不代表操作数是 3000H。

如果:

那么:

所以做寻址题必须分两步:

再:


二十、2013 年真题:变址寻址

题目给:

形式地址:

并给:

M[1000H]=2000H
M[2000H]=3000H
M[3000H]=4000H

问变址寻址访问到的操作数。

(Any Docs)


变址:

因此:

真正操作数:

所以:

题目故意给:

M[1000]
M[2000]

都是干扰信息。


二十一、直接寻址与间接寻址

假设形式地址:

且:

M[1000H]=2000H
M[2000H]=3000H

直接寻址

操作数:


间接寻址

操作数:

所以间接寻址多一次访问存储器。


二十二、寄存器寻址与寄存器间接

若:

且:


寄存器寻址 R

操作数:


寄存器间接寻址 R

操作数:

网站模拟题恰好考了这个陷阱:立即寻址 600 和寄存器寻址 R 得到的操作数才是 600;直接寻址 600 和寄存器间接 R 得到的都是内存中的 700。(Any Docs)


二十三、基址与变址:最容易混

公式其实完全一样:

真正区别是:

谁变、谁不变,以及谁负责管理。


基址寻址

一般:

  • 基址寄存器保存一段程序/数据所在区域的基地址;
  • 形式地址给偏移;
  • 基址往往由操作系统或装入程序确定;
  • 便于重定位。

想象:

程序原来认为变量位于 offset=100

操作系统把程序装入:

5000

则:


变址寻址

一般:

  • 形式地址给数组首地址;
  • 变址寄存器保存下标或偏移;
  • 变址寄存器不断变化。

所以最适合:

数组、循环。


2017 年真题

问:

最适合按照下标顺序访问一维数组的是?

答案:

(Any Docs)


二十四、2018 年真题:数组地址

double 数组:

A 首地址 = 2000H

访问某个元素:

地址 = 2100H

double 占:

问下标。

(Any Docs)

偏移:

而:

字节。

所以:

答案:


二十五、数组地址必须会的万能公式

一维数组:

例如 int:

于是编译器经常把:

a[i]

翻译成:

slli temp, i, 2
add  temp, base, temp
lw   x, 0(temp)

因为:


二十六、二维数组是近年重点

C语言二维数组:

int a[M][N];

按行优先存储。

于是:

如果每行 64 个 int:

所以:

这正是 2023 年真题的核心。(Any Docs)


二十七、题型六:相对寻址

这是必须满分掌握的东西。

核心公式不是:

而通常是:


二十八、2009 年真题

转移指令:

  • 首地址 2000H;
  • 长 2 字节;
  • 位移 06H;
  • 每取一个字节 PC 加 1。

(Any Docs)

取完后:

再加:

所以:

答案:


二十九、为什么一定是“下一条指令”?

因为 CPU 先取当前指令。

取指结束以后:

PC 通常已经自动指向下一条顺序指令。

然后执行阶段才计算:

因此 PC 的基准不是当前指令起始地址。

这是相对寻址最大的坑。


三十、反向跳转:模拟题

题目:

  • 两字节跳转指令;
  • 执行前 PC=200CH;
  • 目标为 1FB0H;
  • 第二字节为 8 位补码偏移。

(Any Docs)

取完指令:

偏移:

8 位补码:

因此:


三十一、相对寻址万能模板

以后看到:

JMP / Jcc / CALL + 相对位移

直接写:

然后:

如果题目反过来求 offset:


三十二、带补码位移必须符号扩展

例如 16 位形式地址:

FF12H

如果它表示补码,则不是:

而是一个负数。

扩展到 32 位:

FFFFFF12H

三十三、2019 年真题:基址 + 补码 + 大端

题目:

  • 基址寄存器:
F0000000H
  • 位移:
FF12H

16 位补码;

  • 操作数:
1234FF00H
  • 大端;
  • 问最低有效字节 LSB 地址。

(Any Docs)


第一步:符号扩展


第二步:EA

得到:


第三步:判断 LSB 在哪里

32 位共 4 字节。

大端:

EA      12
EA+1    34
EA+2    FF
EA+3    00

所以 LSB 位于:

即:

这道题把:

基址 + 补码符号扩展 + 大端

三个知识点一次考完,非常典型。


三十四、题型七:寻址范围

2014 年真题

32 位指令:

  • 操作码+寻址方式:8 位;
  • 16 个通用寄存器;
  • Store 有源寄存器、基址寄存器;
  • 其余位为补码偏移。

(Any Docs)

16 个寄存器需要:

位编号。

两个寄存器字段:

所以偏移量:

位。

16 位补码范围:

即:


三十五、题型八:直接、先变址后间址等复合寻址

2016 年真题

若:

先变址,后间址

形式地址 D,变址寄存器 I。

(Any Docs)

先变址:

然后间址:

因此:

所谓“先 X 后 Y”:

就按文字顺序一层一层算。


三十六、非常重要:指令寻址 vs 数据寻址

很多人把两个概念混在一起。

指令寻址

回答:

下一条执行哪条指令?

包括:

  • 顺序寻址;
  • 跳跃寻址。

数据寻址

回答:

当前指令需要的数据在哪里?

包括:

  • 立即;
  • 直接;
  • 间接;
  • 寄存器;
  • 基址;
  • 变址;
  • 相对……

网站模拟题也专门考过:程序运行中通常是指令寻址、数据寻址反复交替进行。(Any Docs)


三十七、题型九:2010 年综合大题——本章极经典

这是非常值得完整掌握的一道题。

题目给出 16 位指令格式

15~12 | 11~9 | 8~6 | 5~3 | 2~0
 OP   |  Ms  | Rs  | Md  | Rd

其中:

  • OP:操作码;
  • Ms:源寻址方式;
  • Rs:源寄存器;
  • Md:目的寻址方式;
  • Rd:目的寄存器。

主存:

  • 128KB;
  • 字长 16 位;
  • 按字编址。

并要求:

  1. 最多多少指令、寄存器?
  2. MAR/MDR 至少几位?
  3. 编码 add (R4),(R5)+;
  4. 执行后谁变化?

(Any Docs)


第一问:指令数

OP 4 位:

最多:


通用寄存器

寄存器编号 3 位:

所以:

个。


MAR

主存容量:

字长:

按字编址,所以字数:

而:

因此:


MDR

一个存储字:

所以:


三十八、2010 真题的机器码编码

给:

add (R4),(R5)+

且:

  • ADD:0010
  • (Rn):寄存器间接 → 001
  • (Rn)+:寄存器间接自增 → 010
  • R4:100
  • R5:101

所以:

0010 001 100 010 101

分组:

0010 0011 0001 0101

得到:

(Any Docs)


三十九、执行后的数据变化

已知:

R4 = 1234H
R5 = 5678H

M[1234H] = 5678H
M[5678H] = 1234H

源:

(R4)

所以源操作数:

目的:

(R5)+

原目的操作数:

ADD:

写回:

同时 (R5)+ 自动自增。

因为按字编址:

于是:

最终:


四十、这里有一个很重要的变式

如果题目改成:

按字节编址

且访问的是 16 位字。

那么自增量通常就可能是:

而不是 1。

所以永远判断:

地址的最小单位是什么?


四十一、题型十:条件转移与标志位

机器级代码题离不开:

  • CF;
  • ZF;
  • SF/NF;
  • OF。

ZF

结果为 0:


SF / NF

通常保存结果最高位。

结果负:


CF

主要用于:

无符号数加减。

减法时:

发生借位 → CF=1。


OF

主要判断:

有符号数运算是否溢出。


四十二、无符号和有符号比较必须分开

这是408常考陷阱。


无符号小于

做:

如果发生借位:

所以:

通常对应 CF。


无符号小于等于

对应:

或:

即:

2013 年真题就要求设计这样的条件检测位。(Any Docs)


四十三、有符号“小于”

不能简单看 SF。

正确关系:

网站模拟题专门考了 jl:

有符号小于时转移。

答案正是:

(Any Docs)


四十四、有符号条件判断建议记这组

严格小于:

大于等于:

小于等于:

大于:


四十五、题型十一:CALL / RET / 栈

网站模拟题:

题目

双字长 CALL:

  • 当前 PC=2000H;
  • 目标地址 4000H;
  • SP=0100H;
  • 按字编址;
  • 栈向低地址增长;
  • 先修改 SP,再压数据。

问 CALL 后:

SP 和新栈顶是什么?

答案:

00FFH
2002H

(Any Docs)


为什么不是把 4000H 压栈?

CALL 做:

  1. 保存返回地址;
  2. PC 跳到函数入口。

返回地址不是被调函数地址。

而是:

CALL 执行完以后下一条顺序指令地址。

双字长、按字编址:

所以压入:


SP

栈向低地址增长:

然后:

最后:


四十六、CALL 万能模型

CALL 的核心可以概括成:

然后:

RET 则:


四十七、题型十二:高级语言与机器级代码

这是近几年本章最值得重视的部分。

真题页可以明显看到:

  • 2017;
  • 2019;
  • 2023;
  • 2024;

连续出现了 C / 汇编 / 机器码相关综合题。(Any Docs)

不能只背:

“立即寻址是什么”。

必须真的会看:

mov
add
sub
cmp
jmp
call
ret
slli
lw

四十八、2017 真题:判断 RISC/CISC

机器代码中出现:

push ebp
cmp dword ptr [ebp-0Ch], ecx
shl edx,1

不同指令长度不同。

例如:

  • push:1 字节;
  • cmp:3 字节;
  • shl:2 字节。

因此属于:

(Any Docs)

为什么?

因为典型 x86/CISC 特点:

  • 指令长度可变;
  • 指令格式较多;
  • 可直接对内存操作;
  • 指令功能复杂。

四十九、机器代码长度怎么算?

2017 真题给:

第一条:

00401020

最后一条 ret:

0040107F

且 ret 占 1 字节。

因此结束位置的下一地址:

00401080

总字节数:

得到:

字节。

所以:

(Any Docs)


五十、这种问题千万不要用

直接作为大小。

如果最后一条指令长度是 ,则:


五十一、2017 真题:unsigned 陷阱

程序里:

unsigned n

当:

计算:

不是 -1。

而是 32 位无符号整数模:

运算。

所以:

比较:

和:

显然无符号:

减法发生借位,所以:

(Any Docs)


五十二、2017 真题另一个非常好的问题

源码里整数:

power *= 2;

编译成:

shl edx,1

如果把 int 换成 float,还能这样吗?

不能。

整数左移:

通常等价于:

但浮点数编码包含:

符号位 | 阶码 | 尾数

整体二进制左移会破坏字段意义。

所以浮点乘 2 应使用:

浮点运算指令。

(Any Docs)


五十三、2019 真题:递归 + CALL + 相对寻址

这道题非常有代表性。

代码实现:

有:

cmp
jle
call
imul
jmp
ret

其中:

00401025 E8 D6 FF FF FF call f1

(Any Docs)


CALL 下一条指令地址

CALL 从:

00401025

开始,长 5 字节。

因此:


CALL 的相对偏移

目标:

00401000

所以:

即:

32 位补码:

FFFFFFD6H

为什么机器码里是:

D6 FF FF FF

而不是:

FF FF FF D6

因为小端。

于是:

这是“相对寻址 + 补码 + 小端”三合一。(Any Docs)


五十四、2019:整数溢出

但 32 位 int 最大正数:

显然:

所以溢出。

正确修改方向:

返回值和乘法中间结果都扩大到 64 位。

例如:

long long

网站真题解析也是这个结论。(Any Docs)


五十五、乘法溢出的高低位判据

如果两个 32 位补码相乘得到 64 位结果:

高32位 H | 低32位 L

如果结果能够正确压缩成 32 位,则:

高 32 位必须恰好等于低 32 位符号位的扩展。

即如果 L 的最高位是 0:

如果 L 的最高位是 1:

否则:

这也是 2019 真题的考点。(Any Docs)


五十六、2023 年真题:机器级代码综合题

这题很重要,因为代表当前408命题方向。

C代码:

for (i=0;i<24;i++)
    for (j=0;j<64;j++)
        a[i][j]=10;

其中第19条机器指令:

004010AE
C7 84 82 00 20 42 00 0A 00 00 00

mov [ecx+edx*4+00422000h],0Ah

(Any Docs)


考法1:求下一条指令地址

数机器码字节:

C7
84
82
00
20
42
00
0A
00
00
00

共:

所以:

答案:


五十七、考法2:判断 JMP 寻址

有:

00401079 EB 09 jmp 00401084

本条长 2 字节。

下一条地址:

再加位移:

所以:

(Any Docs)


五十八、考法3:二维数组地址

指令:

mov [ecx+edx*4+00422000h],0Ah

数组:

int a[24][64]

首地址:

00422000H

已知:

edx = j

那么:

因此 ecx 必须保存:

即:

(Any Docs)


五十九、考法4:立即寻址

指令:

mov [...],0Ah

常数:

0Ah

直接写在机器指令中。

因此源操作数是:


六十、考法5:根据机器码判断大小端

机器指令里数组首地址:

00422000H

在内存中对应:

00 20 42 00

常数:

0000000AH

对应:

0A 00 00 00

所以:

低有效字节放在低地址。

即:

(Any Docs)


六十一、2023 题为什么特别值得学?

因为这一题把:

  • 指令长度;
  • PC;
  • 相对寻址;
  • 立即寻址;
  • 二维数组;
  • 小端;
  • 页式存储;

全部串起来了。

这就是现在408越来越典型的模式:

一道综合题跨三四章。


六十二、2024 年真题:RISC-V 风格机器级代码

源码:

sum += a[i];

对应:

slli r4,r2,2
add  r4,r3,r4
lw   r5,0(r4)
add  r1,r1,r5

(Any Docs)

逐条解释。


第一条

slli r4,r2,2

即:

也就是:

所以 R2 保存:


第二条

add r4,r3,r4

即:

因此 R3 保存:


第三条

lw r5,0(r4)

取得:


第四条

add r1,r1,r5

即:

所以:

最终映射:

r1 → sum
r2 → i
r3 → a首地址

(Any Docs)


六十三、2024 年:真正算数组元素

题目给:

数组首地址:

0013DFF0H

int:

所以:

得到:


内存:

0013E004 : DC
0013E005 : EC
0013E006 : FF
0013E007 : FF

小端恢复成数:

FF FF EC DC

所以:

(Any Docs)


六十四、继续算 sum

原:

sum = 00001332H

所以:

32 位运算结果:

这类题说明必须把:

补码加法 + 大小端 + 数组寻址

真正联通起来。


六十五、2024:数组类型改变怎么办?

原来:

int a[]

每个元素:

字节,因此:

slli r4,r2,2

如果改成:

short a[]

每个:

字节。

因此变成:

slli r4,r2,1

(Any Docs)


六十六、以后看到移位计算数组偏移量,直接这样判断

若元素大小:

则:

所以:

类型大小常见偏移
1 B不移
2 B左移 1
4 B左移 2
8 B左移 3

六十七、题型十三:CISC 与 RISC

真题直接考过。

2009 年真题:

关于 RISC,错误的是“普遍采用微程序控制器”。

答案为该项。(Any Docs)


六十八、RISC 特征

可以直接记成:

少、简、规、寄、流水、硬布线。

即:

  • 指令种类较少;
  • 寻址方式较少;
  • 指令格式规整;
  • 大量通用寄存器;
  • 适合流水线;
  • 多使用硬布线控制;
  • Load/Store 思想明显;
  • 编译器承担更多优化工作。

六十九、CISC 特征

相对来说:

  • 指令多;
  • 寻址方式多;
  • 指令长度可能变化;
  • 指令功能复杂;
  • 一条指令可能完成复杂操作;
  • 传统实现较常使用微程序控制。

但千万不要把它理解成:

CISC 不能流水线。

这是错的。

网站模拟题也专门指出:CISC 同样可以使用流水线,只是实现通常更复杂。(Any Docs)


七十、RISC / CISC 高频判断陷阱

错误说法 1

RISC 普遍微程序控制。

错。

典型 RISC 更倾向:


错误说法 2

CISC 不支持流水线。

错。


错误说法 3

RISC 指令一定只有一个周期。

教材表述通常是:

大多数指令执行时间规整、易于单周期或流水化。

不要把所有架构现实实现绝对化。


错误说法 4

RISC 寄存器少。

恰好相反:


七十一、关于本站模拟题里一个分类问题

模拟题第 4 章开头还收录了诸如:

微指令字段直接编码、水平型/垂直型微指令、控制存储器容量

这样的题。(Any Docs)

这些题本身是好题,但是从408标准知识结构看,它们更属于下一章:

CPU / 控制器 / 微程序控制器

而不是本章“机器指令系统”的核心。

因此复习第 4 章时,不要因为它们位于网页第 4 章就把微程序控制当成第 4 章核心重点。等学第 5 章 CPU 时再系统解决更合适。


七十二、本章所有寻址方式必须形成这张脑图

可以直接这样记。

操作数就在指令里


操作数就在寄存器里


指令里的 A 就是内存地址


指令里的 A 指向一个“地址”


寄存器存的是内存地址


基地址 + 偏移


数组首址 + 下标


下一条指令地址 + 位移


七十三、寻址题统一解题法

无论题目怎么变,做四步。

Step 1:确认寻址方式

不要急着算。


Step 2:写公式

例如变址:

相对:

寄存器间接:


Step 3:判断 A 是否为补码

如果是补码:

先符号扩展。


Step 4:最后区分 EA 和操作数

如果 EA 指向内存:


七十四、机器级代码题统一解题法

现在408越来越爱考这种,建议固定按下面顺序:

1. 看地址

先知道每条机器指令从哪开始。

2. 数机器码字节

得到指令长度。

3. 看汇编语义

确定寄存器谁代表谁。

4. 看寻址表达式

例如:

[base + index*scale + displacement]

转换为:

5. 看立即数

立即数直接就是操作数。

6. 判断大小端

把连续字节重新组合。

7. 遇到 JMP/CALL

永远先算:

再算位移。

8. 遇到 C 数据类型

先看:

  • signed / unsigned;
  • char / short / int;
  • 数组元素大小。

七十五、最值得背的 12 个公式/结论

1. 操作码位数

2. 寄存器编号

若有 个寄存器:

3. 补码范围

位:

4. 直接寻址

5. 间接寻址

6. 寄存器间接

7. 基址

8. 变址

9. 相对寻址

这里的 PC 通常是:

已经指向下一条指令的 PC。

10. 一维数组

11. 二维数组

C语言:

其中 N 为每行元素数。

12. 有符号小于


七十六、本章最容易丢分的 10 个坑

坑 1:相对寻址拿当前指令首地址加 offset

错。

通常是:


坑 2:看到 FFxx 就当正数

先看题目说没说:

补码表示。

如果说了,需要符号扩展。


坑 3:EA 与 Operand 混淆

通常:


坑 4:把寄存器间接当寄存器寻址

寄存器寻址:

寄存器间接:


坑 5:基址与变址死看公式

公式一样。

看用途:

基址 → 重定位。

变址 → 数组。


坑 6:把寄存器里的数按小端倒过来

不行。

大小端只涉及:

多字节数据在按字节编址内存中的排列。


坑 7:struct 忘记 padding

先排结构体地址,再处理大小端。


坑 8:CALL 把目标地址压栈

CALL 压入的是:


坑 9:signed / unsigned 条件码混用

无符号主要看:

有符号主要看:


坑 10:机器码地址差少算最后一条长度

必须算到:

最后一条指令之后的地址。


七十七、结合真题,怎样判断本章重点?

从网站所收录真题可以看出:

第一梯队:★★★★★

寻址方式

典型年份包括 2009、2011、2013、2014、2016、2017、2018、2019、2020,以及 2010/2013 大题。(Any Docs)

这几乎可以视为:

本章绝对核心。


第一梯队:★★★★★

机器级代码 + C语言

2017、2019、2023、2024 都有很有代表性的综合考查。(Any Docs)

而且近年的综合程度明显高于单纯背概念。


第二梯队:★★★★

大小端 + 数据存放 + 对齐

2012、2016、2018、2020,以及 2019、2023、2024 综合题都涉及或可关联。(Any Docs)


第二梯队:★★★★

指令格式 + 扩展操作码

2017、2022 都有直接真题,2021 综合题还要求分析 R/I/J 型格式。(Any Docs)


第三梯队:★★

RISC/CISC

本身不难,通常作为选择题或机器代码综合题中的一个小问。


七十八、2021 年综合题值得额外理解

网站的 2021 真题给了一种 16 位 ISA:

  • R 型;
  • I 型;
  • J 型;
  • 2 位寄存器号;
  • I 型有 6 位立即数;
  • J 型有 10 位 target。

并问:

  • ALU 宽度;
  • 主存空间;
  • IR/MAR/MDR;
  • 能定义多少操作;
  • 寄存器数;
  • 减法/乘法结果及溢出;
  • imm 符号扩展;
  • 无条件转移格式。

(Any Docs)

这类题的意义在于:

不要把“指令格式题”理解成只有扩展操作码。

它还可能要求从一个 ISA 反推整个机器结构。

例如字长 16 位:

地址线 20 位、按字节编址:

16 位定长指令:

20 位地址:

8 位数据总线:

寄存器编号 2 位:

个寄存器。


七十九、预测未来很可能出现的考法

基于这些真题,建议特别防下面几种组合。

预测 1:RISC-V 机器码 + 数组 + Cache

给:

slli
add
lw

要求计算:

  1. 数组元素地址;
  2. 所属 Cache 块;
  3. Cache 组号;
  4. 是否命中;
  5. 最终寄存器值。

这是:

第 3 章 + 第 4 章。

2024 已经非常接近这个方向。


预测 2:机器码 + 虚拟地址 + TLB/页表

例如给:

lw r5,12(r4)

要求:

  1. 算有效地址;
  2. 求虚拟页号;
  3. 查 TLB;
  4. 查页表;
  5. 得物理地址;
  6. 再查 Cache。

这是极其自然的:

指令系统 + 存储层次 + 操作系统

综合题。

2023/2024 的命题已经表现出这种跨章节趋势。(Any Docs)


八十、预测 3:分支指令 + 标志位 + 流水线

给:

cmp
jge

问:

  1. 标志位;
  2. 是否跳转;
  3. 目标地址;
  4. 流水线是否冲刷;
  5. CPI 或周期数。

这会把:

第 2 章运算 + 第 4 章指令 + 第 5 章流水线

串起来。


八十一、预测 4:struct + 对齐 + Cache

给:

struct {
    char a;
    int b;
    short c;
} x[100];

再给 Cache:

  • 块大小;
  • 组数;
  • 映射方式。

问访问:

x[i].b

的地址和 Cache 位置。

必须先:

  1. 求结构体内部 padding;
  2. 求 sizeof(struct);
  3. 求数组元素地址;
  4. 再求 Cache 地址字段。

这类综合题质量很高。


八十二、预测 5:扩展操作码反推设计

不直接问:

最多多少条零地址指令。

而是问:

要同时支持 X 条三地址、Y 条二地址和 Z 条一地址,至少多长指令?

这种题本质仍是:

所以只要真正理解扩展操作码,不怕任何变形。


八十三、给出一道很值得练的自拟综合题

某 32 位小端计算机按字节编址,执行:

lw r3,-8(r2)

已知:

r2 = 00002004H

内存:

00001FFC  78
00001FFD  56
00001FFE  34
00001FFF  12

问:

  1. 属于什么寻址方式?
  2. EA 是多少?
  3. r3 最终是多少?

第一步:寻址方式

形式:

-8(r2)

属于基址/基址加偏移形式。


第二步:EA


第三步:恢复32位数

低地址依次:

78 56 34 12

小端恢复:

12345678H

因此:

这一道题就同时训练了:

  • 补码偏移;
  • 基址寻址;
  • 有效地址;
  • 小端。

八十四、再来一道相对寻址预测题

某转移指令:

首地址 = 1000H
长度 = 4B
16位相对位移字段 = FFF8H

问跳转目标。


位移:

FFF8H

是 16 位补码:

下一条地址:

因此:

所以:

这里最大陷阱就是有人算:

得到错误答案。


八十五、这一章复习到什么程度才算真正学会?

至少要做到下面这些不需要翻书。

看到:

29条三地址、107条二地址、地址字段6位

马上想到:

扩展操作码。

看到:

FF12H,补码位移

马上想到:

符号扩展。

看到:

jmp
call
jge

马上想到:

看到:

[r3+r2*4]

马上想到:

数组首地址 + 下标 × 元素大小。

看到:

DC EC FF FF

且小端,马上恢复:

FFFFECDCH

看到:

jl

马上想到:

看到:

char + int + short

马上先算:

alignment / padding。

看到:

CALL

马上想到:

返回地址入栈,而不是目标地址入栈。

如果这些已经形成条件反射,第 4 章基本就稳了。


八十六、最后给出一份本章复习优先级

如果现在准备408强化,建议按这个顺序刷:

  1. 所有寻址方式及 EA 计算
  2. PC 相对寻址
  3. 数组地址计算
  4. 小端/大端
  5. 边界对齐
  6. 机器级代码与 C 语言对应
  7. 扩展操作码
  8. CALL / RET / 标志位
  9. ISA
  10. RISC / CISC

尤其推荐把网站中的这些题真正自己再算一遍:

2010 综合题 → 2013 条件转移大题 → 2017 指令格式与机器级代码 → 2019 递归机器级代码 → 2021 ISA 格式综合题 → 2023 二维数组机器级代码 → 2024 sum += a[i] 综合题。

这几道基本把本章从传统“寻址方式”一直覆盖到现在408喜欢考的“C语言—汇编—机器指令—存储系统”综合方向。(Any Docs)

网站本身也明确建议分析408时遵循“知识点 → 真题 → 总结命题方式 → 模拟题补充”的路径;本章同样按这个顺序筛题,而没有把模拟题数量直接当成考频。(Any Docs)

On this page

一、先建立整章框架二、题型一:指令格式与字段位数1. 指令到底由什么组成?2. 操作码至少需要多少位?三、经典题型:扩展操作码真题 1:2017 年 408题目第一步:先看三地址指令第二步:确认剩余编码够不够扩展四、扩展操作码的本质五、真题 2:2022 年扩展操作码题目第一步:二地址格式第二步:扩成一地址第三步:再扩成零地址六、扩展操作码万能解法第一步:从地址最多的格式开始第二步:算该级剩多少编码第三步:少一个地址,就多出地址字段那么多位给 OP第四步:扣除下一类指令,再继续扩展七、模拟题中的高质量变式八、题型二:ISA 到底规定什么?2022 年真题怎么判断?九、题型三:大端、小端十、大小端到底是什么?大端 Big Endian小端 Little Endian十一、2016 年真题:直接读某个字节题目十二、2018 年真题:补码 + 小端 + 机器码第一步:求 -64 的 32 位补码第二步:小端排列十三、注意一个超级易错点“数值的十六进制表示”和“内存中的字节顺序”不是一回事。十四、题型四:边界对齐基本原则十五、2012 年经典真题1. 先分析 a2. b3. c十六、2020 年真题:边界对齐 + 小端十七、这种题的固定模板第一步:布局第二步:padding第三步:再处理字节序十八、题型五:数据寻址方式十九、最重要的区别:EA 和操作数二十、2013 年真题:变址寻址二十一、直接寻址与间接寻址直接寻址间接寻址二十二、寄存器寻址与寄存器间接寄存器寻址 R寄存器间接寻址 R二十三、基址与变址:最容易混基址寻址变址寻址2017 年真题二十四、2018 年真题:数组地址二十五、数组地址必须会的万能公式二十六、二维数组是近年重点二十七、题型六:相对寻址二十八、2009 年真题二十九、为什么一定是“下一条指令”?三十、反向跳转:模拟题三十一、相对寻址万能模板三十二、带补码位移必须符号扩展三十三、2019 年真题:基址 + 补码 + 大端第一步:符号扩展第二步:EA第三步:判断 LSB 在哪里三十四、题型七:寻址范围2014 年真题三十五、题型八:直接、先变址后间址等复合寻址2016 年真题三十六、非常重要:指令寻址 vs 数据寻址指令寻址数据寻址三十七、题型九:2010 年综合大题——本章极经典题目给出 16 位指令格式第一问:指令数通用寄存器MARMDR三十八、2010 真题的机器码编码三十九、执行后的数据变化四十、这里有一个很重要的变式四十一、题型十:条件转移与标志位ZFSF / NFCFOF四十二、无符号和有符号比较必须分开无符号小于无符号小于等于四十三、有符号“小于”四十四、有符号条件判断建议记这组四十五、题型十一:CALL / RET / 栈题目为什么不是把 4000H 压栈?SP四十六、CALL 万能模型四十七、题型十二:高级语言与机器级代码四十八、2017 真题:判断 RISC/CISC四十九、机器代码长度怎么算?五十、这种问题千万不要用五十一、2017 真题:unsigned 陷阱五十二、2017 真题另一个非常好的问题五十三、2019 真题:递归 + CALL + 相对寻址CALL 下一条指令地址CALL 的相对偏移为什么机器码里是:五十四、2019:整数溢出五十五、乘法溢出的高低位判据五十六、2023 年真题:机器级代码综合题考法1:求下一条指令地址五十七、考法2:判断 JMP 寻址五十八、考法3:二维数组地址五十九、考法4:立即寻址六十、考法5:根据机器码判断大小端六十一、2023 题为什么特别值得学?六十二、2024 年真题:RISC-V 风格机器级代码第一条第二条第三条第四条六十三、2024 年:真正算数组元素六十四、继续算 sum六十五、2024:数组类型改变怎么办?六十六、以后看到移位计算数组偏移量,直接这样判断六十七、题型十三:CISC 与 RISC六十八、RISC 特征六十九、CISC 特征七十、RISC / CISC 高频判断陷阱错误说法 1错误说法 2错误说法 3错误说法 4七十一、关于本站模拟题里一个分类问题七十二、本章所有寻址方式必须形成这张脑图操作数就在指令里操作数就在寄存器里指令里的 A 就是内存地址指令里的 A 指向一个“地址”寄存器存的是内存地址基地址 + 偏移数组首址 + 下标下一条指令地址 + 位移七十三、寻址题统一解题法Step 1:确认寻址方式Step 2:写公式Step 3:判断 A 是否为补码Step 4:最后区分 EA 和操作数七十四、机器级代码题统一解题法1. 看地址2. 数机器码字节3. 看汇编语义4. 看寻址表达式5. 看立即数6. 判断大小端7. 遇到 JMP/CALL8. 遇到 C 数据类型七十五、最值得背的 12 个公式/结论1. 操作码位数2. 寄存器编号3. 补码范围4. 直接寻址5. 间接寻址6. 寄存器间接7. 基址8. 变址9. 相对寻址10. 一维数组11. 二维数组12. 有符号小于七十六、本章最容易丢分的 10 个坑坑 1:相对寻址拿当前指令首地址加 offset坑 2:看到 FFxx 就当正数坑 3:EA 与 Operand 混淆坑 4:把寄存器间接当寄存器寻址坑 5:基址与变址死看公式坑 6:把寄存器里的数按小端倒过来坑 7:struct 忘记 padding坑 8:CALL 把目标地址压栈坑 9:signed / unsigned 条件码混用坑 10:机器码地址差少算最后一条长度七十七、结合真题,怎样判断本章重点?第一梯队:★★★★★第一梯队:★★★★★第二梯队:★★★★第二梯队:★★★★第三梯队:★★七十八、2021 年综合题值得额外理解七十九、预测未来很可能出现的考法预测 1:RISC-V 机器码 + 数组 + Cache预测 2:机器码 + 虚拟地址 + TLB/页表八十、预测 3:分支指令 + 标志位 + 流水线八十一、预测 4:struct + 对齐 + Cache八十二、预测 5:扩展操作码反推设计八十三、给出一道很值得练的自拟综合题第一步:寻址方式第二步:EA第三步:恢复32位数八十四、再来一道相对寻址预测题八十五、这一章复习到什么程度才算真正学会?八十六、最后给出一份本章复习优先级