指令系统
4.1 指令系统
4.1.1 指令集体系结构
指令集体系结构(Instruction Set Architecture,ISA)是计算机系统中软件与硬件之间的接口。它定义了程序员(尤其是汇编语言程序员)所能够看到的计算机的抽象模型,包括:
- 指令格式:指令的二进制编码方式。
- 操作数类型:支持的数据类型(整数、浮点数、地址等)及其长度。
- 寻址方式:如何计算操作数的有效地址。
- 寄存器组织:通用寄存器的数量、位数和用途。
- 存储空间:主存的编址方式、大小和访问方式。
- 异常与中断:处理机制。
- 输入输出:I/O控制方式。
ISA 是计算机体系结构中最核心的部分,它决定了软件的兼容性。同一系列计算机(如 x86 系列)通常保持 ISA 的向后兼容,使得为早期处理器编写的程序能在新型处理器上运行。
4.1.2 指令的基本格式
一条指令通常由操作码和地址码两部分组成:
| 操作码 | 地址码(可能多个) |
|---|
- 操作码(Opcode):指明指令要执行的操作,如加法、减法、转移等。操作码的位数决定了指令系统中最多能支持的指令条数。
- 地址码(Address):指明操作数的地址或操作数本身。根据地址码的个数,指令可分为零地址、一地址、二地址、三地址甚至四地址指令。
指令字长是指一条指令所占的二进制位数。指令字长可以等于机器字长(单字长指令),也可以是其整数倍(双字长指令等)。定长指令字结构实现简单,但可能浪费存储空间;变长指令字结构可以节省空间,但控制复杂。
常见指令格式
-
零地址指令
只给出操作码,没有显式的地址码。常用于不需要操作数的指令(如停机、空操作)或堆栈计算机中的运算指令(操作数隐含在堆栈顶部)。 -
一地址指令
格式:OP A1
含义有两种:- 单操作数指令:
OP (A1) → A1(如加1、取反) - 双操作数指令:
(ACC) OP (A1) → ACC(另一个操作数隐含在累加器 ACC 中)
- 单操作数指令:
-
二地址指令
格式:OP A1, A2
含义:(A1) OP (A2) → A1(或 A2,视约定而定)
通常第一个地址既是源操作数又是目的操作数,第二个地址是另一个源操作数。 -
三地址指令
格式:OP A1, A2, A3
含义:(A1) OP (A2) → A3
三个地址分别存放两个源操作数和结果,不破坏源操作数。 -
四地址指令
格式:OP A1, A2, A3, A4
含义:(A1) OP (A2) → A3,A4给出下一条指令的地址。
实际上,现代计算机中下一条指令地址通常由程序计数器(PC)提供,因此很少使用四地址指令。
4.1.3 定长操作码指令格式
定长操作码是指所有指令的操作码字段长度相同,并且位于指令字的固定位置。例如,若操作码占 8 位,则最多可表示 256 条指令。这种格式的优点是指令译码简单、速度快,适合指令数量较少的情况。RISC 处理器通常采用定长操作码。
4.1.4 扩展操作码指令格式
扩展操作码技术是为了在指令字长有限的情况下增加指令数量而设计的。其基本思想是:将操作码的长度随地址码数量的减少而增加。即,当指令中地址码个数较少时,可以将空闲的地址码位用于扩展操作码。
例如,一个 16 位指令字,操作码固定为 4 位(可表示 16 种),但需要更多指令时,可以这样设计:
- 用 4 位操作码的前 15 种作为三地址指令(操作码 0000~1110),剩余一种(1111)作为扩展标志。
- 当操作码为 1111 时,表示接下来的 4 位(原本是第一个地址码)也作为操作码,于是得到 8 位操作码(可表示 256 种),但此时只有两个地址码字段。
- 依此类推,可继续扩展。
扩展操作码的设计要点:
- 不允许短操作码是长操作码的前缀(即短码不能与长码的前面部分相同)。
- 各指令的操作码必须唯一。
- 通常将使用频率高的指令分配较短的操作码,使用频率低的分配较长的操作码,以缩短平均指令长度。
4.1.5 指令的操作类型
指令系统通常包含以下几类操作:
-
数据传送
包括寄存器与寄存器之间、寄存器与主存之间的数据传送。典型指令:MOV、LOAD、STORE、PUSH、POP。 -
算术与逻辑运算
算术运算:加(ADD)、减(SUB)、乘(MUL)、除(DIV)、加1(INC)、减1(DEC)。
逻辑运算:与(AND)、或(OR)、非(NOT)、异或(XOR)、移位(SHL、SHR)。 -
移位操作
算术移位(考虑符号位)、逻辑移位(补0)、循环移位(带进位或不带进位)。 -
转移操作
无条件转移(JMP)、条件转移(JZ、JC、JG 等)、子程序调用(CALL)、返回(RET)、陷阱(TRAP)。 -
输入输出操作
用于 CPU 与外部设备交换数据,通常有专门指令(如 IN、OUT)或通过内存映射 I/O 实现。
4.2 指令的寻址方式
4.2.1 指令寻址和数据寻址
寻址方式分为两类:
- 指令寻址:确定下一条将要执行的指令的地址。
- 数据寻址:确定本条指令所操作的数据的地址。
1. 指令寻址
- 顺序寻址:通过程序计数器 PC 自动加 1(指令长度)形成下一条指令地址。
- 跳跃寻址:通过转移指令改变 PC 的值,使程序跳转到指定地址。跳跃后的地址可以是绝对地址,也可以是相对地址。
2. 数据寻址
数据寻址的方式很多,通常在指令中设置一个寻址特征字段来指明采用哪种寻址方式。指令格式变为:
| 操作码 | 寻址特征 | 形式地址 A |
|---|
形式地址(A)不是操作数的真实地址,需要根据寻址方式计算出有效地址(EA)。
4.2.2 常见的数据寻址方式
-
隐含寻址
操作数地址隐含在指令中(如累加器 ACC),指令中不显式给出地址。
优点:缩短指令字长。
缺点:需要额外硬件。 -
立即寻址
形式地址 A 就是操作数本身。
格式:OP #A
优点:不需要访存,速度快。
缺点:A 的位数限制了操作数的范围。 -
直接寻址
有效地址 EA = A,即形式地址就是操作数的实际地址。
优点:简单,只需一次访存。
缺点:A 的位数限制了寻址范围,且操作数地址不易修改。 -
间接寻址
有效地址 EA = (A),即形式地址指向的存储单元中存放的是操作数的有效地址。
优点:可扩大寻址范围(因为存储单元可以存放更大位数的地址)。
缺点:需要多次访存(一次间接需2次访存),速度慢。 -
寄存器寻址
有效地址 EA = Ri,即 Ri 中存放操作数本身。
优点:无需访存,速度快;寄存器编号短,指令字短。
缺点:寄存器数量有限,价格高。 -
寄存器间接寻址
有效地址 EA = (Ri),即 Ri 中存放操作数的地址。
优点:既扩大了寻址范围(寄存器位数通常等于地址线数),又只需一次访存。
缺点:仍需访存。 -
相对寻址
有效地址 EA = (PC) + A,其中 A 是相对于当前 PC 的偏移量(补码表示)。
优点:便于程序浮动(程序在内存中移动时无需修改指令中的地址)。
广泛用于转移指令。 -
基址寻址
有效地址 EA = (BR) + A,其中 BR 是基址寄存器(可由操作系统指定)。
优点:可扩大寻址范围,便于多道程序分配存储空间。
基址寄存器的内容在程序执行过程中通常不变,而 A 可变。 -
变址寻址
有效地址 EA = (IX) + A,其中 IX 是变址寄存器(用户可修改)。
优点:便于处理数组,通过修改 IX 的值可顺序访问数组元素。
变址寄存器的内容可变,A 作为基地址。注意:基址寻址与变址寻址的区别在于——基址寻址面向系统(基址由OS设定),变址寻址面向用户(变址值由程序改变)。
-
堆栈寻址
操作数隐含在堆栈中,由堆栈指针 SP 自动管理。
适用于堆栈计算机,指令多为零地址。
4.2.3 偏移寻址
相对寻址、基址寻址、变址寻址统称为偏移寻址,因为它们都是将一个寄存器的内容与一个形式地址相加得到有效地址。区别在于所涉及的寄存器和用途不同。