一.8086寻址方式
1.指令构成
2.寻址方式(对于两个操作数分别有不同的寻址方式)
- 立即寻址:操作数直接出现在指令中
-
操作数作为指令的一部分放在代码段中
-
立即寻址只能用于源操作数
-
立即数和目的操作数的长度要一致,立即数可以是8位或16位的二进制数,也可以是字符常数
2.寄存器寻址:操作数在CPU内部寄存器中,寄存器名表示其内容
-
源操作数和目的操作数字长要相同
-
寄存器寻址和段地址无关
3.存储器寻址:操作数在内存
-
存储器操作数的表现形式:[ ],方括号中为立即数或者是寄存器
-
在默认的或使用段超越前缀指定的段存储器中
-
指令中只需给出操作数的逻辑地址
存储器寻址分为四种:
-
直接寻址:直接给出操作数的偏移地址,默认在数据段DS,但也可使用段超越指定其他段,如ES,SS
如 MOV AX,[1100H] #默认在DS段
MOV AX,ES:[1100H] #使用段超越,改为ES段 -
基址寻址:有效地址放在基址寄存器BX或BP中,**对应BX寄存器默认是DS,BP默认对应是SS,**可以使用段超越改变.表现形式为[BX或BP]+[+8位或16位的偏移量]或将偏移量写在括号外
如 MOV AX,[BX] #相当于MOV AX,DS:[BX]
MOV AX,[BP+06H] #相当于MOV AX,SS:[BP+06H],也可以写成MOV AX,SS:06H[BP] -
变址寻址:偏移地址放在变址寄存器SI或DI中,**默认段是DS,**可用段超越改变前缀。表现形式为[SI或DI]+[8位或16位偏移量]
-
基址变址寻址:表现形式为[BX或BP]+[SI或DI]+[8位或16位偏移量],BX寄存器默认是DS,BP默认对应是SS
如MOV AX,[BX][DI] 相当于MOV AX,[BX+DI]
二.指令系统
分类
- 数据传送类指令
- 算术运算指令
- 逻辑运算指令和移位指令
- 串操作指令
- 程序控制指令
- 处理器指令
三.数据传送指令(不影响标志位)
#传送交换指令
- MOV 目的操作数,源操作数
- XCHG 目的操作数,源操作数 #交换两个操作数的内容
#堆栈操作指令
- PUSH OPRD #压栈
- POP OPRD #弹栈
#地址传送指令
- LEA 源操作数,目的操作数
- LDS SI,LIST1 #从LIST1存储单元开始取两个字节给SI和DS
- LES SI,LIST1 #从LIST1存储单元开始取两个字节给SI和ES
#与I/O设备交换数据指令
- IN 源操作数,目的操作数
- OUT 源操作数,目的操作数
#符号位扩展指令
- CBW #把AL的符号位复制到AH,8位到16位的扩展
- CWD #把AX的符号位复制到DX ,16位到32位的扩展
1.MOV指令
(1)关于传送双方的要求:
(2)说明:
- 在图中可以看出并不是任意两者间都可以传送的,如不允许立即数到段寄存器的传送
如果要解决上述问题,我们需要在两者间架起桥梁,用AX作桥梁。 - 双方要至少有一个的类型确定,另外一个依附于已经确定的类型。比如 MOV [1500H],9 这是错误的,因为无法确定9是字还是字节,所以我们可以用 MOV BYTE PTR[1500H],9 。其中BYTE PTR 是修改操作数类型的属性运算符,将操作数修改成字节类型,WORD PTR 则将操作数修改成字
2.XCHG指令
规则:
两操作数中必须有一个是寄存器,操作数不能是段寄存器或者立即数
3.堆栈指令
(1)说明:
- SS段寄存器记录堆栈段基址,堆栈指针为SP,SP总是指向栈顶
- 必须以字为单位进行操作,不能对立即数做堆栈操作,其他十六位的寄存器,段寄存器,存储器都可以。
- 堆栈指令一般成对出现,且操作顺序相反,目的是为了保证堆栈段的原始状态。
- 对标志寄存器进行压栈弹栈操作时,指令为PUSHF 和 POPF
(2)堆栈初始化:
(3)压栈弹栈过程:
(1)压栈时,SP-1,然后压入数据高子节,SP再-1,再压入低字节,随着压栈内容增加,SP不断减小
(2)出栈相反,SP+1,弹出数据低字节,SP再+1,弹出数据高字节
4.LEA指令:将存储器操作数的16位偏移地址传送到指定的寄存器
(1)说明:
- 源操作数必须是一个存储器操作数,目的操作数必须是一个16位的通用寄存器。通常是地址指针寄存器
(2)示例:
MOV BX,OFFSET BUF #将BUF的偏移地址传送到BX中
LEA BX,BUF #将BUF的偏移地址传送到BX中
5.输入输出指令IN,OUT:进行I/O设备和微处理器间的数据交换
(1)说明:
- IN指令将I/O设备数据传给AL/AX,OUT指令将AL/AX中数据传递给I/O设备
- I/O设备的端口地址有8位和16两种形式
- 当端口地址是8位时,可以直接在指令中使用,若为16位,则应放在DX寄存器中再进行传送
(2)示例:
#端口地址为8位
IN AX,25H #代表从端口地址为25H的I/O设备中取出数据传送到AX寄存器中
#端口地址为16位
MOV DX,03F8H
IN AL,DX #代表从端口地址为25H的I/O设备中取出数据传送到AX寄存器中
四.算数运算类指令
(1)说明:
- 操作数不能是段寄存器,需要关注对标志位的影响,可用于字或字节的运算
(2)分类
#加法指令
ADD OPRD1,OPRD2 #不带进位的加法
ADC OPRD1,OPRD2 #带进位的加法
INC reg/mem #加1,不能是段寄存器或者立即数
#减法指令
SUB OPRD1,OPRD2 #不带借位的减法
SBB OPRD1,OPRD2 #带借位的减法
DEC reg/mem #减1,不能是段寄存器或立即数,不影响CF标志位
#乘法指令
MUL 乘数 #无符号乘法
IMUL 乘数 #有符号乘法
#除法指令
DIV 除数 #无符号除法
IDIV 除数 #有符号除法
#比较指令
CMP OPRD1,OPRD2 #将两个操作数相减,但结果不送目的操作数,两数相等ZF=1
#求补指令
NEG reg/mem #用0减去操作数,对非零数求补时
乘法和除法指令
注意:关于乘法和除法的规则
- 指令中的乘数和除数必须是寄存器或者存储器操作数
- 乘法指令不能出现AL,AX寄存器 , 除法指令不能出现AX,DX
- 运算前应先送被乘数、被除数到累加器AX(AL)/AX(DX:AX)中
- 乘法指令对CF,OF标志位的影响有意义,表示相乘之后位数是否变化。其余标志位的变化没有实际意义
- 字节相成的积在AX中,如果CF=OF=1,表明AH不为0,同理字相称乘的积在DX:AX中,如果CF=OF=1,表明DX不为0
- 除法指令被除数必须是被除数字长的两倍
- 除数不能是0,也不能太小,否则会产生溢出,这两个错误会使系统中断
五.逻辑运算类指令和移位类指令
逻辑运算类指令:
# 逻辑运算指令
AND OPRD1,OPRD2 #保留操作数的某几位,其他位清零
OR OPRD1,OPRD2 #将操作数的某几位置1,其他位不变
NOT OPRD #按位取反再送回原地址
XOR OPRD1,OPRD2 #把寄存器清零(自身异或),把操作数的某几位取反(与1异或)
TEST OPRD1,OPRD2 #执行与运算,但是结果不送回目标地址,用于测试某些位的状态,用‘1’测试,ZF标志位判断结果
非循环移位指令:
#移位指令:SAL reg/mem, 1/CL 当移位次数大于1时,由CL指定
#非循环移位类指令:左移1位可实现乘2,右移1位可实现除以2
#逻辑左右移动,将操作数当成无符号数
#算术左右移动,将操作数当成有符号数
SHL(逻辑左移)#空白位用0填补
SHR(逻辑右移)#空白位用0填补
SAL(算术左移)#最高位放在CF中,第0位用0填充
SAR(算术右移)#将0位放在CF中,最高位不变
循环移位指令:
#不带进位标志位CF的循环移动指令
ROL #左移,最高位存入CF和第0位中
ROR #右移,第0位存入CF和最高位中
#带进位标志位CF的循环移动指令
RCL #左移 最高位存入CF,CF的值传入第0位
RCR #右移
循环移位示意图:左边为不带标志位的,右边为带标志位的
六.串指令:对内存中连续存放的数据串进行操作
(1)说明:
- 可以以字节或字为单位进行操作
- 数据串最大长度为64K
- 源操作数 DS:[SI],允许段超越为SS,ES
- 目的操作数 ES:[DI],不允许段超越
- CX作为串计数器
- DF=0,增量 ;DF=1,减量 。增量代表从低地址开始,移动一个数据,指针SI、DI自动修正,DI,SI都加1
- CLD指令 复位方向标志:DF=0。STD指令 置位方向标志:DF=1
(2)分类
#传送类指令
MOVS :MOVSB(传字节) MOVSW(传字) MOVSD(传双字)
#检测类指令
CMPS
#重复前缀
REP
#执行 REP MOVSB之前,需要
# DS:SI, ES:DI 赋值
# 将D标志置零/置1
# 对CX 赋值
MOVS使用实例:
MOV SI,OFFSET STRING1
MOV DI,OFFSET STRING2
MOV CX,100
CLD
REP MOVSB #自动重复传送,直到CX等于0
七.程序控制指令
说明:
- 不会影响标志位
- 按转移条件分:无条件转移和有条件转移
- 按转移范围分:段内转移和段间转移,段内转移只需要改变IP值,段间转移要改变IP和CS的值
- 按获取转移地址的方法分:直接转移和间接转移
#无条件转移指令
JMP OPRD #具体见下表一
#有条件转移指令:满足条件时进行转移
#常在CMP/TEST指令后使用,具体见下表二,三
#循环指令
LOOP LABEL #由CX指定循环次数
#子程序调用指令
call
ret
#调用:CALL子程序,即无条件转到的子程序的第一指令
#返回:RET返回断点,即到 返回到CALL的后继指令
#中断指令:INT n
#8086CPU支持256(00H~FFH)个中断,每个中断用一个编号(中断向量号)区别。
表一
表二:无符号数
表三:有符号数
循环指令示例:将数据段定义的100个元素的数组逆序传到另一个数组里面
LEA SI , ARY
LEA DI , DES
ADD DI , 200-2
MOV CX , 100
MOV AX , [SI]
MOV [DI] , AX
ADD SI , 2
SUB DI , 2
LOOP L1
八.处理器指令:用控制类指令用来控制CPU的状态,使CPU暂停、等待或空操作等。
NOP #空操作,常用于对I/O的操作中
HLT #暂停,CPU进入暂停状态,等待外中断
#DOS功能调用
MOV AH,01H #设置功能调用号
INT 21H #调用功能
标志位控制指令
CLD #复位方向标志:DF←0
STD #置位方向标志:DF←1
CLI #复位中断标志:IF←0
STI #置位中断标志:IF←1