指令系统(二)
寻址方式(一)
在指令中,用于说明操作数所在地址的方法就称为寻址方式
8086 CPU指令系统的寻址方式分为两类。
-
数据的寻址方式:寻找指令操作所需数据的方法。
-
转移地址的寻址方式:寻找转移指令所需程序地址的方法。
数据的寻址方式
一共有8种:立即寻址、寄存器寻址、直接寻址、寄存器间接寻址、寄存器相对寻址、基址-变址寻址、基址-变址-相对寻址(后五类可以统称存储器寻址)和隐含寻址
MOV指令数据传送图:

注意图中只有立即数和段寄存器是单向箭头,说明:
- 立即数只能做SRC(源操作数)
- 段寄存器只能做DST(目的操作数)
立即寻址
将8位或16位数据直接放在指令之后,这种操作数的寻址方式称为立即寻址
例:MOV AX, 1234H
寄存器寻址
指令的操作数存放在寄存器中,这种操作数的寻址方式称为寄存器寻址。16位数据可以存放在寄存器 AX、BX、CX、DX、SI、DI、SP、BP、DS、ES、SS、CS 中;8 位数据可以存放在寄存器AL、AH、BL、BH、CL、CH、DL、DH中
例:MOV AX, BX 功能:将BX寄存器中的数据存入AX寄存器中
注意
-
传送类型的寄存器要一致,解决方法参考PTR操作符
比如:
MOV [0200H], 56H; [0200H]是个寄存器,0200H是寄存器地址,寄存器类型不知道 ;解决 MOV WORD PTR [0200H], 56H -
注意:立即数和段寄存器(
DS、ES、SS)不能直接交互,看上图,图中立即数和段寄存器没有箭头直接连接解决:二者交互要通过存储单元或者通用寄存器
例:
MOV DS, 1500H;语法错误 ;解决 MOV AX, 1500H MOV DS, AX -
CS、IP不能做DST,用户无权更改其值例:
MOV CS, AX;语法错误 MOV AX, CS;正确 MOV IP, AX;语法错误 MOV AX, IP;正确
其他语法规则:堆栈操作,只能按字操作
存储器寻址
要寻找的操作数(OPR)在存储器某单元中,存储操作数单元的段内偏移地址(EA)可以由以下5种方法求得
直接寻址
操作数保存在存储单元中,其16位的偏移地址(有效地址)直接在指令中给出,这种方式称为直接寻址
例1:
MOV AL, [2000H]
分析
- 存储器段地址
DS(默认),偏移地址2000H,即DS:2000H - 目的寄存器是
AL,字节型单元,所以DS:2000H处存储的是字节型数据 - 将
DS:2000H处存储的字节型数据送入AL
例2:将DAT1的数据送入AL(直接寻址)
DATA SEGMENT ;定义数据段
DAT1 DB 12H ;定义两个变量
DAT2 DB 34H
DATA ENDS
CODE SEGMENT ;定义代码段
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX ;将数据段的段地址送人DS
MOV AL, DAT1
CODE ENDS
END START
结果:

分析代码 MOV AL, DAT1 ,AL和DAT1分别是什么寻址
根据上节知道,变量有5个属性,DAT1代表的就是一个地址(储存变量数据存储器的地址)
所以DAT1是直接寻址,而AL是寄存器寻址
注意:两存储器之间不能直接操作
MOV DAT2, DAT1;语法错误
例3:将字型数据传给字节型(关注第11-14行代码)
DATA SEGMENT ;定义数据段
DAT1 DB 12H ;定义两个变量
DAT2 DB 34H
DATA ENDS
CODE SEGMENT ;定义代码段
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX ;将数据段的段地址送人DS
MOV DAT1, AX;语法错误,类型不一致
;修改
MOV WORD PTR DAT1, AX
MOV AL, DAT2 ;用于查看DAT2内的数据
CODE ENDS
END START
这会有个问题,刚才还定义了一个 DAT2 ,这个变量还会存在吗,其中的数据会发生变化吗
演示:
语句执行前:

第一个空间存储的是DAT1,第二个空间存储的是 DAT2

寄存器 AX内是0710H
执行后:

数据段内,DAT2的数据被覆盖了

但 DAT2这个变量还存在
寄存器间接寻址
操作数保存在存储单元中,其段内偏移地址存放在寄存器中。只能使用 BX、SI、DI
注意:
BX默认为DS段的基址,BP默认为SS段,也就是堆栈段的基址
例4:将DAT1的数据送入AL(寄存器间接寻址)
MOV BX, OFFSET DAT1 ;
MOV AL, [BX] ;(DS:(BX))-->AL
分析:BX 采用寄存器间接寻址
寄存器相对寻址
操作数保存在存储器中,其段内偏移地址为一个基址寄存器或变址寄存器的内容与一个8位或16位的位移量(disp)之和:

MOV [BP], AL;(SS:(BP)+0)<--AL
编译后:

MOV DAT1+3, AL
分析:DAT1+3是直接寻址,将 AL内的数据,存入DAT1+3所指向的空间内
下面改用寄存器间接寻址
MOV [BX]+3, AL;等价于MOV 3[BX], AL
结果展示:
未转移前的数据段:

未转移前的 AL :

转移后的数据段:

注意:
MOV BX, 0 ;清零
MOV AL, 0 ;清零
MOV DAT1[BP], AL;DS:OFFSET DAT1+(BX)<--AL
-
因为
DAT1在DS中定义,所以最后一行代码段地址是DS -
MOV [BX]+3, AL也可写成MOV [BX+3], AL
例:CPU执行以下代码
PUSH AX
PUSH BX
PUSH CX
将压入堆栈的(AX)放入DX中,但不能破坏 SP指针
分析:
PUSH前,DX中数据为0:

PUSH后:

;寄存器相对寻址
MOV BP, SP;使BP也指向FFFA
MOV DX, [BP]+4
注意:代码中为什么 +4,因为堆栈操作是按字操作,且指向栈底,每次 PUSH地址 -2,所以 FFFA+4=FFFE(AX的地址)
结果:

DX获取到了值,且 SP没有改变
基址-变址寻址
操作数保存在存储器中,其段内偏移地址为一个基址寄存器和一个变址寄存器的内容之和:

例:
MOV AX, [BX][SI]
基址-变址-相对寻址
操作数保存在存储器中,其段内偏移地址为一个基址寄存器内容、一个变址寄存器内容、一个 8 位或 16 位的位移量(DISP)之和:

例:用基址-变址-相对寻址,将DAT1清零

代码:
MOV BX, OFFSET DAT1
MOV SI, 0
MOV AL, 0
MOV [BX][SI], AL;((BI)+(SI))<--AL,基址-变址寻址
结果:

在将 DAT2的值清零
代码:
MOV [BX][SI]+1, AL;((BI)+(SI)+1)<--AL,基址-变址-相对寻址
结果:

隐含寻址
有些指令的指令码中不包含指明操作数寻址方式的部分,但操作码本身隐含指明了操作数的地址
例:
PUSH AX; 1.SP<--(SP)-2
; 2.(SS:(SP))<--(AX)
压栈操作只给出了源操作数,但本身隐含了目的操作数((SS:(SP)))
后面讲的字符串操作指令,均为隐含寻址

浙公网安备 33010602011771号