8086CPU中的寻址方式一

寻址方式

定义

寻址方式:求操作数所在地或者所在存储器地址单元的方式。

指令中的操作数,大多数都在存储器单元当中,也可以在寄存器里面,也可以是在指令中立即给出的常数。我们都把求得她们的方式归属于寻址方式。


类型

寻址方式按求得的操作数的目的不同,可以分为两类:

  1. 数据用

  2. 程序要实现转移的地址用

如果要实现段内转移,就需要求得段内偏移地址给IP用,如果要实现段间转移,除了偏移地址外,还需要求得目的地的段地址给CS用。

要计算的数据的所在存储地址怎么得到,或者转移的地址内容的所在存储地址怎么得到,就需要用以一种寻址方式去求得。


关于数据的寻址方式

1.立即数寻址

要寻找的操作数在指令中立即给出,直接以常数给出。

mov AX,1234H

AX是目的操作数,1234H是源操作数,对于源操作数而言,采用的就是立即数寻址。指令中要传送给AX的数据在哪里呢?指令中立即给出了。这就叫立即数寻址。

要搞清楚8086立即寻址,就需要了解谁和谁之间可以传送

从图中可知,在8086当中,立即数只能作为源操作数。

立即数传送数据时要类型明确

mov [0002H],15H

中括号里面表示的是地址,这条语句是把立即数15H送到地址为0002H的存储器单元中。

但是我们只知道地址是多少,不知道存储器单元的存储类型是什么?语法错误。类型不明确。这中问题只要源操作数和目标操作数有一方明确,双方均能明确(不一致另说)。双方不明确,类型不明确。

mov WORD PTR [0002H],15H

如果要传送数据给段寄存器,不能直接立即数传送,要按箭头走。

从图中也可以看出,段寄存器CS单独划分出来,因为用户无法改变CS的内容,和IP寄存器一样,开机的内容由操作系统完成。执行期间是由CPU完成转移指令改变。CS和IP不能做目标操作数,但是可以做源操作数。


2.寄存器寻址

指要寻找的操作数在某寄存器当中

mov AX,BX

对于源操作数而言,要操作的数据在BX寄存器中,这就是寄存器寻址。同样的,目的操作数而言,也是寄存器寻址。

当源和目标是寄存器寻址时,一定要注意类型要一致

mov AX,CL

AX是16位的,而CL是8位的,语法错误。


3.存储器寻址

指要寻找的操作数在存储器某单元中,存放操作数的单元的EA段内偏移地址,可以由以下5种寻址方式求得:

1.直接寻址

直接寻址就是在指令中直接写出存储单元的有效地址

mov AL,[2000H]

将存储器单元地址为2000H的字节内容送给AL(实际上决定是字节内容的是AL的类型)

但这种方法不常用,一般都将地址符号化——变量名。

在DS段有下列变量定义:

dat1 DB 12H
dat2 DB 34H
...

实际中数据段定义的变量很多。

在CS段执行程序

mov AL dat1

dat1代表的就是一个地址,所以源操作数的寻址方式是直接寻址。在dat1里面的内容送给AL。执行完(AL)=12H。

mov dat2 dat1

源和目标操作数都采用直接寻址,想把dat1里内容直接送给dat2单元里面。但是语法错误。如上图3.3,寄存器之间可以互传数据,但是存储器单元之间不可以直接操作(任何操作)。不能直接传送数据,也不能直接运算。

只能通过寄存器做中转,读出来后,再将寄存器里面的值送给存储器。

当然也要遵循前后类型一致。如

mov WORD PTR dat1,AX

而不能直接进行数据传送,因为dat1是字节变量8位,AX是16位。

mov dat1,AX

2.寄存器间接寻址

指操作数在存储器中,段内偏移地址由寄存器间接给出。能做寄存器间接寻址的寄存器只有3个——BX,SI,DI。

这三个寄存器默认的段地址默认在DS数据段

dat1 DB 12H
dat2 DB 34H

把dat1内容送给AL,寄存器间接寻址方式为:

mov BX, OFFSET dat1
mov AL,[BX]

OFFSET dat1把dat1的偏移地址属性拿出来了,所以对于源操作数而言属于立即数寻址。

