寻址方式
定义:寻找操作数存放地址的方式
在进行一个操作之前,需要知道源操作数和目的操作数分别存放在什么位置,用什么方式去找到这个位置
操作数的位置
- CPU寄存器
- 主存(内存)
- IO设备
寄存器寻址
示例:INC AX
操作数存放在CPU寄存器内,寄存器的名字就是它的地址,直接操作对应的寄存器
- 操作数的类型:由所用寄存器的位数决定,如AX是16位字类型
寄存器间接寻址
示例:MOV AX, [SI]
操作数存放在内存中,需要通过寄存器的值(该值就是操作数的偏移地址EA)间接找到操作数
- 操作数的类型:不明确,对于双操作数的指令,如例子所示,由于AX类型已知,则另一个操作数默认使用同样类型,如果两个操作数类型都不明确,则出错
- 寄存器的选择:
- 可以是32位的8个通用寄存器
- 也可以是4个16位通用寄存器(BX,DI,SI,BP)
- 但是不能是8位寄存器,需要注意的是被允许的16位寄存器只有这四个
- 操作数的段:如果寄存器选用ESP、SP、BP,则默认在堆栈段SS,否则一律默认在数据段DS
变址寻址
示例:MOV AL, 5[EBX]
操作数存放在内存中,需要根据寄存器的值、比例因子、位移量,计算出操作数的偏移地址EA,然后去所在段找到操作数,注意选用ESP时,比例因子F只能为1
- 书写形式:常见以下三种,其中R是寄存器,F是比例因子,V是位移量
1.[R * F + V]
2.[R * F] + V
3.V [R * F] - 寄存器选择,操作数的段,同间接寻址的规定一样
基址加变址寻址
示例:MOV AX, 8[BX][SI]
操作数在内存中,先计算EA,再在段中找到操作数
-
书写格式:常见的以下三种,BR是基址寄存器,IR是变址寄存器,F是比例因子,V是位移量
1.[BR + IR * F + V]
2.V [BR] [IR * F]
3.V [BR + IR * F -
寄存器选择:
- 16位寄存器,BR只能选择BP、BX,IR只能选择DI、SI,F只能为1
- 32位寄存器,BR可选择任意通用寄存器,IR可选择除ESP外的任意通用寄存器
-
操作数的段:
- 选择EBX/BX时,段寄存器默认DS
- 选择EBP/BP时,段寄存器默认SS
立即寻址
示例:ADD EAX, -1
操作数是一个有符号数,且只能是源操作数(IO寄存器除外)
直接寻址
示例:MOV DS:[20H], CL
操作数在内存中,指明操作数的段(部分情况下可省略),后面紧跟偏移地址EA,EA是一个无符号数
需要注意,操作数类型一定要明确
寻址相关的问题
显示/隐含操作数
一些指令显示的指明操作数,有些则相反
各寻址方式的关系
根据操作数存放的位置,寻址方式分为三类:
- 寄存器方式:寄存器寻址
- 存储器方式:寄存器间接寻址,变址寻址,基址加变址寻址,直接寻址
- 立即方式:立即寻址
源操作数和目的操作数的存放位置
- 对于双操作数的指令,源操作数和目的操作数不能同时使用存储器方式,也就是说不能都来自于内存
- 立即寻址的操作数,只能是源操作数
寄存器方式寻址的操作数,其数据类型是不明确的,必要情况下,需要额外声明
- BYTE PTR
- WORD PTR
- DWORD PTR
段选择说明
- 如果不希望使用默认段寄存器,也可以显式地指定,也就是在对应的寻址方式表达式之前,加上段超越前缀(跨段前缀)
- 段超越前缀可以使用任意段寄存器
- 不受跨段前缀影响的情况
- 取指令时,只能是CS段
- 压栈和出栈,只能是SS段
- 串操作中,目的串只能是ES段