跳到主要内容

寻址方式概述

寻址方式是指寻找指令或操作数有效地址的方式,即确定本条指令的数据地址及下一条待执行指令的地址的方法。寻址方式分为指令寻址和数据寻址两大类。

指令寻址

指令寻址方式有两种:一种是顺序寻址方式,另一种是跳跃寻址方式。

指令寻址

顺序寻址

由于指令地址在内存中按顺序存放,当执行一段程序时,通常是按一条指令接一条指令的顺序执行。这种程序顺序执行的过程,我们称为指令的 顺序寻址方式。为此,必须使用程序计数器 (PC Register) 来计数指令的顺序号,该顺序号就是指令在内存中的地址。

跳跃寻址

当程序转移执行的顺序时,指令的寻址就采取 跳跃寻址方式
。所谓跳跃,是指下条指令的地址码不是由程序计数器给出的,而是由本条指令给出。注意,程序跳跃后,按新的指令地址开始顺序执行。因此,指令计数器的内容也必须相应改变,以便及时跟踪新的指令地址。

采用指令跳跃寻址方式,可以实现程序转移或构成循环程序,从而能缩短程序长度,或将某些程序作为公共程序引用。指令系统中的各种条件转移或无条件转移指令,就是为了实现指令的跳跃寻址而设置的。

数据寻址

在指令执行过程中,操作数的来源一般有三个:

  1. 由指令中的地址码部分直接给出操作数
  2. 将操作数存放在 CPU 内的通用数据寄存器中,这样速度快,但是寄存器存储空间有限。
  3. 更一般化的方式是将操作数存放在内存的数据区中。

而对于内存寻址,既可以在指令中直接给出操作数的实际访存地址,称为 有效地址(EA\text{EA})
,也可以在指令的地址字段给出所谓的 形式地址(A\text{A}),在指令执行时,将形式地址依据某种方式变换为有效地址再取操作数。

形成操作数的有效地址的方法,称为 操作数的寻址方式

而指令有分为零地址指令、一地址指令、二地址指令、三地址指令等。以一地址指令和二地址指令为例,其指令结构如下:

一地址指令 操作码 (OP)[ 寻址特征] 形式地址 (A)二地址指令 操作码 (OP)[ 寻址特征] 形式地址 (A1)[ 寻址特征] 形式地址 (A2)\begin{array}{l} \text{一地址指令} \quad \boxed{\quad\text{ 操作码 (OP)}\quad}\:\boxed{\quad\text{[ 寻址特征]}\quad}\:\boxed{\quad\text{ 形式地址 (A)}\quad} \\ \\ \text{二地址指令} \quad \boxed{\quad\text{ 操作码 (OP)}\quad}\:\boxed{\quad\text{[ 寻址特征]}\quad}\:\boxed{\quad\text{ 形式地址 (A$_1$)}\quad}\:\boxed{\quad\text{[ 寻址特征]}\quad}\:\boxed{\quad\text{ 形式地址 (A$_2$)}\quad} \end{array}

立即寻址(Immediate Addressing)

指令的地址字段指出的不是操作数的地址,而是操作数本身,这种寻址方式称为立即寻址。指令中的操作数称为立即数。立即寻址方式的特点是指令中包含的操作数立即可用,节省了访问内存的时间。

示例代码
MOV R1, #3 ; 将数字 3 移动到寄存器 R1 中
armasm

立即寻址的优点是指令在执行阶段不访问主存, 指令执行时间最短; 缺点范围受限。

直接寻址(Direct Addressing)

直接寻址是一种基本的寻址方法,其特点是:在指令格式的地址字段中直接指出操作数所在的内存地址。由于操作数的地址直接给出而不需要经过某种变换,所以称这种寻址方式为 直接寻址方式。即 EA=A\text{EA}=\text{A}

提示

注意 EA 是有效地址,并不是有效地址中的值。而是相当于一个指针,指向了这个有效地址。操作数的读取将从 EA 指向的地址中读取。

示例代码
MOV A, 1000h  ; 将内存地址 1000h 处的值加载到寄存器 A
armasm

间接寻址(Indirect Addressing)

指令的地址字段给出的形式地址不是操作数的真正地址,而是操作数有效地址所在的存储单元的地址,也就是操作数地址的地址。即EA=(A)\text{EA}=(\text{A})

提示

这里的括号 (A) 的含义是取出给定的形式地址 A\text{A} 中的值。上面的式子的含义是,有效地址 EA\text{EA} 等于 形式地址
A\text{A} 中的 存储的地址。假如 A\text{A} 中的存储的地址为 0x00001011。这时候 EA=0x00001011\text{EA}=\text{0x00001011}

间接寻址

