您的位置: 网站首页 > 程序开发 > 汇编语言与微机原理教程 > 第9章 80x86的寻址方式与指令系统 > 【9.3.1 数据传送指令】

9.3.1 数据传送指令

 

9.3.1  数据传送指令

数据传送指令是一种简单而又基本的语句,它常用于给寄存器、内存变量置初值或赋新值。当需要把一些信息传送到某处时,就要用数据传送指令。下面介绍最常用的5种数据传送指令。

1MOV——传送指令

形式:MOV  目标操作数,源操作数。

功能:目标操作数(源操作数)。

该指令有如下9种形式:

MOV  R,R        ; 通用寄存器间传送

MOV  R,Im       ; 立即数送通用寄存器

MOV  M,Im       ; 立即数送内存单元

MOV  M,R        ; 通用寄存器送内存单元

MOV  R,M        ; 内存数送通用寄存器

MOV  SegR,R     ; 通用寄存器送段寄存器(CS除外)

MOV  R,SegR     ; 段寄存器送通用寄存器

MOV  SegR,M     ; 内存数送段寄存器(CS除外)

MOV  M,SegR     ; 段寄存器送内存单元

使用MOV指令应注意:

1)源操作数和目的操作数不能同时为内存数,即MOV MM的指令形式是非法的。

2)两个操作数的类型属性要一致,例如,MOV AXBL指令中的两个操作数,一个是字操作数,一个是字节操作数,两个操作数的类型不一致,所以是非法指令。

3)操作数不能出现二义性,即至少一个操作数的类型要明确,例如,MOV  [BX]1000H指令中的两个操作数的类型都不明确,不知是字还是字节。更要特别注意的是,立即数是没有类型的,不能把16位二进制数当作字类型,也不能把8位二进制数当字节类型。

2XCHG——数据交换指令

形式:XCHG  目标操作数,源操作数。

功能:目标操作数 源操作数。

该指令有如下3种形式:

XCHG  R,R    ; RR

XCHG  R,M    ; RM

XCHG  M,R    ; MR

3.地址传送类指令

微处理器有3条指令专门传送地址,它们的目标操作数均是16位的通用寄存器,源操作数都是内存数。

1LEA——传送偏移地址指令。

形式:LEA  目标操作数,源操作数。

功能:目标操作数源操作数的偏移地址。

该指令只有如下一种形式:

LEA  R 16,M    ; R16OFFSET M

该指令的意义是将按源操作数M提供的寻址方式计算的偏移地址送16位通用寄存器。该指令通常用来给某个16位通用寄存器设置偏移地址的初值。

假设BUFF是内存变量名,例如:

LEA  SI,BUFF   

该指令的功能是将BUFF的偏移地址送入SI寄存器,源操作数是直接寻址。

MOV SI,OFFSET BUFF 

该指令的功能是将BUFF的偏移地址送入SI寄存器,所以该指令与上条指令是等价的,不过该指令的源操作数是立即寻址。

MOV SI,BUFF

该指令的功能是将BUFF单元的内容送入SI寄存器。

2LDS——传送数据段地址指令。

形式:LDS  目标操作数,源操作数。

功能:目标操作数←(源操作数),DS←(源操作数+2)。

该指令只有如下一种形式:

