Skip to content

指令系统的基本概念

2026 大纲 四(一)指令系统的基本概念

指令字里明明少了一项,程序却照样往下走

按存储程序的工作方式推一遍:CPU 执行完一条指令,必须知道做什么、对谁做、结果放哪、下一条在哪。四项缺一不可。可是翻开任何一台真实机器的指令格式,第四项——下条指令地址——都不在指令字里。

它被 PC 的计数功能吸收了。程序顺序存放、顺序执行,所以下条指令的地址是可以算出来的:PC 加上本条指令的长度即可,硬件自动完成,指令一个字段都不用出。只有需要打破这个顺序时,转移指令才把目标地址写进来。这等于用一个寄存器,换掉了每条指令里的一整个地址字段——本篇后面那条"地址码个数越少、隐含约定越多"的取舍链,第一环就在这里。

顺着同一条思路往下推,还能省:结果地址和源地址共用一个字段,三地址就变成二地址;把一个操作数固定在累加器里,二地址就变成一地址;把操作数全都放在栈顶,一地址就变成零地址。每减掉一个地址字段,指令都变短了,但信息一点没少——它只是从指令字挪进了硬件的隐含约定里。 代价则是灵活性:二地址指令写结果时必然覆盖掉第一个源操作数,因为那本来就是同一个字段。

这条链贯穿全篇。还有一件事需要先立起来:哪些东西属于 ISA、哪些属于微架构。判据只有一句——换一款实现同一 ISA 的处理器,它会不会变? 不变的属 ISA(否则老程序换台机器就跑不了),会变的属微架构。这一句话本身就是近年真题反复出的考点。

交互可视化

加载可视化中...

一、一条指令必须携带哪些信息

从冯·诺依曼结构的"存储程序"工作方式出发,可以推出一条指令必须明显或隐含地包含四项信息:

必须说清的事为什么必须有
操作码不说做什么,硬件无从产生控制信号
源操作数或其地址不说操作谁,运算部件拿不到输入
结果的地址不说结果放哪,算完就丢了
下条指令地址程序要能自动往下走

第四项是关键的一处设计取舍。如果每条指令都显式写出下条指令地址,指令会长得离谱——而绝大多数指令后面跟的就是紧挨着的那一条。于是硬件替它记账:程序计数器 PC 既存放指令地址,又具备计数功能。早期确实存在四地址指令,第四个地址就是下条指令地址;PC 的引入把这一整个字段从每条指令里省掉了。PC 在取指周期自增的时序细节见 指令执行过程

剩下三项归并后,指令的通用结构就是两段:

操作码(OP)+地址码

二、ISA:软件能看见的那一层

一台计算机能执行的机器指令的集合称为指令集体系结构(Instruction Set Architecture,ISA),也就是指令系统——两者是同一个东西的两个名字。它是硬件与软件之间的约定界面:规定了程序员和编译器能看见、能用的一切,把"怎么实现"留给硬件设计者。

ISA 规定(软件可见,换实现也不变)微架构决定(实现细节,可以随芯片改)
指令格式与指令集主频、时钟周期
通用寄存器的个数与位数流水线级数、是否超标量
寻址方式Cache 的容量与层次
数据类型与字长控制器用微程序还是硬布线
异常与中断模型内部总线结构、加法器的进位方式
存储器模型(编址方式、字节序)数据通路是单总线还是多总线

这条界线解释了一件常被忽略的事:同一份 x86 可执行文件能在跨越二十年的处理器上运行,正是因为这二十年里变的全是右列。左列一动,二进制兼容立刻破裂。

图 4.5 MIPS 指令格式

图 4.5 MIPS 指令格式(R 型)

指令格式在 ISA 里是以位段划分的形式规定死的:OP[31:26] 共 6 位,rs/rt/rd 各 5 位,shamt 5 位,func 6 位。寄存器号占 5 位,直接意味着这套 ISA 有 25=32 个通用寄存器——字段位宽就是软件可见规格本身

三、按地址码个数分类

地址码个数不是越多越好也不是越少越好,而是一条"显式写出"与"隐含约定"之间的连续取舍

类型形式语义省掉了什么、代价是什么
三地址OP  A1,A2,A3(A1) OP (A2)A3三个地址全显式给出。源操作数不被破坏、调度自由度最大,代价是指令最长
二地址OP  A1,A2(A1) OP (A2)A1结果地址与第一源地址合并。省一个地址字段,代价是 A1 被覆盖,后面还要用就得先复制
一地址OP  A1(ACC) OP (A1)ACC另一源操作数与结果隐含在 ACC。单目运算不需要 ACC,双目才需要
零地址OP无操作数,或操作数在栈顶地址码全部消失

