8086指令的寻址方式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq2071114140/article/details/102573909

8086指令的寻址方式

1.操作数的种类

根据操作数所在的位置划分

根据操作数所在的位置,划分为4种操作数

 

  • 立即数操作数:操作数直接跟在指令的操作码后面
  • 寄存器操作数:操作数存储在寄存器中
  • 存储器操作数:操作数存储在内存单元中
  • I/O端口操作数:操作数存储在I/O端口中

 

根据操作数的表示的内容划分

可以分为两大类:数据操作数、地址操作数

其中,数据操作数,是指与数据有关的操作数,用在数据操作的指令中,数据操作数包含了立即数操作数,寄存器操作数,存储器操作数,I/O端口操作数

地址操作数,是指与程序转移地址有关的操作数,地址操作数表示的是地址而不是数据,一个供程序转移的目标地址,包含了立即数操作数,寄存器操作数,存储器操作数

数据操作数和地址操作数的比较

  • 操作数长度方面:数据操作数可以是8位或16位;由于地址操作数表示一个地址,则地址操作数是16位的
  • 操作数在指令中的数目:数据操作指令中,一般有两个数据操作数。(也有一个的情况,但是,本质上还是两个,另一个操作数可能在某一个寄存器中作为隐含的条件);在程序转移指令中,仅有一个地址操作数。

源操作数和目的操作数、左值和右值

先说一下左值和右值,左值表示一个存储单元的地址,右值表示一个立即数(常数)或存储单元的值。对于一条赋值语句来说,有两点要素:给谁赋值?赋的值是什么?

给谁赋值?也就是给哪个位置赋值,是一个左值,表示一个位置
赋的值是什么?也就是一个右值

对应到数据操作指令中,有两个操作数,源操作数和目的操作数,源操作数是一个右值,目标操作数是一个左值。举个例子,MOV AX, BX;这里BX是源操作数,也就是一个右值,所以,BX的值为BX中存储的值;而AX是一个目的操作数,是一个左值,表示一个位置。

寻址,其实就是找一个位置,而对于源操作数来说,关注的是一个单元的值;对于目的操作数来说,关注的是一个单元的位置

2.数据寻址方式

数据寻址方式,就是找到数据操作指令中,目的操作数所表示的位置(左值)和源操作数的所表示的位置的值(右值)。由于数据操作数有可以存在4个地方:指令中直接给出操作数、寄存器中、存储器中、I/O端口中,所以,对应有四大类的寻址方式

  • 指令中直接给出操作数 ---> 立即数寻址
  • 操作数在寄存器中 ---> 寄存器寻址
  • 操作数在内存中 ---> 存储器寻址
  • 操作数在I/O端口中 ---> I/O端口寻址

对于每一类寻址方式,还有更细的划分,详细内容请看下图

立即数寻址

举个例子: MOV AX, 1234H

对于这条指令,源操作数数据操作数1234H直接跟在操作码后面,执行的结果就是将数据1234H放入寄存器AX中。

这里的源操作数1234H的寻址方式,是立即寻址方式

寄存器寻址

举个例子: MOV AX, BX

对于这条指令,源操作数和目的操作数都是用寄存器寻址的方式。对于源操作数BX来说,是一个右值,在BX寄存器中取得操作数;对于目的操作数AX来说,是一个左值,表示一个位置。

可使用的寄存器:AX,BX,CX,DX,SI,DI,SP,BP,AH,AL,BH,BL,CH,CL,DH,DL