LDS    R16M    ; R16←(M),DS←(M+2

该指令的意义是将存于M的逻辑地址(双字)的段地址送DS,偏移地址送16位通用寄存器。

例如:

LDS   SI,[BX]    ;SI←(DS:[BX],DS:[BX+1],Ds←(DS:[BX+2],DS:[BX+3]

3LES——传送附加段地址指令。

形式:LES  目标操作数,源操作数。

功能:目标操作数←(源操作数),ES←(源操作数+2)。

该指令只有如下一种形式:

LES  R16,M  ; R16←(M,DS←(M+2

该指令的意义是将存于M的逻辑地址(双字)的段地址送ES,偏移地址送16位通用寄存器。

例如:

LES  SI,[BX]  ;SI←(DS:[BX],DS:[BX+1],ES←(DS:[BX+2],DS:[BX+3]

例如有一数据段定义如下:

mydata      SEGMENT

ORG         1000H

dPt1 DD     15780100H

dPt2 DD     20001000H

wEa DW      4765H

mydata      ENDS

有如下语句:

LEA     SI,dPt1     ; SI1000H

LEA     BP,dPt2     ; BP1004H

LDS     DI,dPt1     ; DI0100HDS1578H

LES     BX,dPt2     ; BX1000HES2000H

LDS     DI,wEa      ; 非法指令,源操作数若为内存变量,类型需为双字

4XLAT——查表转换指令

形式:XLAT

功能:AL←(DS[BX+AL])。

该指令的操作数都是隐含的,所执行的操作是将以BX为基地址,AL为位移量的字节存储单元中的数送AL。该指令可以很方便地将一种代码转换为另一种代码。

9-1 数字07对应的格雷码为:

                            数字   格雷码  十六进制值

                             0           000           00H

                             1           001           01H

                             2           011           03H

                             3           010           02H

                             4           110           06H

                             5           111           07H

                             6           101           05H

                             7           100           04H

要求从键盘输入一位07的十进制数码,把它变成格雷码再输出到显示器上。

注意:因为十进制数码与格雷码之间没有函数关系,所以必须用查表指令来实现转换,不过应在数据段首先建立格雷码表。

源程序:

.MODEL  SMALL

.STACK  200H

.DATA

bGlm DB 00H,01H,03H,02H

DB 06H,07H,05H,04H

.CODE

startMOV AX,@DATA

MOV DS,AX

MOVAH,  1

INT     2IH             ; 等待从键盘输入数码→AL

SUB     AL,30H          ; ASCII码转换成数值

LEA     BX,bGlm

XLAT                    ; AL←对应的格雷码

ADD     AL,30H          ; AL←将格雷码转换成ASCII

MOV     DI,AL

MOVAH,  2

INT     21H             ; CRT显示

.EXIT   0

END start

运行结果(带下画线表示输入的字符)如下:

46

5PUSH/POP——堆栈操作指令

堆栈是以“后进先出”的规则存取信息的一种存储机构。在微机中,堆栈就是在内存中定义的一部分空间。为了保证堆栈区能按“后进先出”的规则存取信息,该存储区的存取地址由一个专门的地址寄存器(SP)来管理,这个地址寄存器称为堆栈指针或称为堆栈指示器。当信息存入堆栈时,堆栈指针将自动递减,然后将信息存入堆栈指针所指示的存储单元中;当需要从堆栈中取出信息时,首先将堆栈指针所指示的存储单元的内容读出,然后堆栈指针将自动递增。所以,堆栈指针始终指向堆栈中最后存入信息的那个单元,我们称该单元为堆栈顶。在信息的存与取的过程中,栈顶是不断移动的,而栈底是固定不变的。对堆栈的操作主要有两大类:进栈(信息的存入)和出栈(信息的取出)。

1)进栈。

形式:PUSH操作数16

功能:系统自动完成两步操作,即SPSP-2SP←操作数16

该指令有如下3种形式:

PUSH        R16     ; SPSP-2,SPR16

PUSH        SegR    ; SPSP-2,SPSegR

PUSH        M16     ; SPSP-2,SPM16

2)出栈。

形式:POP  操作数16

功能:系统自动完成两步操作,即操作数16←(SP),SPSP-2

该指令有如下3种形式:

POP         R16     ; R16←(SP,SPSP-2

POP         SegR    ; SegR←(sP,sPsP-2,CS除外)

POP         M16     ; M16←(SP,SPSP-2

9-2 在例9-1中显示的界面不美观,因为从键盘输入的数据和格雷码混在一起。为了有所区分,希望显示格式为:

键盘输入的数据——对应的格雷码

注意:为了实现所要求的显示格式,我们只需在例9.1中显示格雷码前加显“-”。但是,加显“-”的系统程序的调用改变了AL寄存器值。为了保护AL中的值,通常做法都是将其压入堆栈,显示“-”后,再将其从堆栈中取出传给AL

源程序:

.MODEL  SMALL

.STACK  200H

.DATA

bGlm DB 00H,01H,03H,02H

DB 06H,07H,05H,04H

.CODE

startMOV AX,@DATA

MOV     DS,AX

MOVAH,  1

INT     21H             ; 等待从键盘输入数码AL

SUB     AL,30H          ; ASCII码转换成数值

LEA     BX,bGlm

XLAT                    ; AL←对应的格雷码

PUSH        AX          ; 保护AL寄存器值

MOV     DI,'-'

MOV     AH,02H

INT     21H             ; 显示“-

POP     AX              ; 恢复AL寄存器值

ADD     AL,30H          ; AL←将格雷码转换成ASCII

MOV     DI,AL

MOVAH,  2

INT     21H             ; CRT显示

.EXIT   0

END     start

运行结果:

4-6

现在我们来分析该程序的堆栈定义及操作。该程序中的语句“.STACK  200H”就是对堆栈的定义,即在内存中划分出200H字节作为堆栈区,其地址为SS0000HSS01FFH,那么堆栈指针SP的初值为0200H,如图9-1所示。程序中的堆栈操作语句有:

PUSH AX

该语句SP01FEH,(SS01FE)←(AL),(SS01FF)←(AH),堆栈变化如图9-2所示。

POP AX

该语句AL←(SS01FE),AH←(SS01FFH),SP0200H,堆栈变化如图9-3所示。

9-1  堆栈的定义              9-2  进栈操作                  9-3  出栈操作