3.1 指令格式
本节讨论计算机指令的二进制编码格式,包括指令由哪些部分组成,以及不同地址数量的指令结构。指令格式是计算机硬件与软件之间的关键接口,它直接影响到CPU的设计复杂度、程序的存储空间以及指令的执行效率。
核心概念
1. 机器指令的基本格式
一条机器指令是计算机执行一个基本操作的命令,它是一组有意义的二进制代码。指令通常由两部分组成:
- 操作码字段 (Opcode):指明该指令要执行的操作性质和功能,例如加、减、取数、存数、跳转等。操作码是指令的核心,译码电路通过识别操作码来控制执行部件完成相应操作。
- 地址码字段 (Address Field):指明操作数或操作数的地址。地址码字段并不总是直接指向内存地址,它可以是:
- 内存地址:操作数存储在内存中的位置。
- 寄存器编号:操作数存储在某个通用寄存器中。
- 立即数:操作数本身就包含在指令的地址码字段中。
+--------------+-----------------+
| 操作码 | 地址码 |
+--------------+-----------------+此外,指令中还可能包含寻址模式字段,用来解释地址码字段应如何解读,我们将在后续章节详细讨论。
2. 指令长度
- 定义:一条指令中所包含的二进制代码的位数,也称为指令字长。
- 指令字长与机器字长的关系:两者没有固定的关系。指令字长可以等于、大于或小于机器字长。
- 定长指令字结构:指令系统中所有指令的长度都相等。这是精简指令集计算机 (RISC),如MIPS和ARM架构的典型特征。
- 优点:指令译码和取指过程简单、规整,非常有利于实现指令流水线,从而提高处理器性能。
- 缺点:灵活性较差,对于简单的操作可能会浪费存储空间。
- 变长指令字结构:指令长度随指令功能而异。这是复杂指令集计算机 (CISC),如Intel x86架构的典型特征。
- 优点:灵活性高,可以根据操作的复杂程度和寻址方式的不同,使用不同长度的指令,从而提高代码密度,节约存储空间。
- 缺点:增加了指令译码和预取的复杂性,不利于实现简单的指令流水线。
- 定长指令字结构:指令系统中所有指令的长度都相等。这是精简指令集计算机 (RISC),如MIPS和ARM架构的典型特征。
3. 地址码结构 (N地址指令)
根据指令中显式包含的地址码数量,可以将指令分为不同类型。一条完整的运算类指令需要包含以下信息:
- 两个源操作数的地址 (
) - 存放结果的目标地址 (
) - 下一条指令的地址 (
)
现代计算机通常使用程序计数器 (PC) 来自动指向下一条指令,因此
四地址指令:
OP A1, A2, A3, A4- 含义:
;下一条指令地址为 。 - 特点: 指令长度过长,访存次数多,完全不切实际。程序计数器(PC)的出现使其被历史淘汰。
- 含义:
三地址指令:
OP A1, A2, A3- 含义:
。下一条指令地址由PC隐含给出 ( )。 - 特点: 编程直观,可以保留两个原始操作数。但指令长度仍较长,访存次数多(取指令1次,取两个操作数2次,存结果1次,共4次访存)。在寄存器数量众多的现代CPU中较为常见(此时A1, A2, A3均为寄存器)。
- 含义:
二地址指令:
OP A1, A2- 含义:
。将其中一个操作数地址 同时用作结果地址,这会破坏原始操作数 。 - 特点: 指令长度适中,是通用寄存器结构计算机最常用的格式。如果需要保留
的原始值,需要先执行一条 MOV A3, A1指令,会增加指令数量。
- 含义:
一地址指令:
OP A- 含义:
。需要一个隐含的累加寄存器(Accumulator, Acc) 作为固定的源操作数和目标地址。 - 特点: 访存次数减少为2次(取指令、取操作数),指令短,硬件设计简单。但对累加器的依赖性强,导致其成为性能瓶颈,限制了并行计算的可能。
- 含义:
零地址指令:
OP- 含义: 操作数地址隐含在堆栈 (Stack) 的顶部。通常从栈顶弹出两个操作数,运算后将结果压入栈顶。例如,
ADD指令会执行TOS = (TOS-1) + (TOS),其中TOS是栈顶指针。 - 特点: 指令最短,非常适合表达式求值和过程调用。但并非所有计算都适合用堆栈来完成,其性能依赖于堆栈操作的效率。
- 含义: 操作数地址隐含在堆栈 (Stack) 的顶部。通常从栈顶弹出两个操作数,运算后将结果压入栈顶。例如,
易考点和难点
易考点
- 理解不同地址数量指令的含义、执行过程和访存次数。
- 知道PC(程序计数器)、Acc(累加器)、SP(堆栈指针)在不同指令格式中的隐含作用。
- 比较定长指令与变长指令的优缺点,并联系RISC与CISC架构。
难点
- 指令操作码的编码方式,特别是扩展操作码法,这是设计指令系统的核心技术之一,也是考试的重点和难点。
- 理解指令格式设计中的权衡(Trade-off):在指令长度、功能完备性、硬件实现复杂度、程序大小和执行速度之间做出选择。
3.1.3 指令的操作码
本节讨论如何对指令系统中的所有指令进行二进制编码,即操作码的设计方法。设计的目标是用尽可能短的位数表示所有指令,同时保证译码的高效性。
1. 规整型定长编码
- 定义:操作码字段的位数和位置固定。
- 关系: 如果指令系统有
条指令,操作码字段位数为 ,则必须满足 或 。 - 优点: 译码简单,硬件实现容易,速度快。这是RISC架构的首选。
- 缺点: 如果指令数量远小于
,会造成编码空间的浪费。例如,若有17条指令,则需要5位操作码( ),会浪费15个编码状态。
2. 非规整型变长编码 (扩展操作码法)
这是指令设计中的核心和难点。其思想是让不同地址数量的指令共享操作码编码空间,以在有限的指令长度内支持尽可能多的指令。
基本思想:
- 让地址码数量多的指令(如三地址指令)使用较短的操作码。
- 让地址码数量少的指令(如一地址、零地址指令)使用较长的操作码。
- 用一个特殊的编码(如
1111)作为扩展标志,表示当前操作码不是最终操作码,需要和后续的地址码字段一起组成更长的操作码。
设计原则: 任何一个短操作码都不能是任何一个长操作码的前缀,否则译码时会产生歧义。这与数据结构中的**前缀码(哈夫曼编码)**思想一致。
示例: 假设指令长度为16位,每个地址码占4位。我们来设计一个包含三地址、二地址、一地址和零地址指令的系统。
三地址指令:
- 格式:
OP(4位) | A1(4位) | A2(4位) | A3(4位) - 假设我们用
0000到1110(15个状态) 来定义15条三地址指令。 - 留下
1111作为扩展标志,用于二地址指令。
- 格式:
二地址指令:
- 格式:
1111 | OP'(4位) | A1(4位) | A2(4位) - 当译码器看到
1111时,它会知道这是一个扩展操作码,需要继续读取后面的4位OP'字段。 - 这里的操作码实际是8位 (
1111 OP')。同样,我们可以定义15条二地址指令 (1111 0000到1111 1110)。 - 留下
1111 1111作为下一级的扩展标志。
- 格式:
一地址指令:
- 格式:
1111 1111 | OP''(4位) | A1(4位) - 操作码为12位。可以定义15条一地址指令。
- 留下
1111 1111 1111作为扩展标志。
- 格式:
零地址指令:
- 格式:
1111 1111 1111 | OP'''(4位) - 操作码为16位。可以定义16条零地址指令,因为无需再留出扩展位。
- 格式:
总结: 通过这种方式,我们在固定的16位指令长度内,总共定义了
条指令,极大地提高了指令编码空间的利用率。
核心考点
- 扩展操作码法的设计和计算。习题中经常出现类似问题:给定指令总长和地址码长度,要求设计一套指令系统,使其能容纳指定数量的不同地址指令。
- 解题思路: 从地址码最多的指令开始分配操作码(即从操作码最短的指令开始),每次都留出一个或多个编码作为下一级(地址码更少的指令)的扩展入口。
- 难点: 理解编码空间的逐级"挤占"。从短操作码到长操作码,可用的编码数量越来越少,但操作码的长度越来越长。