存储器寻址

  • 直接寻址:内存单元的有效地址直接跟在操作码后面
    举个例子:MOV AX, [1234H];
    对于源操作数来说,使用的是存储器寻址方式的一种,直接寻址,存储器的地址直接跟在操作码的后面,上面指令的执行结果,将数据段中,有效地址(相对短地址的偏移)为1234H的内存单元的值,赋给AX寄存器 直接寻址允许段超越,也就是说,可以访问指定的段。例如:MOV AX,ES:[1234H];

  • 寄存器间接寻址:内存单元的有效地址存放在寄存器中
    举个例子:MOV AX, [BX];
    间接寻址可以使用的寄存器:SI,DI,BX,BP。使用BP时,对应的段是堆栈段,前面的三个寄存器对应的是数据段 同样也允许段超越,例如:MOV AX,ES:[DI]

  • 寄存器相对寻址:内存单元的有效地址分为两部分,一部分在寄存器中存储,另一部分是一个偏移量,两者相加的结果为存储单元的有效地址。
    举个例子:MOV AX, [BX + 10H];等价写法 MOV AX,[BX]+10H;MOV AX, 10H[BX];
    源操作数对应的内存单元的物理地址:(DX) * 10H + (BX) + 10H
    寄存器相对寻址可以使用的寄存器:SI,DI,BX,BP。偏移量可以是8位或16位的立即数(也可以是一个符号地址,总之是一个常量)。相对寻址允许段超越

  • 基址变址寻址:内存单元的有效地值分为两部分,一部分在基址寄存器中,另一部分在变址寄存器中。
    举个例子:MOV AX, [BX + DI]等价写法 MOV AX,[BX][DI] 表示的物理地址:(DS) * 10H + (BX) + (DI)
    可用的基址寄存器:BX(数据段),BP(堆栈段)
    可用的变址寄存器:SI,DI

  • 基址变址相对寻址: 内存单元的有效地址分为两部分,一部分在基址寄存器中,另一部分在变址寄存器中,第三部分是表示偏移量的立即数
    举个例子:MOV AX,[BX + DI + 12H]
    表示的物理地址: (DS) * 10H + (BX) + (DI) + 12H

存储器寻址都是允许段超越的

I/O端口寻址

  • 端口直接寻址:端口的地址直接通过立即数给出
    举个例子:IN AL, 21H

  • 端口间接寻址:端口的地址存储在寄存器DX中(必须是DX)
    举个例子:OUT DX, AX

3.地址寻址方式

地址寻址方式,改变程序执行流程的指令需要通过地址寻址方式找到跳转的地址(转移地址)。

分为两大类:段内跳转,和段间跳转;每一类又分为直接和间接两种方式,所以,一共有四种寻址方式。

段内的地址寻址方式

  • 段内直接寻址:又称为相对寻址方式。
    跳转指令给出一个偏移量,将这个偏移量与下一条指令的地址相加,得到转移地址。 举个例子:JMP SHORT NEXT 假设这条指令的地址是18200H,这条指令的长度为2Byte,NEXT的值为20H。跳转指令的下一条指令的地址为18200H + 2H = 18202H,所以转移地址为18202H + 20H = 18222H。
    关于跳转指令的下一条指令的地址,可以有另一个表述:当前IP寄存器的值。当程序读取并执行跳转指令,程序IP会指向跳转指令的下一条指令

  • 段内间接寻址:将转移地址的有效地址部分存储到寄存器或者内存中,程序跳转时,通过数据寻址方式得到跳转地址的有效地址,直接更新IP的值。

段间的地址寻址方式

  • 段间直接寻址:指令中直接给出短地址和有效地址
    举个例子:JMP FAR PTR GAMMA;若GAMMA=3000:4000 执行后,CS的值被更新为3000H,IP的值被跟新为4000H

  • 段间间接寻址:指令中给出一个地址,地址指向4Byte的内存单元,低两个字节存储有效地址,高两字节存储段地址。执行时,通过操作数寻址的方式找到这4Bye,然后用低两字节更新IP,高两字节跟新CS。
    举个例子:JMP DWORD PTR DELTA[BX] 如果DELTA=0040H,(BX)=3000H,(DS)=2000H。通过寄存器相对寻址,DELTA[BX],找到存储转移地址的4Byte。

猜你喜欢

转载自blog.csdn.net/qq2071114140/article/details/102573909