【x86汇编】第二章:寻址方式

寻址方式

定义:寻找操作数存放地址的方式
在进行一个操作之前,需要知道源操作数和目的操作数分别存放在什么位置,用什么方式去找到这个位置

操作数的位置

  • 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段

猜你喜欢

转载自blog.csdn.net/whitefish520/article/details/105474595