指令系统(二)

目录

寻址方式(一)

在指令中,用于说明操作数所在地址的方法就称为寻址方式

8086 CPU指令系统的寻址方式分为两类。

  • 数据的寻址方式:寻找指令操作所需数据的方法。

  • 转移地址的寻址方式:寻找转移指令所需程序地址的方法。

数据的寻址方式

一共有8种:立即寻址、寄存器寻址、直接寻址、寄存器间接寻址、寄存器相对寻址、基址-变址寻址、基址-变址-相对寻址(后五类可以统称存储器寻址)和隐含寻址

MOV指令数据传送图:

image-20230216123206412

注意图中只有立即数和段寄存器是单向箭头,说明:

  • 立即数只能做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寄存器中

注意

  1. 传送类型的寄存器要一致,解决方法参考PTR操作符

    比如:

    MOV [0200H], 56H; [0200H]是个寄存器,0200H是寄存器地址,寄存器类型不知道
    ;解决
    MOV WORD PTR [0200H], 56H
    
  2. 注意:立即数和段寄存器(DS、ES、SS)不能直接交互,看上图,图中立即数和段寄存器没有箭头直接连接

    解决:二者交互要通过存储单元或者通用寄存器

    例:

    MOV DS, 1500H;语法错误
    ;解决
    MOV AX, 1500H
    MOV DS, AX
    
  3. CS、IP不能做 DST,用户无权更改其值

    例:

    MOV CS, AX;语法错误
    MOV AX, CS;正确
    MOV IP, AX;语法错误
    MOV AX, IP;正确
    

其他语法规则:堆栈操作,只能按字操作

存储器寻址

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

直接寻址

操作数保存在存储单元中,其16位的偏移地址(有效地址)直接在指令中给出,这种方式称为直接寻址

例1:

MOV AL, [2000H]

分析

  1. 存储器段地址DS(默认),偏移地址2000H,即 DS:2000H
  2. 目的寄存器是 AL ,字节型单元,所以 DS:2000H处存储的是字节型数据
  3. 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

结果:

image-20230216165905651

分析代码 MOV AL, DAT1ALDAT1分别是什么寻址

根据上节知道,变量有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 ,这个变量还会存在吗,其中的数据会发生变化吗

演示:

语句执行前:

image-20230216173717908

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

image-20230216173815418

寄存器 AX内是0710H

执行后:

image-20230216173850234

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

image-20230216174105657

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)之和:

image-20230216130941846

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

编译后:

image-20230216185847429

MOV DAT1+3, AL

分析:DAT1+3是直接寻址,将 AL内的数据,存入DAT1+3所指向的空间内

下面改用寄存器间接寻址

MOV [BX]+3, AL;等价于MOV 3[BX], AL

结果展示:

未转移前的数据段:

image-20230216190642526

未转移前的 AL

image-20230216190818383

转移后的数据段:

image-20230216190731468

注意

MOV BX, 0		;清零
MOV AL, 0		;清零
MOV DAT1[BP], AL;DS:OFFSET DAT1+(BX)<--AL
  • 因为 DAT1DS中定义,所以最后一行代码段地址是 DS

  • MOV [BX]+3, AL也可写成 MOV [BX+3], AL

例:CPU执行以下代码

PUSH AX
PUSH BX
PUSH CX

将压入堆栈的(AX)放入DX中,但不能破坏 SP指针

分析:

PUSH前,DX中数据为0:

image-20230216201225223

PUSH后:

image-20230216201325838

;寄存器相对寻址
MOV BP, SP;使BP也指向FFFA
MOV DX, [BP]+4

注意:代码中为什么 +4,因为堆栈操作是按字操作,且指向栈底,每次 PUSH地址 -2,所以 FFFA+4=FFFEAX的地址)

结果:

image-20230216201855677

DX获取到了值,且 SP没有改变

基址-变址寻址

操作数保存在存储器中,其段内偏移地址为一个基址寄存器和一个变址寄存器的内容之和:

image-20230216131105851

例:

MOV AX, [BX][SI]

基址-变址-相对寻址

操作数保存在存储器中,其段内偏移地址为一个基址寄存器内容、一个变址寄存器内容、一个 8 位或 16 位的位移量(DISP)之和:

image-20230216131201657

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

image-20230216190642526

代码:

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

结果:

image-20230216203054567

在将 DAT2的值清零

代码:

MOV [BX][SI]+1, AL;((BI)+(SI)+1)<--AL,基址-变址-相对寻址

结果:

image-20230216203140506

隐含寻址

有些指令的指令码中不包含指明操作数寻址方式的部分,但操作码本身隐含指明了操作数的地址

例:

PUSH AX; 1.SP<--(SP)-2
	   ; 2.(SS:(SP))<--(AX)

压栈操作只给出了源操作数,但本身隐含了目的操作数((SS:(SP))

后面讲的字符串操作指令,均为隐含寻址

posted @ 2023-02-16 21:00  打不死の小强丶  阅读(114)  评论(0编辑  收藏  举报