汇编之寻址方式


前言

寻址方式真的是汇编里最基础最重要的内容,一开始觉得听懂了,用着用着又糊涂了,所以总结一下。
所谓寻址,就是寻找操作数所在地址的方法。
源操作数:运算数据的来源
目标操作数:运算结果的去向或另一个运算数据
先目的后源

操作数可能的来源或运算结果可能的去处只有三个

  • 由指令直接给出
  • 寄存器
  • 内存单元

由此寻找操作数所在地址的方法可以有三种类型:

  • 指令直接给出的方式
  • 存放于寄存器中的寻址方式
  • 存放于存储器中的寻址方式

与数据有关的寻址方式

立即寻址

由指令直接给出运算的数据(操作数是立即数)。为常数形式或字符形式。
立即数只表示运算的数据,无地址含义。
立即寻址仅适合于源操作数(后面的那个操作数)。即源操作数是参加操作的数据本身。
立即数可以是16位的,也可以是8位的,可以是有符号数,也可以是无符号数,是比较*的。
而且立即数没有确定的长度,1200H可以是1200H,也可以是00001200H

注意:操作数涉及立即数的指令,指令长度为:寄存器类型+1个字节
8位寄存器,寄存器类型=1,如:mov al,8;指令长度为2个字节
16位寄存器,寄存器类型=2,如:mov ax,8;指令长度为3个字节
因此涉及立即数的指令通常比较长,所以它在程序中的应用范围有限,一般只用于给某个寄存器或内存单元赋初值

汇编之寻址方式

MOV AX,1200H
把立即数1200H送入AX
立即数是由指令直接给出的,因此在编译的时候它会和指令码一起被放到内存的代码段。

注意高地址存放高字节,低地址存放低字节。

寄存器寻址

参与运算的数据被存放在CPU的某个通用寄存器中

例:MOV AX,BX

此种寻址方式中的寄存器主要是通用寄存器,不会是控制寄存器,偶尔是段寄存器。

寄存器间接寻址

寄存器相对寻址

存储器寻址

存储器寻址
指令操作的对象在内存中,表现形式为**[ ]**
指令中给出运算对象在内存某个逻辑段中的偏移地址:[偏移地址]
逻辑段的段基地址通过默认或重设方式给出

存储器操作数的字长本身不确定,其字长取决于指令中另一个寄存器操作数,或通过其他方式指定字长

直接寻址

指令中直接给出操作数的偏移地址
方括号里的就是操作数的偏移地址

例:MOV AX,[1200H]

因为AX是16位,会取出两个字节的数据。

直接寻址方式下,操作数默认在数据段,但允许段重设,即由指令给出所在逻辑段

例:MOV AX,ES:[1200H]

ES:就是段重设符

寄存器间接寻址

操作数存放在内存中,数据在内存中的偏移地址为方括号中通用寄存器的内容。
仅有四个通用寄存器可用于存放数据的偏移地址,它们不仅是用用寄存器还是间址寄存器——BX,BP,SI,DI,它们用来存放数据在内存中的偏移地址
或者说,能放在[ ]里的只有这四个寄存器!

间接寻址的一般格式:
[ 间址寄存器 ]

操作数的段地址(数据处于哪个段)取决于选择哪个间址寄存器。
BX,SI,DI——默认在数据段
BP——默认在堆栈段

扩展一下:
BP和SP都指向堆栈区,SP固定指向栈顶,而BP可以指向堆栈区的任何一个位置。
注意这里说的是“默认”,我们还是可以通过段重设的方法,来让它们处于其他的段。

寄存器相对寻址

间接寻址在对数组元素求和等程序时很好用。间接寻址用间址寄存器来表示数据的存放地址,可以不断DX+1,DX+2实现一组数据的操作,这样比直接寻址方便多了。如果用间接寻址求100个数相加,那就至少需要写100条指令。

MOV BX,1200H
MOV AX,[BX]

看见方括号[ ]就知道要找的数在内存里,在内存的什么地方?这就要看[ ]里面。
在这里,BX里的值就是数据的偏移地址。1200H就是操作数的偏移地址。

基址变址寻址

相对基址变址寻址

与转移地址有关的寻址方式

段内直接转移

段间直接转移

段间直接转移

段间间接转移