示例代码
MOV A, (R0)  ; 将寄存器 R0 指向的地址处的值加载到寄存器 A
armasm

寄存器寻址(Register Addressing)

当操作数不在内存中,而是放在 CPU 的通用寄存器中时,可采用寄存器寻址方式。显然,此时指令中给出的操作数地址不是内存的地址单元号,而是通用寄存器的编号。即
EA=Ri\text{EA} = \text{R}_i,其中操作数在由 Ri\text{R}_i 所指的寄存器内。

寄存器寻址

MOV A, B  ; 将寄存器 B 的值加载到寄存器 A
armasm

寄存器间接寻址(Register Indirect Addressing)

寄存器间接寻址与寄存器寻址的区别在于:指令格式中的寄存器内容不是操作数,而是操作数的地址,该地址指明的操作数在内存中。即
EA=(Ri)\text{EA} = (\text{R}_i)

寄存器间接寻址

偏移寻址 (Displacement Addressing)

一种强有力的寻址方式是直接寻址和寄存器间接寻址方式的结合,它有几种形式,我们称它为偏移寻址。它要求指令中有两个地址字段,至少其中一个是显式的。

相对寻址、基址寻址、变址寻址都属于偏移寻址。

但是他们之间还是有区别的,在于 偏移的“起点”不一样

  • 基址寻址:以程序的起始存放地址作为“起点”
  • 变址寻址:程序员自己决定从哪里作为“起点”
  • 相对寻址:以程序计数器 PC 所指地址作为“起点”
提示

数组 访问一般采用的是 偏移寻址(一般使用的是变址寻址),因为访问数组元素时通过计算基地址和偏移量来确定元素的位置。

基址寻址(Base Addressing)

基址寻址是指将 CPU 中基址寄存器 (BR) 的内容加上指令格式中的形式地址 A 而形成操作数的有效地址, 即 EA = (BR) +
A。其中基址寄存器既可采用专用寄存器, 又可釆用通用寄存器。

提示

其中基址寄存器 (BR) 中为基址地址,形式地址 A 中为偏移量。这与下面的变址寻址略有不同。

基址寻址

MOV A, (BR+5)  ; 将基址寄存器 BX 加上偏移量 5 处的值加载到寄存器 A
armasm

变址寻址(Indexed Addressing)

变址寻址是指有效地址 EA 等于指令字中的形式地址 A 与变址寄存器 IX 的内容之和, 即 EA = (IX) + A, 其中 IX
为变址寄存器(专用) , 也可用通用寄存器作为变址寄存器。

变址寻址

变址寄存器是面向用户的, 在程序执行过程中, 变址寄存器(IX)的内容可由用户改变(作为偏移量) , 形式地址 A 不变(作为基地址)。

MOV A, (1000h+IX)  ; 将基地址 1000h 加上变址寄存器 IX 的值处的内容加载到寄存器 A
armasm

在数组处理过程中,可设定 A 为数组的首地址, 不断改变变址寄存器 IX 的内容,便可很容易形成数组中任一数据的地址,特别适合编制循环程序。偏移量(变址寄存器
IX)的位数足以表示整个存储空间。

基址寻址和变址寻址的区别

  • 基址寻址面向系统, 主要用于为多道程序或数据分配存储空间, 因此基址寄存器的内容通常由操作系统或管理程序确定,
    在程序的执行过程中其值不可变, 而指令字中的 A 是可变的;
  • 变址寻址立足于用户, 主要用于处理数组问题, 在变址寻址中, 变址寄存器的内容由用户设定, 在程序执行过程中其值可变, 而指令字中的
    A 是不可变的

相对寻址(Relative Addressing)

相对寻址是把 PC 的内容加上指令格式中的形式地址 A 而形成操作数的有效地址, 即 EA = (PC)+A, 其中 A 是 相对于 PC 所指地址 的位移量, 可正可负, 补码表示。

相对寻址

JMP LABEL  ; 跳转到 LABEL 标记处的指令
armasm

相对寻址的优点是操作数的地址不是固定的, 它随 PC 值的变化而变化, 且与指令地址之间总是相差一个固定值, 因此便于程序浮动。
相对寻址广泛应用于转移指令。

总结

寻址方式、有效地址及访存次数

寻址方式有效地址访存次数
立即寻址A 即是操作数00
直接寻址EA = A11
一次间接寻址EA = (A)22
寄存器寻址EA=Ri\text{EA}=\text{R}_i00
寄存器一次间接寻址EA=(Ri\text{EA}=(\text{R}_i)11
相对寻址EA = (PC) + A00
基址寻址EA = (BR) + A00
变址寻址EA = (IX) + A00

Warning

这里的访存指访问主内存,寄存器的访问不算访存次数