表里最后两行各有一处容易读偏。一地址指令未必要用 ACC:取反、取负、加 1 这类单目运算,那唯一的地址既是操作数地址也是结果地址,压根不需要第二个操作数,ACC 无从谈起;只有双目运算才要靠 ACC 补上缺掉的那个操作数与结果。零地址也分两种:一种是真的不碰数据(NOPHLT),另一种是操作数隐含在栈顶(栈型机的 ADD)——"零地址"说的是指令字里没有地址字段,不等于这条指令没有操作数。

这条取舍链正好对应教材按"操作数位置怎么指定"划分的四种指令系统风格:

风格操作数在哪典型指令形态代价
累加器型一个操作数与结果恒在 ACC一地址复杂表达式要反复进出 ACC,程序变长
栈型操作数恒在栈顶零地址 / 一地址指令字最短,但表达式求值顺序被写死,不灵活
通用寄存器型立即数、寄存器、存储单元皆可二地址 / 三地址指令较长,但调度灵活
Load/Store 型只有取数/存数指令能访存,运算全在寄存器间三地址指令条数变多,但长度与执行时间高度一致

前两种只在早期机器和虚拟机(如 Java 虚拟机)里使用;现代通用处理器基本都是后两种。Load/Store 型的"规整"正是流水线得以高效运转的前提,这条线索会在 CISC 与 RISC 里接上。

四、操作类型

类别典型指令说明
算术与逻辑运算ADD, SUB, CMP, MUL, DIV, AND, OR, NOT, NEG, XOR, INC, DEC双目与单目运算
移位算术移位、逻辑移位、循环移位一条指令移多位时用桶形移位器实现
数据传送MOV, LOAD, STORE寄存器之间、寄存器与存储单元之间
串操作串传送、串比较、检索对字符串整体操作
顺序控制JMP, 条件转移, CALL, RET, 跳步通过把目标地址送入 PC 实现
CPU 控制停机、开/关中断、模式切换多为特权指令,只能在内核态执行
输入输出IN, OUT统一编址时可由访存指令代劳,无须单设

顺序控制这一行里,转移与调用的根本区别只有一条:要不要保存返回地址JMP 把目标地址送进 PC 就完事,一去不返;CALL 必须先把下条指令的地址存起来(压栈或存入固定单元),RET 再把它取回送进 PC。这一条也是过程调用为什么非要用栈的起点,展开见 机器级表示。输入输出那一行同样值得多看一眼:I/O 指令并非必需——端口与主存统一编址时,普通的访存指令就能读写端口,机器可以完全不设 IN/OUT

指令系统设计要满足完备性(所提供的操作类型足以编制任何可计算的程序),另有兼容性、均匀性(一种运算能处理多种数据类型)、可扩充性(操作码要留出编码空间)三条原则。最后一条直接指向 扩展操作码 的设计。

五、指令字长、机器字长、存储字长

名称定义由什么决定
机器字长CPU 一次能处理的数据位数ALU 位宽、通用寄存器宽度
指令字长一条指令的二进制长度操作码长度 + 地址码长度 × 地址码个数
存储字长存储器一个单元的位数编址单位

三者可以相等,也可以互不相等。早期计算机三者相等——访问一个存储单元就恰好取出一条完整指令或一个完整数据,控制方式因而非常简单。随着数据类型增多、存储容量增大,指令字长逐渐变得可变,出现单字长、双字长指令,控制电路随之复杂化,而多字长指令要多次访存才能取出一条完整指令,反过来拖慢 CPU。因此有一条经验:把使用频度高的指令(数据传送、算术逻辑运算)设计成单字长或短字长格式,把长格式留给不常用的指令。

命名基准与取指次数是两个除数:IBM 370 与 8086 的实例(做"某双字长指令要访存几次"这类题、发现自己拿错除数时展开)

"单字长""双字长"里的那个字,指的是机器字长,不是存储字长。教材给的例子把这个基准摆得很清楚:IBM 370 的指令字长可变,有 16 位(半个字)、32 位(一个字)、48 位(一字半)三种;Intel 8086 则有 8、16、24、32、40、48 位六种。所以

单字长指令=机器字长,双字长指令=2×机器字长,半字长指令=12×机器字长

而"这条指令要访存几次才取得完"是另一个问题——那要拿指令字长去除编址单位。机器字长 32 位、按字节编址时,一条双字长指令是 64 位 = 8 字节,占 8 个存储单元;若该机一次能取 32 位,就要取两次。

指令存放在按字节编址的内存里,为便于取指和地址计算,指令字长通常取 8 的整数倍;算出来不是 8 的倍数就要向上圆整,具体做法见 指令格式与扩展操作码

