通用寄存器:
数据寄存器:累加器AX,基址寄存器BX,计数器CX,数据寄存器DX
变址寄存器:源地址寄存器SI,目的变址寄存器DI
指针寄存器:基址指针BP,堆栈指针SP
段寄存器:
代码段寄存器CS
堆栈段寄存器SS
数据段寄存器DS
附加段寄存器ES
标志寄存器:FLAGS
指令指针:IP
数据寄存器
8086有4个16位数据寄存器:AX,BX,CX,DX;它们都可以分为两个独立的8位寄存器:
AH/AL,BH/BL,CH/CL,DH/DL;对其中的某8位操作,并不影响另外对应8 位寄存器的数
据.数据寄存器是通用的,用来存放计算结果和操作数, 但每个寄存器又有它们各自
专用目的,主要是:
AX称为累加器,使用程度最高,用于算术,逻辑运算及与外设传送信息等;
BX称为基地址寄存器,常用做存放存储器的地址;
CX称为计数器,作为循环和串操作等指今中隐含的计数器;
DX称为数据寄存器,常用来存放双字节长数据的高16位,或存放外设端口地址.
指针及变址寄存器
指针及变址寄存器包括SI,DI,BP,SP四个16位寄存器,常用于存储器寻址时提供地址.
SI是源变址寄存器,DI是目的变址寄存器,一般与DS联用确定数据段中某一存储单元
地址.
SP为堆栈指针寄存器,指示栈顶的偏移地址;BP为基址指针寄存器, 表示堆栈段中的
基地址.
16位指令指针寄存器IP用来指示代码段中指令的偏移地址,它与代码段寄存器CS 联
用,以确定下一条指令的物理地址.处理器利用CS:IP取得下一条要执行的指令,然后
修改IP的内容,使之指向下一条指令的存储器地址.
标志寄存器(FLAGS) 也称为状志标志寄存器PSW
0 CF(Carry Flag) 进位标志
1
2 PF(Parity Flag)零标志
3
4 AF(Auxiliary Carry Flag)辅助进位标志
5
6 ZF(Zero Flag)零标志
7 SF(Sign Flag)符号标志:运算结果最高有效位的状态就是符号位的状态.
8 TF(Trap Flag)陷井标志
9 IF(Interrupt-enable Flag)中断允许标志
10 DF(Direction Flag)方向标志
11 OF(Overflow Flag)溢出标志
12
13
14
15
状态标志:CF,ZF,SF,PF,OF,AF
控制标志:DF,IF,TF
8086的字长是16位的,但其地址线是32位的.
8086处理器将1M存储器空间分成许多逻辑段(Segment),每个段的最大限为16KB. 这
样,每个存储单元就可以用"段地址:段内偏移地址"表达其准确的物理位置.
汇编程序的最后,要返回调用者,例如用:
mov ah,4ch
int 21h
好像是用来返回DOS的
否则会出现不可预料的结果,如死机或更糟.
.exit 0对应的代码是:
mov ax,4c00h
int 21h
这是利用了DOS功能调用的4ch子功能(返回DOS的功能:AH=4ch)实现的, 它的入口参
数是AL=返回数码. 通常返回0表示没有错误.
"段地址:偏移地址"的形式称为 逻辑地址 .将逻辑地址中的段地址左移4位(这是对
二进制而言,若是十六进制,只要左移一位),加上偏移地址就得到20位物理地址. 例
如逻辑地址"1460H:100H"表示物理地址14700H, 同一个物理地址可以有多个逻辑地
址形式.
存储器寻址方式
1.直接寻址方式
2.寄存器间接寻址方式
3.寄存器相对寻址方式
4.基址变址寻址方式
5.相对基址变址寻址方式
在汇编语言中,每条指令的格式一般为:
标号:指令助记符 目的操作数,源操作数;注释
它由4部分组成.标号表示该指令在主存中的址,可有可无.每个助记符就代表一种指
令.目的操作数和源操作数表示参与操作的对象.注释通常是对该指令或这段程序功
能的说明,是为了程序便于阅读加上的,不是必须有的.
指令操作数的符号说明:
r8 任意一个8位通用寄存器AH/AL/BH/BL/CH/CL/DH/DL
r16 任意一个16位的通用寄存器AX/BX/CX/DX.
reg 代表r8或r16
seg 段寄存器CS/DS/ES/SS
m8 一个8位的存储器单元(包括所有的主存寻址方式)
m16 一个16位的存储器单元(包括所有的主存寻址方式)
mem 代表m8或m16
i8 一个8位立即数
i16 一个16位立即数
imm 代表i8或i16
dest 目的操作数
src 源操作数
INTEL8086指令系统共有117个基本指令,约300个操作码,包括8080/8085的全部指令
8086的指令组可以分成6个功能组,它们是:
1.数据传送类指令(14种)
2.算术运算类指令
3.位操作类指令
4.串操作类指令
5.控制转移类指
6.处理机控制类指令
学习指令时要注意以下几个方面:
指令的功能
指令支持的寻址方式
指令对标志的影响
其它方面:如指令执行时的约定设置,必须预置的参数,隐含使用的寄存器等等
1.数据传送类指令
数据传送类指令的功能是把数据从一个位置传送到另一个位置.共14种.除志寄存器
传送指令外,该类指令均不影响标志位.
1.1通用数据传送指令 MOV,XCHG,XLAT
1.1.1传送指令MOV
MOV dest,src ;dest<-src
可以使用的寻址方式如下:
MOV reg/mem,imm ;立即数送寄存器或主存
MOV reg/mem/seg,reg ;寄存器送寄存器(包括段寄存器)或主存
MOV reg/seg,mem ;主存送寄存器(包括段寄存器)
MOV reg/mem,seg ;段寄存器送主存或寄存器
1.1.2交换指令XCHG
XCHG reg,reg/mem ;reg<->reg/mem,将源操作数与目的操作数的内容交换
1.1.3交换码指令XLAT
将BX指定的缓冲区中,AL指定的位移处的数据取出赋给AL
XLAT lable
XLAT ;al<-ds:[bx+al]
换码指令常用于将一种代码转换为另一种码,如扫描码转换为ASCII码,数字0-9转换
为7段显示码等.使用前首先在主存中建立一个字节表格, 表格的内容是要转换成的
目的代码,表格的首地址存放BX寄存器,需要转换的代码放于AL寄存器, 要求被转换
的代码应是相对表格首地址的位移量.设置好后,执行换码指令,即将AL 寄存器中的
内容转换为目标代码.
因为AL的内容实际上是距离表格首地址的位移量,只有8位, 所以表格的最大长度为
256.超过256的表格需要采用修改BX和AL的方法在能转换.
XLAT指令中没有显示指明操作数,而是默认使用BX和AL寄存器.这种默认操作数的方
法称为隐含寻址方式,指令系统中有许多指令采用隐含寻址方式.
1.2堆栈操作指令
堆栈是一个"先进后出"(FIlO Frst In Last Out)的主存区域,位于堆栈段中,使
用SS段寄存器记录其段地址.堆栈只有一个出口,即当前栈顶. 栈顶是地址较小的一
端(低端),它用堆栈指针寄存器SP指定.
堆栈有两条基本指令:进栈指令PUSH和出栈指令POP.
堆栈可用来临时存放数据,以便随时恢复它们. 堆栈也常用于在子程序传递参数.
1.2.1进栈指令PUSH
PUSH reg/mem/seg ;SP<-SP-2,SS:[SP]<-reg/mem/seg
1.2.2出栈指令POP
POP reg/seg/mem ;reg/seg/mem<-SS:[SP],SP<-SP+2
1.3标志寄存器传送指令
标志寄存器传送指令用来传送标志寄存器中的内容,它包括LAHF/SAHF, PUSHF/POPF
四条指令.
1.3.1标志送AH指令LAHF
LAHF ;AH<-FLAGS的低字节
LAHF 将AH 寄存器内容送FLAGS 的低字节, 即状态标志位SF/ZF/AF/PF/CF 分别送
入AH的第7/6/4/2/0位,而AH的第5/3/1位任意
1.3.2AH送标志指令SAHF
SAHF ;FLAGS的低字节<-AH
SAHF 将AH 寄存器内容送FLAGS 的低字节, 即根据AH 的第7/6/4/2/0 位相应设置
SF/ZF/AF/PF/CF的标志.由此可见SAHF和LAHF是一对相反功能的指令.它们只影响标
志寄存器的低8位,而对高8位无影响.
1.3.3标志进栈指令PUSHF
PUSH ;SP<-SP-2,SS[SP]<-FLAGS
1.3.4标志位出栈指令POPF
POPF ;FLAGS<-SS:[SP],SP<-SP+2
1.4地址传送指令
地址传送指令将存储器的逻辑地址传送至指令的寄存器.
1.4.1有效地址传送指令LEA
LEA r16,mem ;r16<-mem的有效地址EA
LEA指令将存储器操作数的有效地址传送至指定寄存器中.
1.4.2指针传送指令LDS
LDS r16,mem ;r16<-mem,DS<-mem+2
LDS指令将主存中mem指定的字节送至r16,拼将mem的下一字送DS寄存器. 实际上mem
指定了主存的连续4个字节作为逻辑地址,即32位地址指针
1.4.5指针传送指令LES
LES r16,mem ;r16<-mem,ES<-mem+2
LES指令和LDS指令相比,除把mem的下一个字送ES外,其他均与LDS一样.
1.5输入输出指令IN,OUT
外部设备通过I/O端中与处理器交换信息.输入指令将外设数据传送至CPU,而输出指
令OUT则将CPU数据传送至外设.8086中,只有这组指令能够实现与外设的信息交换,
并且只能利用AL/AX寄存器与I/O端口通信.
1.5.1输入指令IN
IN al,i8 ;字节输入:ALIN ax,i8 ;字节输入:AL<-I/O端口i8,AH<-I/O端口i8+1
IN al,dx ;字节输入:AL<-I/O端口[DX]
IN AX,DX ;字节输入:AL<-I/O端口[DX],AH<-I/O端口[DX+1]
1.5.2输出指令OUT
OUT i8,AL
OUT i8,AX
OUT DX,AL
OUT DX,AX
1.6算术运算类指令
算术类运算指令用来执行二进制及十进制的算术运算:加减乘除.这类指令会根据运
算结果影响状态标志FLAGS,有时要利用某些标志才能得到正确的结果.
1.6.1加法指令ADD.ADC.INC.
1.6.1.1加法指令ADD
ADD reg,imm/reg/mem ;reg<-reg+imm/reg/mem
ADD mem,imm/reg ;mem/<-mem+imm/reg
ADD按照状态标志的定义相应设置这些标志的0或1状态.
1.6.1.2带进位加法指令ADC
ADC reg,imm/reg/mem ;reg<-reg+imm/reg/mem+CF
ADC mem,imm/reg ;mem<-mem+imm/reg+CF
ADC指令除完成ADD加法运算以外, 还要加进位CF, 其用法及对状态标志的影响也与
ADD指令一样.ADC主要用于与ADD指令相结合实现多精度数相加.
1.6.1.3增量指令INC
INC reg/mem ;reg/mem<-reg/mem+1
INC指令对操作数加1(增量).
1.6.2减法指令SUB,SBB,DEC,NEG,CMP
除DEC不影响CF标志外,其它减法指令按定义影响全部状态标志位.
1.6.2.1减法指令SUB
SUB reg,imm/reg/mem ;reg<-reg-imm/reg/mem
SUB mem,imm/reg ;mem<-mem-imm/reg
1.6.2.2带借位减法指令SUB
SBB reg,imm/reg/mem ;reg<-reg-imm/reg/mem-CF
SBB mem,imm/reg ;mem<-mem-imm/reg-CF
该指令使目的操作数减去源操作数减去源操作数,还要减去借(进位)CF,结果送到目
的操作数.SBB指令主要用于与SUB指令相结合实现多精度数相减.
1.6.2.3减量指令DEC
DEC reg/mem ;reg/mem<-reg/mem-1
同INC一样,DEC指令不影响CF,但影响其它状态标志.
1.6.2.4求补指令NEG
NEG reg/mem ;reg/mem<-0-reg/mem
求补运算也可以表达成:将作数按位取反后加1. NEC 对标志的影响与用0 作减法的
SUB指令一样.
CMP reg,imm/reg/mem ;reg-imm/reg/mem
CMP mem,imm/reg ;mem-imm/reg
CMP指令减法指令SUB执行同样的操作,同样影响标志,只是不改变目的操作数. 常用
来比较两个操作数的大小关系.执行比较指令后,可以根据标志判断两个数的大小关
系等.
1.6.4乘法指令MUL和IMUL.
1.6.4.1无符号数乘法指令MUL
MUL r8/m8 ;AX<-AL*r8/m8
MUL r16/m16 ;无符号字乘DX.AX<-AX*r16/m16
MUL指令影响标志OF和CF.如果乘积的高一半(AH或DX)为0,则OF=CF=0;否则OF=CF=1
.但是,MUL指令对其它状态标志的影响没有定义,也就是成为任意的,不可预测的.注
意:不是没有影响.
1.6.4.2有符号乘法指令IMUL
IMUL r8/m8 ;有符号字节乘:AX<-AL*r8/m8
IMUL r16/m16 ;有符号字乘DX.AX<-AX*r16/m16
IMUL除计算对象是带符号的二进制以外,其他都与MUL是一样的,但计算结果不同.
IMUL指令对OF和CF的影响是:若乘积的高一半是低一半的符号扩展,则OF=CF=0;否则
均为1.IMUL对其他标志没有定义.
1.6.5除法指令DIV和IDIV.
除法指令使状态标志没有意义.
结果可能产生溢出,溢出时8086CPU中就产生编号为0的内部中断.实用中应该考虑这
个问题.
1.6.5.1无符号数除法指令DIV
DIV r8/m8 ;无符号字节除:AL<-AX除以r8/m8
;AH<-AX除以r8/m8的余数
DIV r16/m16 ;无符号字除:AX<-DX.AX除以r16/m16的商.
;DX<-DX.AX除以r16/m16的余数
1.6.5.2有符号数除法指令IDIV
IDIV r8/m8 ;同DIV
IDIV r16/m16 ;同DIV
IDIV除将操作数视为带符号的二进制数以外,其它与DIV指令均一样
1.6.6符号扩展指令
符号扩展指令指用一个操作数的符号位(即最高位)形成另一个操作数, 后一个操作
数的各位是全0(正数)或全1(负数).符号扩展指令可用来将字节转换成字,字转换成
双字.它们都不影响标志位.
1.6.6.1字节转换成字指令CBW
CBW ;AL符号扩展成AX
1.6..6.2字转换为双字指令CWD
CWD ;AX符号扩展成DX
1.6.7十进制调整指令
二进制编码的十进制数:BCD码.8086支持压缩BCD码和非压缩的BCD码,相应地十进制
调整指令分为压缩BCD码调整指令和非压缩BCD码调整指令.
十进制调整指令只针对要求BCD码运算的应用,并且要与对应的运算指令配合.
1.6.7.1压缩的BCD码(8421码)调整指令
8421码用4个二进制位表示一个十进制位, 一个字节可以表示两个十进制位, 即00
-99.
该组指令包括加法和减法的十进制调整指令DAA和DAS, 它们用来对二进制加减法指
令的执行结果进行调整,得到十进制结果.必须注意的是,在使用DAA或DAS指令之前
,应先执行加法或减法指令.
1.6.7.1.1加法的十进数调整指令DAA
DAA ;AL<-将AL中的加和调整为压缩BCD码
该指令根在以AL为目的操作数的ADD或ADC指令之后,对AL 的二进制结果进行十进制
调整,并在AL得到十进制结果.DAA指令对OF标志无定义,按其结果影响所有的其他标
志,其中CF反映压缩BCD码相加的进位状态.
1.6.7.1.2减法的十进制调整指令DAS
DAS ;AL<-将AL中的减差调整为压缩BCD码
该指令根在以AL为目的操作数的SUB或SBB指令之后,对AL 的二进制结果进行十进制
调整,并在AL得到十进制结果.DAS指令对OF标志无定义,按其结果影响所有的其它标
志,其中CF反映压缩BCD码相减的借位状态.
1.6.7.2非压缩的BCD码调整指令
非压缩BCD码用8个二进制位表示一个十进制位,实际上只是用低4个二进位表示一个
十进制位0-9,高4位任意,但通常默认为0.ASCII码中0-9的编码是30h-39h,所以0- 9
的ASCII码(高4位为0)就可以认为是非压缩BCD码.
对非压缩BCD码,8086提供了AAA,AAS,AAM,AAD四条指令,分别用于对二进制加,减,乘,
除指令的结果进行调整,以得到非压缩的BCD码表示的十进制调整结果. 由于只要在
调整后的结果中加上30h就成为ASCII码,所以这组指令实际上也是针对ASCII码的调
整指令.
1.6.7.2.1加法的非压缩BCD码调整指令AAA
AAA ;AL<-将AL中的加和调整为非压缩BCD码
;AH<-AH+调整产生的进位
该指令跟在以AL为目的操作数的ADD或ADC指令之后,对AL进行非压缩BCD码调整;
如果调整中产生了进位,则将进位1加到AH中,同时CF=AF=1;否则CF=AF=0.AAA指令对
其它标志无定义.另外,该指令使AL的高4位清0.
1.6.7.2.2减法的非压缩BCD码调整指令AAS
AAS ;AL<-将AL中的减差调整为非压缩BCD码
;AH<-AH-调整产生的借位
该指令跟在以AL为目的操作数的SUB或SBB指令之后,对AL进行非压缩BCD码调整; 如
11果调整中产生了借位,则将AH减去借位1,同时CF=AF=1;否则CF=AF=0.AAS指令对其他
标志无定义.另外,该指令使AL的高4位清0.
1.6.7.2.3乘法的非压缩的BCD码调整指令AAM
AAM ;AX<-将AX中的乘积调整为压缩BCD码
该指令跟在以AX为目的操作数的MUL指令之后,对AX进行非压缩BCD码调整. 利用MUL
相乘的两个非压缩BCD码的高4位必须为0.AMM指令根据结果设置SF,ZF 和PF, 但OF
,CF和AF无定义.
1.6.7.2.4除法的非压缩BCD调整指令AAD
AAD ;AX<-将AX中的非压缩BCD码扩展成二进制数,即
;AL<-10d*AH+AL,AH<-0
AAD调整指令与其他的调整指令应用情况不同.它是先将存放AX寄存器中的两位非压
缩BCD码数进行调整,然后再用DIV 指令除以一个非压缩BCD 码数, 这样得到非压缩
BCD码数的除法结果.其中,要求AL,AH和除数的高4位为0.AAD 指令根据结果设置SF
,ZF和PF,但OF,CF和AF无定义.
1.7位操作类指令
位操作指令对二进制数的各个位进行操作,包括逻辑运算指令和移位指令.
1.7.1逻辑运算指令AND(逻辑与),OR(逻辑或),NOT(逻辑非),XOR(逻辑异或),TEST(
测试)
AND/OR/XOR/TEST reg,imm/reg/mem
AND/OR/XOR/TEST mem,imm/reg
1.7.1.1逻辑与指令AND
AND dest,src ;dest<-dest(按位逻辑与)src
AND指令对两个操作数执行按位的逻辑与运算:即只有相"与"的两位都是1,结果才是
1;否则,"与"的结果为0.逻辑与的结果送到目的操作数.
1.7.1.2逻辑或指令OR
OR dest,src ;dest<-dest(按位逻辑或)src
1.7.1.3逻辑异或指令
XOR dest,src ;dest<-dest(按位逻辑异或)src
1.7.1.4逻辑非指令
NOT reg/mem ;reg/mem<-(按位取反)reg/mem
1.7.1.5测试指令
TEST dest,src ;dest(按位逻辑与)src
TEST指令对两个操作数执行按位逻辑与的运算,但结果不回到目的操作数.TEST指令
执行的操作与AND完全相同,但不保存执行的结果,只根据结果来设置状态标志.
TEST指令通常用于检测一些条件是否满足,但又不希望改变原操作数的情况.这条指
令之后,一般都是条件转移指令,目的是利用测试条件转向不同的程序段.
1.7.2移位指令
移位指令分成逻辑移位指令和算术移位指令,分别具有左移或右移操作.
四条(实际是3条)移位指令的目的操作数可以是寄存器或存储器单元.后一个操作数
表示移位位数,该操作数为1,表示移动一位;当移位操作数大于1时,则用CL寄存器表
示,该操作数表达为CL.
移位指令按照移入的位设置进位标志CF,根据移位后的结果影响SF,ZF,PF,对AF没有
定义.如果进行一位移动,则按照操作数的最高符号位是否改变, 相应设置溢出标志
OF:如果移位前的操作数最高位与移位后的操作数最高位不同(有变化),则OF=1; 否
则CF=0.当移位次数大于1时,OF不确定.
1.7.2.1逻辑移位指令SHL和SHR
SHL reg/mem,1/CL ;逻辑左移:reg/mem左移1/CL位,最低位补0,
;最高位进入CF
SHR reg/mem,1/CL ;逻辑右移:reg/mem右移1/CL位,最高位补0,
;最低位进入CF
1.7.2.2算术移位指令SAL和SAR
SAL reg/mem,1/CL ;算术左移,功能与SHL相同
SAR reg/mem,1/CL ;算术右移:reg/mem右移1/CL位,最高位不变
;最低位进入CF
1.7.3循环移位指令
循环移位指令按照指令功能设置进位标志CF,不影响SF,ZF,PF,AF标志.对OF 标志的
影响,循环移位指令与前面介绍的移位指令一样.
1.7.3.1不带进位循环移位指令
ROL reg/mem,1/CL ;不带进位循环左移
ROL reg/mem,1/CL ;不带进位循环右移
这两个指令不将进位标志CF纳入循环中.
1.7.3.2带进位循环移位指令
RCL reg/mem,1/CL ;带进位循环左移
RCL reg/mem,1/CL ;带进位循环右移
这两条指令将进位标志CF纳入循环位中,与操作数一起构成9位或17位二进制数一起
移位.
1.8串操作类指令
串操作类指令是一组入理主存中连续存放数据串的指令.
串操作指令中,源操作数用寄存器SI寻址,默认在数据段DS中,但允许段超越:目的操
作数用寄存器DI寻址,默认在附加段ES中,不允许段超越.每执行一次串操作指令,作
为源地址指针的SI和作为目的地址指针的DI将自动修改:+/-1(对于字节串)或+/-2
(对于字串).地址指针是增加还是减少则取决于方向标志DF.在系统初始化后或者执
行指令CLD指令后,DF=0,此时地址指针增1或2;在执行指令STD指令后,DF=1, 此时地
址指针减1或2
1.8.1串传送指令MOVS
MOVSB ;字节传送:ES:[DS]<-DS:[SI],SI<-SI+/-1
MOVSW ;字节传送:ES:[DI]<-DS:[SI],DI<-DI+/-2
串传送指令MOVS将数据段主存单元的一个字节或字,传送至附加段的主存单元中去.
助记符中字母B和W分别表示字节和字串操作.除了这两种格式外,MOVS指令还有另外
的一种格式:
MOVS 目的串名,源串名
但是为了说明是字节或字串操作,这种格式需要使用前缀word ptr或byte ptr指明.
其它串操作同样有这种格式,以下不再说明.
MOVS指令不影响标志.
1.8.2串存储指令STOS
STOSB ;字节串存储:ES:[DI]<-AL,DI<-DI+/-1
STOSW ;字串存储:ES:[DI]<-AX,DI<-DI+/-2
串存储指令将AL或AX寄存器的内容存入由DI指定的附加段主存单元中,并根据DF 和
传送单位修改DI寄存器.STOS指令不影响标志.
1.8.3串读取指令LODS
LODSB ;字节串读取:AL<-DS:[SI],SI<-SI+/-1
LODSW ;字串读取:AX<-DS:[SI],SI<-SI+/-2
LODS指令和STOS指令功能互逆.LODS指令不影响标志.
1.8.4串比较指令CMPS
CMPSB ;字节串比较:DS:[SI]-ES:[DI],SI<-SI+/-1,DI<-DI+/-1
CMPSW ;字串比较:DS:[SI]-ES:[DI],SI<-SI+/-2,DI<-DI+/-2
串比较指令的功能是比较源串与目的串是否相同,并根据其减法结果设置标志位;指
令在每次比较后修改SI和DI寄存器的值,使之指向下一元素.
1.8.5串扫描指令SCAS
SCASB ;字节串扫描:AL-ES:[DI],DI<-DI+/-1
SCASW ;字串扫描:AX-ES:[DI],DI<-DI+/-2
串扫描指令SCAS将附加段中的字节或字节内容与AL/AX寄存器内容进行比较,根据比
较结果设置标志位,每次比较后修改DI寄存器的值,使之指向下一元素.
1.8.6重复前缀指令
任何一下串操作指令,都可以在前面加一个重复前缀,以实现串操作的重复执行, 重
复数隐含在CX寄存器中.重复前缀有三种:
REP ;REP前缀用在MOVS,STOS,LODS指令前
;每执行一次串指令,CX减1;直到CX=0,重复执行结束
;当数据串没有结束,则继续传送
REPZ ;也可表达为REPE,用在CMPS,SCAS指令之前
;每执行一次串指令CX减1,并判断ZF标志是否为0
;只要CX=0或ZF=0,则重复执行结束
;当数据串没有结束,并且串相等 ,则继续比较
REPNZ ;也可表达为REPNE,用在CMPS,SCAS指令前
;每执行一次串指令,CX减1,并判断ZF标志是否为1
;只要CX=0或ZF=1,则重复执行结束
;当数据没有结束,并且串不相等,则继续比较
1.9控制转移类指令
Intel8086中,程序的执行序列是由代码段寄存器CS和指令指针IP确定的.CS 包含当
前指令所在代码段的段地址,IP则是要执行的下一条指令的偏移地址.控制转移类指
令通过修改CS和IP寄存器来改变程序的执行顺序,包括5组指令:无条件转移类指令,
循环指令,子程序指令和中断指令
1.9.1无条件转移指令
JMP label ;程序转向label标号指定的地址
JMP指令中的操作数label是要转移的目标地址,也称为目的地址,转移地址.label操
作数的寻址方法可以是直接寻址或间接寻址.
JMP指令可以将程序转移到1MB存储空间的任何位置.根据跳转的距离,JMP 指令分成
了段内转移段间转移.
段内转移是指在当前代码64KB范围内转移,因此不需要更改CS段地址,只要改变IP偏
移地址.如果转移范围可以用一个字节(-128-+127)表达,则可以形成所谓的"短转移
short jump":如果地址位移用一个16位数表达,则形成"近转移near jump",它是在
+/-32KB范围.
段间转移是指从当前代码段跳转到另一个代码段,此时需要更改CS段地址和IP 偏
移地址.这种转移也称为"远转移far jump";转移的目标地址必须用一个32位数表达,
叫做32位远指针,它应是逻辑地址.
1.9.1.1段内转移,直接寻址
JMP label ;IP<-IP+位移置
1.9.1.2段内转移,间接寻址
JMP r16/m16 ;IP<-r16/m16
1.9.1.3段间转移,直接寻址
JMP far ptr label ;IP<-label的偏移地址,CS<-label的段地址
1.9.1.4段间转移,间接寻址
JMP far ptr mem ;IP<-[mem],CS<-[mem+2]
1.9.2条件转移指令
条件转移指令JCC根据指令的条件确定程序是否发生了转移.如果满足条件, 则程
序转移到目标地址去执行程序:不满足条件,则程序将顺序执行下一指令. 其通用格
式为:
Jcc label ;条件满足,发生转移:IP<-IP+8位位移量:
;否则,顺序执行:IP<-IP+2
其中,label表示目标地址(8位位移量).因为Jcc指令2个字节, 所以顺序执行就
是指令偏移指针IP加2.条件转移指令跳转的目标地址只能用前面介绍的段内短距离
跳转.即目标地址只能是在同一段内,且在当前IP地址-128-+127个单元范围之内.这
种寻址方式由于是相对于当前IP的,所以被称为相对寻址方式.
条件转移指令不影响标志,但要利用标志.条件转移指令Jcc中的cc表示利用标
志判断条件,共有16种,如下所示
JZ/JE ZF=1 等于0/相等
JNZ/JNE ZF=0 不等于0/不相等
JS SF=1 符号为负
JNS SF=0 符号为正
JP/JPE PF=1 "1"的个数为偶
JNP/JPO PF=0 "1"的个数为奇
JO OF=1 溢出
JNO OF=0 无溢出
JC/JB/JNAE CF=1 进位/低于/不高于等于
JNC/JNB/JAE CF=0 无进位/不低于/高于等于
JBE/JNA CF=1或ZF=1 低于等于/不高于
JNBE/JA CF=0且ZF=0 不低于等于/高于
JL/JNGE SF不等于OF 小于/不大于等于
JNL/JGE SF=OF 不小于/大于等于
JLE/JNG ZF<>OF或ZF=1 不小于等于/不大于
JNLE/JG SF=OF且ZF=0 不小于等于/大于
1.9.3循环指令
循环是一种特殊的转移流程,当满足(或不满足)某条件时,反复执行一系列操作, 直
到不满足(或满足)条件为止.循环流程的条件一般是循环计数,在程序中用循环计数
来控制循环次数.循环流程可以用前面条件转移指令来实现.
8086还设计了专门的循环指令用于控制循环流程,其格式为:
LOOP label ;CX<-CX-1;若CX<>0,循环:IP<-IP+位移量
;否则,顺序执行
LOOPZ/LOOPE label ;CX<-CX-1;若CX<>0且ZF=1,循环:IP<-IP+位移量
;否则,顺序执行
LOOPNZ/LOOPNE label ;CX<-CX-1;若CX<>0且ZF=0,循环:IP<-IP+位移量
;否则,顺序执行
LOOP指令首先将CX计数CX值减1,然后判断计数值CX是否为0.CX不为0,则继续执行
循环体内的指令;CX等于0,表示循环结束,于是程序退出循环,顺序执行后面的指令
.LOOPZ和LOOPNZ指令中又要求同时ZF为1或0才进行循环, 用于判断结果是否为零或
相等,以便提前结束循环.
循环指令中的操作数label采用相对寻址方式,表示循环的目标地址,是一个8位位
移量.另外,循环指令不影响标志.
1.9.4子程序指令
子程序由主程序执行子程序调用CALL来调用; 而子程序执行完后用子程序返回指
令RET,返回主程序继续执行.CALL与RET指令均不影响标志位.
1.9.4.1子程序调用指令CALL
CALL label ;段内调用,直接寻址:SP<-SP-2,SS:[SP]<-IP,
;IP<-IP+16位位移量
CALL r16/m16 ;段内调用,间接寻址:SP<-SP-2,SS:[SP]<-IP,
;IP<-r16/m16
CALL far ptr label ;段间调用,直接寻址:SP<-SP-2,SS:[SP]<-CS,
;SP<-SP-2,SS:[SP]<-IP
;IP<-label偏移地址,CS<-label段地址
CALL far ptr mem ;段间调用,间接寻址:SP<-SP-2,SS:[SP]<-CS,
;SP<-SP-2,SS:[SP]<-IP,
;IP<-[mem],CS<-[mem+2]
根据过程伪指令, 汇编程序可以自动确定是段内还是段间调用, 同时也可以采用
near或far伪指令强制成为调用或远调用.其过程同段内或段间转移一样.
1.9.4.2子程序返回指令RET
要回到主程序,只要获得离开主程序时,由CALL指令保存于堆栈的指令地址即可,
根据子程序与主程序是否入于同一个段内,返回指令分为段内返回和段间返回.
RET ;无参数段内返回:IP<-SS:[SP],SP<-SP+2
RET i16 ;有参数段内返回:IP<-SS:[SP],SP<-SP+2
;SP<-SP+i16
RET ;无参数段间返回:IP<-SS:[IP],SP<-SP+2
;CS<-SS:[SP],SP<-SP+2
RET i16 ;有参数段间返回:IP<-SS:[SP],SP<-SP+2
;CS<-SS:[SP],SP<-SP+2,SP<-SP+i16
1.9.5中断指令
处理器收到中断信号后中止当前程充的运行,转而去执行的处理中断的子程序叫" 中
断服务程序"或"中断处理程序".当前程序被中断的地方称为"断点". 中断服务程序
执行完后应返加原来程序的断点,继续执行被中断的程序.中断提供了又一种改变程
序执行顺序的方法.
8086CPU的中断系统具有256个中断,每个中断用唯一的中断向量号标识.向量号也称
为知量号或类型号,它用一个字节表示:0-255,对应256个中断.8086的中断可以分成
外部中断和内部中断两类.
中断服务程序可以被认为是一种特殊的子程序,可以被存放在主存的任何位置.中断
服务程序的首起(起始,入口)地址,被安排在中断向量表 .
中断向量表设置在主存的最低1KB区域内,物理地址000H-3FFH.向量表从0开始, 每4
个字节(双字)对应一个中断,低字节存放中断服务程序的偏移地址IP,高字节存放其
段地址CS.中断向量号n的中断服务程序放在4*n的物理地址处.
INT i8 ;中断调用指令:产生i8号中断
IRET ;中断返回指令:实现中断返回
INTO ;溢出中断指令:若溢出标志OF=1,产生4号中断
;否则顺序执行
1.9.6系统功能调用
所有系统功能调用格式(包括ROM-BIOS)都是一样的,一般按如下四步进行:
一.在AH寄存器中设置系统功能调用号:
二.在指定寄存器中设置入口参数;
三.用INT 21H(或ROM-BIOS的中断向量号)指令执行功能调用;
四.根据出口参数分析功能调用执行情况.
下面对汇语言程序设计中常用的输入输出类功能调用予以介绍:
1.9.6.1一个字符的输出
DOS功能调用INT21H的输出字符功能:AH=02H
入口参数:DL=字符的ASCII码
该功能执行后,会在显示器当前光标位置显示给定的字符,且光标右移一个字的位置
.如按CTRL-BREAK或CTRL-C则退出.
ROM-BIOS显示器功能调用INT 10H的字符显示功能:AH=0EH
入口参数:AL=字符的ASCII码,BL=字符的颜色值(图形方式),BH=页号(字符方式).通
常使BX=0
响铃字符(07H),退格字符(08H),回车字符(0DH),换行字符(0AH)
1.9.6.2一个字符串的输出
DOS功能调用INT21H的输出字符串功能:AH=09H
入口参数:DS:DX=欲显示字符串在主存中的首地址.字符串应以$(24H)结束, 可以输
出回车(0DH)和换行(0AH)字符产生回车和换行的作用.
1.9.6.3一个字符的输入
DOS功能调用INT21H的输入字符功能:AH=01H
出口参数:AL=字符的ASCII码.调用此子程序时,若无键按下,则会一直等到按键后才
读取该键值.
ROM-BIOS键盘功能调用INT 16H的读取键值功能:AH=0
出口参数:AX=键值代码.对于标准ASCII码按键:AL=ASCII码,AH=扫描码;对于扩展按
键:AL=00H,AH=键扩展码;对于alt+小键盘数字按键,AL=ASCII码,AH=00H. 此功能与
DOS功能调用01H一样,会一直等待按键.
1.9.6.4一个字符串的输入
DOS功能调用INT 21H的输入字符串功能:AH=0AH
入口参数:DS:DX=缓冲区首地址
执行该功能调用时,用户按键,最后用回车确认.缓冲区第1字节事先填入最多要接收
的字符个数(1-255),第2字节将存放实际输入的字符个数(不包括回车符),从第3 个
字节开始存输入的字符串.实际输入的字符个数少于定义的字符时,缓冲区其余字节
填0;多于定义数时,多出的字符丢掉,且响铃.注意扩展ASCII码(如功能键)占两个字
节,第1个为0.本调用可执行全部标准键盘编辑命令; 用户按回车键结束输入, 如按
CTRL-BREAK或CTRL-C则中止.
1.9.6.5判断是否按键
DOS功能调用INT21H的键盘检测功能:AH=0BH
出口参数:AL=0,当前没有按键;AL=FFH,当前已经按键.
此功能仅判断当前是否有按下的键,设置AL后退出.
ROM-BIOS键盘功能调用INT 16H的判断按键功能:AH=1
出口参数:若标志ZF=1,则无键按下:若ZF=0,则说明有键按下,且AX=键值代码. 此功
能仅能判断是否按键,设置零标志位ZF后退出.
这两个功能都不循环等待按键.
1.10处理机控制指令
分为两类:一类是针对标志位的指令,对标志位进行设置;另一类是对CPU状态进行控
制的指令.
1.10.1标志位操作指令
这一类指令可用来对CF,DF和IF三个标志位进行设置,除影响其所设置的标志外, 均
不影响其他标志.
1.10.1.1进位标志指令
CLC ;复进位标志:CF<-0
STC ;置位进位标志:CF<-1
CMC ;求反进位标志:CF<-非CF
1.10.1.2方向标志指令
CLD ;复位方向标志DF<-0
STD ;置位方向标志:DF<-1
在串操作指令使用之前,通常应先设置方向标志,以决定SI/DI是增量还是减量.
1.10.1.3中断标志操作指令
CLI ;复位中断标志,禁止可屏蔽中断:IF<-0
STI ;置位中断标志,允许可屏蔽中断:IF<-1
许多指令的执行都会影响标志,上述指令提供了直接改变CF,DF,IF的方法.标志寄存
器中的其他标志,需要用LAHF/SAHF或PUSHF/POPF指令间接改变.
1.10.2 CUP状态控制指令
这类指令用来控制CPU的状态,使8086暂停,等待或空操作等.
1.10.2.1 空操作指令NOP
NOP
该指令不执行任何操作,但占用一个字节存储单无,空耗一个指令执行周期. 该
指令常用子程序调试.事实上,NOP和XCHG AL,AL的指令代码一样.
1.10.2.2段超越前缀指令
SEG: ;即CS:,SS:,DS:,ES:,取代默认段寄存器
1.10.2.3封锁前缀指令LOCK
LOCK ;封锁总线
这是一个指令前缀,可放在任何指令前.这个前缀使得在这个指令执行时间内, 8086
处理器的封锁输出引脚有效,即把总线封锁,使别的控制器不能控制总线; 直到该指
令执行完后,总线封锁解除.当CPU与其它处理机协同工作时,该指令可避免破坏有用
信息.
1.10.2.4暂停指令HLT
HLT ;进入暂停状态
暂停指令使CPU进入暂停状态,这时CPU不进行任何操作.当CPU 发生复位或来自外部
的中断时,CPU脱离暂停状态.
HLT指令可用于程序中等待中断.当程序中必须等待中断时,可用HLT, 而不必用软件
死循环.然后,中断使CPU脱离暂停状态,返回执行HLT的下一条指令.注意, 该指令在
PC机中将引起所谓的"死机",一般的应用程序不使用.
1.10.2.5交权指令ESC
ESC 6位立即数,reg/mem;把浮点指令交给浮点处理器
交权指令ESC把浮点指令交给浮点处理器执行.为了提高浮点运算能力,8086系统中
可加入浮点运算协处理器8087.但是,8087的浮点指令是和8086的整数指令组合在一
起的,8086主存中存储8087的操作码及其所需的操作数.当8086发现是一条浮点指令
时,就是利用ESC指令将浮点交给 8087 执行 , 6 位立即数即为浮点指令的操作码
,reg/mem指示浮点指令的操作数.当操作数为寄存器时 ,它的编码也做为操作数码;
如果为存储器操作数,CPU读出这个操作数送给协处理器.
实际写程序时,一般采用易于理解的浮点指令助记符格式.
1.10.2.6等待指令WAIT
WAIT ;进入等待状态
WAIT指令在8086的测试输入引脚为高电平无效时,使CPU进入等待状态;这时, CPU
并不做任何操作.测试为低电平有效时,CPU脱离等待状态,继续执行WAIT指令后面的
指令.
浮点指令经由8086CPU处理发往8087,并与8086本身的整数指令在同一个指令序列
;而8087执行浮点指令较慢,所以8086必须与8087保持同步.8086就是利用WAIT 指令
和测试引脚实现与8087同步运行.