[BX]中括号里面是把BX的内容作为DS段的段内有效地址,属于寄存器间接寻址。


3.寄存器相对寻址

指的是操作数在存储器某个单元当中,有效地址由两部分组成:

第一部分在一个基址寄存器当中——BX,BP,SI,DI 四者之一。第二部分是一个8位或16位的DISP相对位移量。两部分之和就是操作数所在存储单元的地址。

如果相对位移量是一个常数,那么对应的逻辑段的段地址由寄存器部分默认决定给出。BX\SI\DI默认在DS段,BP默认在堆栈段SS。

如果相对位移量是一个变量,会自动取变量的段内偏移地址作为位移量,此时逻辑段的段地址由变量所在的段决定。

当然我们可以添加段超越前缀,改变寄存器指向的段地址。

这个方式容易和寄存器间接寻址混淆,但我觉得其实就是间接寻址基础上加上个位移量,但是又加上了一些规则。

mov [BP],AL

注意,[BP]是寄存器相对寻址,因为BP不能用作间接寻址。所以这条指令,是把AL的内容送给某个存储器单元,这个单元的地址一部分是BP内容,一部分为相对位移量,这里为0,即SS:(BP)+0。

ALmov [BX]+3,AL

目标操作数是寄存器相对寻址,存储器单元地址为BP内容+3.

这种方式也可以写成

mov [BX+3],AL

结果相同,汇编后代码相同,只是书写格式不同。

也可以写成

mov 3+[BX],AL

当位移量在左边时,加号可以省略,即

mov 3[BX],A

当位移量是一个变量时

dat1 DB 12H
mov dat1[BX],AL

dat1定义在DS段,则dat1[BX]代表的存储器地址为 DS:OFFSET dat1+(BX)

BP相对寻址的目的

添加BP进行相对寻址的目的,是为了在不破坏堆栈指针SP的情况下,将堆栈里面的值读取出来

PUSH AX
PUSH BX
PUSH CX

现在将AX内容送给DX,但不能破坏SP内容,怎么做·?

mov BP,SP
mov DX,[BP]+4

4.基址、变址寻址

指的是操作数在存储器某个单元当中,有效地址由两部分组成:第一部分在一个基址寄存器当中——BX,BP两者之一;第二部分在一个变址寄存器中——SI、DI两者之一。两部分之和就是操作数所在存储单元的段内地址。段地址由基址寄存器默认决定。这种寻址方式叫做基址、变址寻址。

如,用基址、变址寻址方式,将dat1内容送给AL

dat1 DB 12H
dat2 DB 34H
...
mov BX,OFFSET dat1
mov SI,0
mov AL,[BX][SI]

5.基址、变址相对寻址

由第三种和第四种结合而来。

指的是操作数在存储器某个单元当中,有效地址由三部分组成:第一部分在一个基址寄存器当中——BX,BP两者之一;第二部分在一个变址寄存器中——SI、DI两者之一;第三部分是一个8位或16位的DISP相对位移量。三部分之和就是操作数所在存储单元的地址。这种寻址方式叫做基址、变址相对寻址。

同样的,和第三种一样,如果相对位移量是一个常数,那么对应的逻辑段的段地址由寄存器部分默认决定给出。BX默认在DS段,BP默认在堆栈段SS。

如果相对位移量是一个变量,会自动取变量的段内偏移地址作为位移量,此时逻辑段的段地址由变量所在的段决定。

如,用基址、变址相对寻址方式,将dat1内容送给AL

dat1 DB 12H
dat2 DB 34H
...
mov BX,0
mov SI,0
mov AL,dat1[BX][SI]

4.隐含寻址

隐含寻址的含义是,指令中并没有写明操作数,但是CPU知道操作数在哪个地方。

PUSH AL

指令只有单操作数,且是源操作数,没有指明目标操作数在哪里,但是CPU知道怎么做:

  1. SP=(SP)-2

  2. (SS:(SP))=AL

在8086中,字符串的指令,对于源和目标操作数都是隐含寻址。


实际当中,我们只需要选择其中之一作为寻址方式即可。

posted @ 2021-02-20 15:28  懒懒阳光下的午睡  阅读(1643)  评论(0编辑  收藏  举报