考点速记

  1. 一条指令必须携带操作码、源操作数地址、结果地址、下条指令地址四项,第四项被 PC 的计数功能吸收,因而指令字里通常没有它。
  2. ISA 是软硬件的约定界面,判据是"换一款实现同一 ISA 的处理器它会不会变"——寄存器个数与位数、指令字格式、寻址方式、数据类型、字节序、异常与中断模型属 ISA;主频、流水线级数与深度、Cache 容量、控制器实现方式、数据通路结构、加法器进位方式属微架构。
  3. 地址码个数减少时信息没有消失,只是从指令字挪进了隐含约定(二地址共用地址、一地址靠 ACC、零地址靠栈顶),四种指令系统风格正是这条取舍链的具体化;三种字长互相独立,命名看机器字长、取指次数看编址单位

这一节在真题里被考过的形式

  • 给四项内容,问哪些由 ISA 规定(2022-18、2025-16、2026-16 连着三年考同一件事)。做法是逐项套那一句判据。2022-18 的四项里,"指令字格式和指令类型""通用寄存器个数和位数"是软件写程序时必须知道的,属 ISA;"CPU 的时钟周期""加法器的进位方式"换个实现就变,属微架构。2025-16 四个选项中只有"是否采用定长指令字格式"是软件看得见的,阵列乘法器、微程序控制器、单总线数据通路全是实现细节。2026-16 反过来问哪个不是——超级流水线是流水线深度的实现选择,属微架构;而虚拟存储管理方式、向量中断、I/O 指令都要写进程序或影响程序行为,属 ISA。⚠️ 最容易被误判的是虚拟存储管理方式与中断响应方式:它们听起来"很硬件",但操作系统必须按约定去写页表、写中断向量表,所以在 ISA 一侧。
  • 给出指令格式的位段划分,反推出几项软件可见规格(2010-43、2015-44)。这类题第一问几乎固定是"最多可定义多少条指令 / 最多有多少个通用寄存器 / MAR 与 MDR 至少各要多少位",全部由字段位宽直接读出:k 位操作码 最多 2k 条指令,r 位寄存器号 最多 2r 个通用寄存器。MAR 的位数由地址空间与编址单位共同决定——2010-43 里主存 128KB 而按字编址、字长 16 位,故单元数 =128KB/2B=64K=216,MAR 是 16 位而不是 17 位;MDR 的位数则等于存储字长 16 位。这一步拿错编址单位,后面全错。
  • 由指令格式定义反推指令条数的上限(2015-44)。该机 7 位操作码,但三地址、二地址、单地址三种格式靠"末 3 位是否全 0""末 6 位是否全 0"区分,而不是靠操作码扩展,所以三种格式共用同一个 7 位操作码空间,最多 27=128。这里要看清题面用什么来区分格式——是操作码前缀,还是地址字段的取值。

易错:把"下条指令地址"当成指令字里不存在的信息。它存在,只是被 PC 的计数功能吸收了;转移指令仍要显式给出。

易错:认为地址码越少能力越弱。信息只是挪进了隐含约定,代价是灵活性(二地址会覆盖第一个源操作数),不是算不出来。

易错:把 Cache 容量、流水线级数、控制器实现方式算进 ISA。判据是"换一款实现同一 ISA 的处理器它会不会变"。

易错:算 MAR 位数时直接拿主存字节数取对数。按字编址时要先除以字的字节数,得到的是单元数

易错:把"单字长指令"里的字当成存储字长。命名基准是机器字长;取指访存几次才看编址单位。

教材出处
  • 袁春风《计算机组成与系统结构(第 3 版)》§4.1.1 指令地址码的个数:一条指令必须包含的四项信息、下条指令地址由 PC 隐含给出、四种地址码个数的含义(印刷页 p91~92)
  • 同上 §4.2 指令系统设计:完备性、兼容性、均匀性、可扩充性四条原则(印刷页 p92)
  • 同上 §4.2.4 操作类型:七类操作、调用指令与转移指令的区别、统一编址时可省去 I/O 指令(印刷页 p96~97)
  • 同上 §4.2.7 指令系统设计风格:累加器型、栈型、通用寄存器型、Load/Store 型(印刷页 p99~100);图 4.5 MIPS 指令格式(印刷页 p104)
  • 唐朔飞《计算机组成原理(第 3 版)》§7.1.2 指令字长:早期三种字长相等、指令字长可变时有单字长与多字长指令、多字长指令要多次访存才能取出一条完整指令、IBM 370 的指令字长为 16 位(半个字)/32 位(一个字)/48 位(一字半)与 Intel 8086 的六种指令字长、指令字长通常取 8 的整数倍、常用指令设计成短字长格式(印刷页 p304)

相关知识

指令格式与扩展操作码数据寻址方式指令执行过程CISC 与 RISC

真题练习