数据传送:负责把数据、地址或立即数传送到寄存器或存储单元中
数据传送指令可以分为四个类型:通用数据传送指令、地址传送指令、标志位传送指令、专用累加器传送指令(输入、输出指令)
一、通用数据传送指令
(一)传送字或字节指令 MOV
(1)重点掌握内容
-
格式:
MOV DST,SRC
-
执行的操作:
(DST) ← (SRC)
-
标志位:不影响
功能:将源操作数传送到目的操作数
这里的传送实际上是复制,将 SRC
复制到DST
,SRC
内容不变
注意
DST
和SRC
必须类型一致(都是 8位 或者是 16位)DST
不能是立即数(立即数不能作为目的操作数)SRC
是立即数时,DST
不能是段寄存器,必须通过通用寄存器作中介- 两个操作数不能同时为存储器操作数,存储单元之间不能直接传送数据
- 两个操作数不能同时为段寄存器操作数,段寄存器之间不能直接传送
(2)传送指令格式总结
SRC
可以是:寄存器、存储单元、立即数、段寄存器DST
可以是:寄存器、存储单元(此时SRC
不能是存储单元)、除CS
以外的段寄存器(此时SRC
不能是立即数和段寄存器)
(3)MOV指令使用的几种情况
-
立即数传送给通用寄存器或存储器
MOV AL,12H ;8位数据传送,将12H传送到寄存器AL中 MOV AX,3456H ;16位数据传送,将3456H传送到寄存器AX中
-
通用寄存器之间相互传送
MOV AX,BX ;16位数据传送,将BX中的数据传送到寄存器AX中 MOV CL,BH ;8位数据传送,将BH中的数据传送到寄存器CL中
-
通用寄存器和存储器之间相互传送
MOV AX,[BX] ;16位数据传送,将BX指定的连续2个字节中的数据传送到AX中 MOV [SI],DH ;8位数据传送,将DH中的数据传送到由SI指定的内存单元中
-
段寄存器与通用寄存器、存储器之间的相互传送
MOV DS,AX MOV BX,ES MOV ES,[SI] MOV [DI],SS
注意:MOV [BX],0
指令是错误的,因为述指令的源操作数是立即数,其长度是不确定的,目的操作数是主存单元,但以低地址访问主存单元时,[BX]
并不能说明是字节单元还是字单元,因此长度也是不确定的
解决办法:在指令中指定内存单元的类型,将上述指令改写为下面两种形式
MOV BYTE PTR BX,0 ;BYTE PTR 说明是字节操作,写一个字节单元
MOV WORD PTR BX,0 ;WORD PTR 说明是字操作,写一个字单元
这样目的操作数长度就是明确的,指令是正确的
(二)堆栈操作指令 PUSH & POP
堆栈是一个“先进后出”的存储区,段地址存放在 SS
中,SP
在任何时候都指向栈顶,进出栈后自动修改 SP
(1)重点掌握内容
PUSH 进栈指令
-
格式:
PUSH SRC
-
执行的操作:
(SP) ← (SP)-2
((SP)+1,(SP)) ← (SRC)
-
标志位:不影响
功能:把通用寄存器,段寄存器,存储单元中的一个字入栈
POP出栈指令
-
格式:
POP DST
-
执行的操作:
(DST) ← ((SP)+1,(SP))
(SP) ← (SP)+2
-
标志位:不影响
功能:从堆栈顶部弹出一个字,到通用寄存器、段寄存器或存储单元
【附注执行操作的解释:因为堆栈指针SP
总是指向已经存入数据的栈顶(不是空单元),所以PUSH
指令是先将(SP)-2
,后将内容压栈,(即先修改SP
使之指向空单元,后压入数据),而POP
是先从栈顶弹出一个字,后将堆栈指针(SP)+2
】
堆栈操作指令使用注意事项
- 堆栈操作必须是以字为单位
- 堆栈操作不能用立即寻址方式
DST
不能是CS
,即POP CS
是不合法的
(2)应用实例
【例1】假设 (AX) = 2107H
【例2】DS=3000H,BX=2000H,SI=0002H,AX=1234H,CX=5678H,(32000H)=99H,(32001H)=88H,(32002H)=77H,(32003H)=66H,(32004H)=55H,(32005H)=44H …
程序如下:
PUSH AX
PUSH CX
POP [BX]
POP [BX+SI]
求执行上面程序后
(1)(32001H)=?
(2)(32002 H)=?,AX=?,BX=?,CX=?
【解】分析如下
(1)(32001H)=56H
(2)(32002H)=34H,AX=1234H,BX=2000H,CX=5678H
(三)交换指令 XCHG
(1)重点掌握内容
- 格式:
XCHG OPR1,OPR2
- 执行的操作:
(OPR1) ←→ (OPR2)
- 标志位:不影响
功能:将OPR1
与OPR2
中的内容进行互换
注意
- 不允许使用段寄存器
- 可以用除立即数以外的所有寻址方式
- 两个操作数必须有一个在寄存器中
(2)应用实例
【例】DS=3000H,BX=2000H,SI=0002H,AX=1234H,(32000H)=99H,(32001H)=88H,(32002H)=77H,(32003H)=66H,(32004H)=55H,(32005H)=44H …
程序如下:
XCHG AX,[BX]
XCHG DX,[BX+SI]
求执行上面程序后的结果(思路和堆栈指令例题相似)
二、累加器(AX)专用传送指令
只限使用AX或AD
(一)输入指令 IN(I/O → CPU)
(1)重点掌握内容
-
长格式:直接在指令中指定端口号(0~FFH)
IN AL, PORT (字节)
IN AX, PORT (字)
执行的操作:
(AL) ← (PORT) (字节)
(AX) ← (PORT+1,PORT) (字)
-
短格式:须先把端口号放在DX寄存器中(0000~FFFFH)
IN AL, DX (字节)
IN AX, DX (字)
执行的操作:
(AL) ← ((DX)) (字节)
(AX) ← ((DX)+1,(DX)) (字)
-
标志位:不影响
(2)应用实例
【例1】
IN AX,28H
MOV DATA_WORD,AX
;把端口28的内容经过AX送到内存单元中
【例2】
MOV DX,3FCH
IN EAX,DX
;从端口送一个双字到EAX中
(二)输出指令 OUT(CPU → I/O)
(1)重点掌握内容
-
长格式:直接在指令中指定端口号(0~FFH)
OUT PORT,AL(字节)
OUT PORT,AX (字)
执行的操作:
(PORT) ← (AL) (字节)
(PORT+1,PORT) ← (AX) (字)
-
短格式:须先把端口号放在DX寄存器中(0000~FFFFH)
OUT DX,AL (字节)
OUT DX,AX (字)
执行的操作:
(AL) ← ((DX)) (字节)
(AX) ← ((DX)+1,(DX)) (字)
-
标志位:不影响
(2)应用实例
【例】
OUT 5,AL
;把 AL 中的内容送到端口5
(三)换码指令 XLAT(了解)
(1)重点掌握内容
- 格式:
XLAT
或XLAT OPR(首地址)
- 执行的操作:
(AL) ← ((BX)+(AL))
- 标志位:不影响
功能:将AL与BX寄存器内容之和作为偏移地,将其所对应的存储单元的内容送入AL寄存器中
注意
- 执行前:在内存建立一个字节表格(长度不超过256),内含要转换成的目的代码
BX——存放表格首地址
AL——存放相对表格首地址的偏移量 - 执行后:将AL寄存器的内容转换为目标代码
(2)应用实例
【例】 (BX) = 0400H,(DS) = F000H
程序执行后 (AL) = 33H
三、地址传送指令
(一)有效地址EA送寄存器指令 LEA
(1)重点掌握内容
- 格式:
LEA REG,SRC
- 执行的操作:
(REG) ← SRC
- 标志位:不影响
功能:该指令把存储单元内容的有效地址送到指定的寄存器中(用一个寄存器作内存单元的地址指针)
注意
- REG不能是段寄存器
- SRC 必须为存储器寻址方式(即不能使用立即数和寄存器寻址方式)
(2)MOV 和 LEA 的区别
LEA 指令可以用来将一个内存地址直接赋给目的操作数,例如:
LEA EAX,[EBX+8]
就是将 EBX+8 这个值直接赋给 EAX
而 MOV 指令 MOV EAX,[EBX+8]
则是把内存地址为 EBX+8 处的数据赋给 EAX
【摘自:汇编语言中mov和lea的区别有哪些? 】
注意:MOV EAX,EBX+8
看起来和 LEA EAX,[EBX+8]
作用相同,但是MOV 指令不支持这样的格式 【摘自:lea和mov指令的区别】
(二)指针传送指令 LDS & LES
(1)重点掌握内容
-
格式
LDS REG,SRC
LES REG,SRC
-
执行的操作
(REG) ← (SRC)
(DS)←(SRC+2)
相继二字 → 寄存器、DS(REG) ← (SRC)
(ES)←(SRC+2)
相继二字 → 寄存器、ES -
标志位:不影响
注意
- REG不能是段寄存器
- SRC 必须为存储器寻址方式(即不能使用立即数和寄存器寻址方式)
(2)LEA & LDS & LES 综合应用实例
四、标志传送指令
(一)标志送AH指令 LAHF
(1)重点掌握内容
- 格式:
LAHF
- 执行的操作:
(AH) ← (Flag/PSW的低位字节)
- 标志位:不影响
(二)AH送标志寄存器指令 SAHF
(1)重点掌握内容
- 格式:
SAHF
- 执行的操作:
(Flag/PSW的低位字节) ← (AH)
- 标志位:影响
(三*)标志进栈指令 PUSHF
(1)重点掌握内容
- 格式:
PUSHF
- 执行的操作
(SP) ← (SP)-2
((SP)+1,(SP)) ← (FLAGS)
- 标志位:不影响
功能:保护标志
(四*)标志出栈指令 POPF
(1)重点掌握内容
- 格式:
POPF
- 执行的操作:
(FLAGS) ← ((SP)+1,(SP))
(SP) ← (SP)+2
- 标志位:影响
功能:恢复标志
五、类型转换指令
(一)字节扩展到双字 CBW
(1)重点掌握内容
- 格式:
CBW
- 执行的操作:
若(AL)的最高有效位为 0,则 (AH) = 00H
若(AL)的最高有效位为 1,则 (AH) = FFH - 标志位:不影响
(二)字扩展到双字 CWD
(1)重点掌握内容
- 格式:
CWD
- 执行的操作:
若(AX)的最高有效位为 0,则 (DX) = 0000H
若(AX)的最高有效位为 1,则 (DX) = FFFFH - 标志位:不影响
这篇 【汇编语言】cbw和cwd 博客讲解了具体方法
参考文章
数据传送指令
8086CPU指令系统——数据传送类指令