指令格式和寻址方式

指令格式是计算机组成原理中的重点考察内容,需熟练掌握,熟练张常常在大题中与 CPU 的知识交叉考察。

指令的格式

指令中主要包含两个部分:操作码(opcode)以及 地址(address)。

这里地址是一个通用含义,指的是操作的对象,可以是一个内存地址,也可以是 CPU 中的一个寄存器。

指令类型

根据操作码分类

指令根据其操作码(opcode)的不同可以分为以下类别:

  1. 数据传输指令
    • MOV:将数据从一个位置传输到另一个位置,可以是寄存器到寄存器、内存到寄存器、寄存器到内存等。
    • PUSH:将数据(通常是寄存器中的值)推入堆栈。
    • POP:从堆栈中弹出数据并存储到寄存器中。
  2. 算术和逻辑运算指令
    • ADDSUBMULDIV:执行算术运算,如加法、减法、乘法和除法。
    • ANDORXORNOT:执行逻辑运算,如按位与、按位或、按位异或和按位取反。
    • INCDEC:递增和递减操作数的值。
    • CMP:用于比较两个值,并根据结果设置标志寄存器的状态。
  3. 控制转移指令
    • JMP:用于无条件跳转到指定的目标地址。
    • Jxx:条件跳转指令,根据特定的条件(如零标志、进位标志等)来决定是否跳转。
    • CALL:调用子程序或函数。
    • RET:从子程序返回。
  4. 输入/输出指令
    • IN:从外部设备或端口读取数据。
    • OUT:向外部设备或端口发送数据。
  5. 字符串操作指令(String Instructions):
    • MOVSLODSSTOSCMPS:用于在内存中执行字符串操作,如移动、加载、存储、比较。
  6. 陷阱指令(Trap Instructions):
    • INT:用于引发中断,通常用于与操作系统进行通信。
  7. 协处理器指令(Coprocessor Instructions):
    • CLISTI:用于清除和设置 CPU 的中断标志,通常只能在内核模式下执行。

根据地址个数分类

根据指令中的地址个数,可以将指令划分为以下类型。

OP
OP
A1
OP
A1
A2
OP
A3
A1
A2
零地址
一地址
二地址
三地址
指令格式指令格式含义
零地址指令op$op$
一地址指令op, A1$op(A_1) \rightarrow A_1$
二地址指令op, A1, A2$(A_1)op(A_2) \rightarrow A_1$
三地址指令op, A3, A1, A2$(A_1)op(A_2) \rightarrow A_3$

“N 地址指令” 中的 “地址” 一词可以是立即数或一个内存地址,也可以是寄存器。

定长和变长指令

变长指令集
定长指令集

定长指令集中所有指令长度相同,变长指令集中会包含不同长度的指令。

使用定长指令集的典型 cpu 架构是 arm(RISC),优点是解码简单、高效,但可能导致指令浪费空间。

使用变长指令集的典型 cpu 架构是 x86(CISC),优点是可以更加紧凑地编码复杂操作,但解码更加复杂。

寻址方式

计算机中的寻址方式(Addressing Modes)是指在指令中如何指定操作数的位置或地址。

立即数寻址

操作数作为指令的一部分而直接写在指令中,这种操作数称为立即数,这种寻址方式也就称为立即数寻址方式。

• • • • • 
OP
76H
45H
• • • • • 
MOV AX, 4576H
76H
45H
立即数寻址
AX
指令存储在 text 段在内存中

立即数寻址方式通常用于对通用寄存器或内存单元赋初值,上图是指令 MOV AX, 4567H 存储形式和执行示意图,直接将 指令中的数据 4567H 存储到寄存器中。

直接寻址

MOV R1, 1000
3456H
R1
56H
高地址
低地址
1000H
0
FFFFH
34H
从相应内存地址中读取数据
存储到 R1 中
内存
10
OP
00
译码执行

间接寻址

MOV R1, [R2]
7890H
1234H
R1
R2
90H
高地址
低地址
1234H
0
FFFFH
78H
从相应内存地址中读取数据
存储到 R1 中
内存
R1
OP
R2
译码执行

基址寻址

8086 的存储器被分成若干段,其中会专门设置一个基址存储器用于存储段的起始地址,段内的位移量由指令给出。操作数的地址由基址寄存器的内容和指令的地址码 A 相加得到,这种情况下地址码 A 常被成为位移量。

OP
Rb
A
基址寄存器
(Rb) + A = E
操作数
E:
指令
基址
(寻址标志)
逻辑地址
加法器
有效地址
地址
主存

变址寻址

指令地址码给出地址 A 和指定的变址寄存器 R,将 A 和 R 的内容相加就是操作数的地址。常利用变址操作与循环执行程序的方法对数组进行运算。

OP
......
基准地址 A
变址值
操作数
E:
指令
主存
ALU
有效地址 EA
变址寄存器 Rx

注意

基址和变址寻址的区别?

  • 基址寻址主要用于为程序或数据分配存储空间,故基址寄存器的内容通常由操作系统或管理程序确定,在程序运行过程中,值是不可变的,而指令字中的地址码是可变的。
  • 变址寻址中,变址寄存器的内容是用户自己设定的,在程序运行过程中是可变的,而指令字中的地址码是不可变的。编制寻址主要用于处理数组等问题,并且特别适合编制循环程序。

相对寻址

OP
......
A
PC
指令
E:
指令
主存
ALU
有效地址 EA
.text

堆栈寻址

根据 函数调用时的内存结构,函数栈可以存储函数中的变量。堆栈寻址就是在函数的栈帧中访问通过 PUSH 指令存储的数据。

caller BP
BP
SP
caller BP
BP
SP
PUSH A
A
caller BP
BP
SP
PUSH B
A
B
caller BP
BP
SP
POP
A
High Address
Low Address

寻址方式对比

寻址方式描述示例
立即寻址操作数直接包含在指令中。MOV R1, #5 (将 5 加载到 R1 寄存器)
寄存器寻址操作数在寄存器中。ADD R1, R2 (R2 加到 R1 中)
直接寻址操作数的内存地址直接包含在指令中。MOV R1, [1000] (从内存地址 1000 取数据)
间接寻址操作数的地址存储在寄存器中,指令通过寄存器访问内存中的数据。MOV R1, [R2] (R2 寄存器中是内存地址)
基址寻址使用基址寄存器和偏移量计算操作数的实际地址。MOV R1, [R2 + 4] (基址 R2 加偏移 4)
变址寻址通过基址寄存器和索引寄存器的和来确定操作数地址,常用于数组操作。MOV R1, [R2 + R3] (R2 与 R3 相加)
相对寻址操作数地址通过程序计数器(PC)当前值加上指令中的偏移量计算,常用于跳转指令。JMP LABEL (跳转到相对地址)
堆栈寻址通过堆栈顶指针(SP)来访问操作数,常用于函数调用和返回。PUSH R1 (将 R1 压入堆栈)