§3.3.0 8086指令系统
本节概述
指令是计算机所能识别和执行的指示和命令,指令在计算机上执行时,控制器根据指令的要求,控制计算机的各部件协调工作。
目标程序不能被操作系统装入和执行,为了让操作系统装入和执行,必须把目标程序连接为操作系统下的可执行文件,连接过程一般使用连接程序Link.EXE来完成。
教学目标
熟练掌握8086指令系统中的各种数据操作指令,并能编写自己的程序。
学习内容
概述
数据传送指令
算术运算指令
逻辑运算、移位、循环指令
控制转移指令
串操作指令
中断指令
处理控制指令
重点难点
1、指令的运用
2、程序的编写
关键字
指令
参考资料
1、《微型计算机技术及应用》,戴梅萼等编著,第二版,清华大学出版社
2、《微型计算机原理》,季维法等编著,第一版,电子科技大学出版社
3、《微型计算机原理—常见题型解析及模拟题》,武自芳主编,西北工业大学出版社
4、《80X86/80X87汇编语言程序设计》,洪志全等编著,电子科技大学出版社
§3.3.1 概述
指令是计算机所能识别和执行的指示和命令,指令在计算机上执行时,控制器根据指令的要求,控制计算机的各部件协调工作。CPU能够直接执行的指令,也是用二进制编码表示的,称为机器指令,这种语言称为机器语言。机器语言不便于编程,在编程时,一般用助记符来代表机器指令,
用助记符编写的程序,称为"汇编语言源程序",汇编语言源程序(文件扩展名ASM)需要翻译为机器指令表示的目标程序(文件扩展名OBJ),这一翻译过程称为"汇编",一般使用称为"汇编程序"的程序来进行翻译。典型的汇编程序如MicrosoftMASM 5.0。
目标程序不能被操作系统装入和执行,为了让操作系统装入和执行,必须把目标程序连接为操作系统下的可执行文件,如DOS及Windows下的可执行文件扩展名为EXE或COM。连接过程一般使用连接程序Link.EXE来完成。
汇编语言指令与机器指令间有一一对应关系,可以充分发挥CPU的性能,如图3-7。
另外,使用高级语言编写的源程序,必须通过"编译"、"连接"形成可执行文件,如图3-8。
能够直接执行的机器指令,用二进制编码表示。在Intel 系列CISC(复杂指令集计算机)CPU中,机器指令的长度为1~6字节。
OP:操作码字段,6位,规定该指令的操作性质,如图3-9。
D: 方向位。D=0, REG为源操作数; D=1,REG为目的操作数。
W: 操作数大小. W=0, 操作数为字节; W=1, 操作数为字。
REG: 寄存器编码如下表:
MOD: 方式字段
MOD=11, 寄存器方式, 两个操作数均在寄存器中,第一个寄存器由REG字段给出, 第二寄存器由R/M字段给出,R/M的编码与REG同.
MOD=00、01、10:存储器方式,有一个操作数在存储器中,存储器的有效地址由R/M字段给出:(D8=8位常数,D16=16位常数)如下表所示。
§3.3.2 数据传送指令
传送指令执行寄存器、存储器、I/O接口电路、堆栈、地址的传送。有效的传送路径及方向如图3-10。
1、 通用型传送指令
(1) MOV
一般格式: "MOV dst,src"
dst=目标(destination),src=源(source)
传送(move)的实质是复制(copy),即传送后,src中的值不变,。
注意:① 上图中未标明的路径均是非法的。
② 不能给CS或IP赋值。
③ 常数不能直接赋给段寄存器。
(2) 堆栈操作
堆栈(STACK)是一段连续的内存,用于暂存数据,例如,可以把寄存器中的值暂存在堆栈中,需要时再取回到寄存器;在子程序和中断处理程序中,通常需要把寄存器中的值暂存在堆栈中。在子程序调用和中断发生时,返回的断点地址也保存在堆栈中。 堆栈段的基地址保存在SS寄存器中,堆栈的大小等于SP的初值。堆栈操作过程中,SP指向数据所在单元(称为"栈顶")。
堆栈操作有两条指令,PUSH和POP。
PUSH:把寄存器或存储器中的16位数值存入堆栈,。
把数据存入堆栈称为"推入"或"入栈"。向堆栈中存入数据 时,SP的值减少,称堆栈具有"下推式"的特点。
POP:把堆栈中SP处的16位数取至寄存器或内存中。
把数据从堆栈中取出称为"弹出"或"出栈"。
堆栈操作指令PUSH/POP只能进行16位数(字)操作,且遵从"先进后出"原则,操作过程如图3-11所示。
使用堆栈还应注意"溢出"问题。
(3) 交换指令XCHG
把两个操作数的值相交换(Exchange)。
(4) 翻译指令XLAT
格式:XLAT 原始表
或:XLAT ;形式上无操作数
功能:查找一个字节表格中某一项的值。表格的名字(表示表格的起始地址)放在BX寄存器中,所查找项相对于表格起始地
址的偏移量放在AL中;该指令执行后,AL等于所查找项的值。
注意,即使使用"XLAT tab"格式,也必须把tab的偏移量放在BX中。
2、 输入输出型传送指令
CPU与外部设备之间必须通过"I/O接口电路"连接。8086的I/O接口电路,其主要作用是完成CPU与外部设备间的信息传送。CPU把信息直接送给外部设备对应的I/O接口电路,由I/O接口电路负责把信息送给外部设备。或者,外部设备把信息送入对应的I/O接口电路,CPU从I/O接口电路中读取信息。
从编程的角度看,I/O接口电路由一些"端口"(PORT)构成,CPU把信息直接送给外部设备对应的端口,由端口负责把信息送给外部设备。或者,外部设备把信息送入对应的端口,CPU从端口中读取信息。
8086CPU采用"端口寻址方式",即端口地址与存储器地址单独编号,使用专用的输入输出指令,在端口与AL或AX寄存器之间传送信息。端口地址范围是0000~FFFFH,每个端口可以存放8位二进制数,称为"8位端口"。
输入输出指令有两个:IN(输入)、OUT(输出)。
IN指令:把端口的值输入到AL或AX寄存器中。
OUT指令:AL或AX寄存器中的值输出到端口。
IN/OUT指令有两种用法:
用法一:端口地址以常数给出,适用于端口地址00~FFH。
用法二:端口地址放在DX寄存器中,适用于端口地址0000~FFFFH。
3、 地址传送型指令
这类指令用于处理存储器地址。如果一个存储单元的值是另一个存储单元的地址,该存储单元被称为"指针"(Pointer)。
存储单元P的地址是1000H,存储单元X的地址是2000H,P中的值等于X的地址2000H,称为P指向X,或者说P是X的指针如图3-12所示。指针P仅包含X的地址偏移量(2字节),是一个"近指针"(Near型指针)。
指针FP包含Y的段地址和偏移量(4字节),是一个"远指针"(Far型指针)。其中偏移量放在前2字节,段地址放在后2字节如图3-13所示。
(1)LEA指令(装入有效地址,Load Effective Addres)
LEA把内存数据的有效地址(地址偏移量,16位)送到一个16位通用寄存器。
(2) LDS指令(装入有效地址和DS寄存器)
LDS 把内存数据的段地址送DS,偏移量送另一个16位通用寄存器。
(3)LES指令(装入有效地址和ES寄存器)
LES 把内存数据的段地址送ES, 偏移量送另一个16位通用寄存器。
4、 标志传送型指令
标志传送指令用于读出标志寄存器(FLAG 或称PSW)的内容,或设置标志寄存器新的值,如图3-14所示。
(1)LAHF (Load AH with Flag) 将标志寄存器的值装入AH(读出标志寄存器的值)。
(2)SAHF (Save AH into Flag) 将AH的值装入标志寄存器(设置新的标志)。
(3)PUSHF,POPF PUSHF:
① SP减2
② 将FLAG的值存入堆栈中SP处,FLAG中的值保 持不变
POPF: ① 从堆栈中SP处取出一字送到FLAG
② SP加2
§3.3.3 算术运算指令
8086提供了加、减、乘、除四种基本算术运算,这些运算都可对字节或字进行运算,既可以对无符号数运算,也可对有符号数运算。无符号数和有符号数的加、减法运算使用相同的指令。乘、除运算中,无符号数和有符号数运算使用不同的指令。
1、 加法
(1) 加法的一般格式
ADD dst,src
功能:dst ←dst+src,源操作数与目的操作数相加,和放在目的操作数中。
(2) 带进位的加法
ADC dst,src
功能:dst←dst+src+CF,源操作数与目的操作数相加,并考虑上一次加法的进位,和放在目的操作数中。
(3) 加1指令 INC dst 功能:dst ←dst+1
2、 减法
(1) 减法的一般格式 SUB dst,src 功能:dst ←dst-src
(2) 带进位的减法 SBB dst,src
功能:dst←dst-src-CF,考虑上一次减法的借位。(上一次减法 的借位在CF中)
(3) 减1指令 DEC dst 功能:dst←dst - 1
(4) 求补指令 NEG dst 功能:dst ←0-dst
(5) 比较指令
CMP dst,src
功能:比较dst和src的大小,比较的结果放在标志位中。
该指令采用"dst-src"的算法实现比较,但相减后的差不送给dst。 条件转移指令(如JG,大于时转移;JNZ,当ZF=0时转移
可以直接利用比较指令的比较结果。(条件转移指令后述)
3、 乘法
无符号数的乘法(MULtiplication)用MUL指令, 有符号数的乘法用IMUL指令(有符号数又称整数INTEGER)。 8086CPU可执行两个8位数相乘,或两个16位数相乘,如图3-15所示。
指令格式为:
MUL 操作数
IMUL 操作数
指令形式上只给出一个操作数(被乘数),但乘数和积是固定存放的。
如:无符号数的乘法
MUL BL ;AL × BL → AX
MUL CX ;AX × CX → DX AX (DX为高16位)
有符号数的乘
IMUL BYTE PTR [DI] ; AL乘内存中的一字节值 ,
; 该内存的地址由DI的值指出。积存放在AX中。
IMUL WORD PTR [DI] ;AX乘内存中的一个字, ;该字的地;址由DI的值指出。积存放在DX和AX中。
注意:(1) 乘法指令的形式操作数不能为立即数;
(2) MUL∕IMUL指令执行后,设置CF和OF标志,但AF,PF,SF,ZF的值不确定,这四个标志无意义。
MUL指令:积的高一半为零,则CF=OF=0,否则,CF=OF=1。
IMUL指令:积的高一半是低一半的符号扩展,则CF=OF=0, 否则,CF=OF=1。
4、 除法
无符号数的除法(DIVision)用DIV指令,
有符号数的除法用IDIV指令 8086CPU可执行16位/8位,或32位/16位,如图3-16所示。
指令格式为:
DIV 操作数
IDIV 操作数
指令形式上只给出一个操作数(除数),但被除数、商和余数是固定存放的。
注意:
(1) DIV∕IDIV指令执行后,所有状态标志(CF,OF,AF,PF,SF,ZF)的值不确定,都无意义。
(2) DIV∕IDIV指令执行后,如果商超出了范围(除数很小,极限为0),即除法溢出(或称商溢出),不使溢出标志置1。此时,CPU产生"0号中断"(除数为零中断)。
(3) 有符号数除法,可能产生两种正确结果:如
(-30)/(+8)= -4 余 +2 (余数的符号与被除数不同)
(-30)/(+8)= -3 余 -6 (余数的符号与被除数相同)
IDIV指令取第二种结果。
数的扩展
(1)概念
数的扩展是指增加数的位数。如,把8位数扩展为16位数,或把16位数扩展为32位数,扩展后的数在数值上与原数相等。
(2)必要性
在乘法前,如果参与运算的乘数和被乘数不满足"8位×8位"或不满足"16位×16位",则需将其中一个数扩展。如:参与乘法的两个数为"8位×16位",应将其中的"8位"数扩展为"16位"数,变成"16位×16位"运算。
在除法前,如果参与运算的除数和被除数不满足"16位/8位"或不满足"32位/16位",则需将被除数扩展。
如果 原除法为"8位/8位",应将被除数扩展为16位,变成"16位/8位"运算。
如果 原除法为"16位/16位",应将被除数扩展为32位,变成"32位/16位"运算。
(3)扩展方法
无符号数的扩展:
8位→16位,只需把高8位清零。如把AH清零,使AL(8位)扩展为AX(16位)。
16位→32位,只需把高16位清零。如把DX清零,使AX(16位)扩展为DXAX(32位)。
有符号数的扩展:
使用扩展指令。
CBW指令(Convert Byte to Word):把AL(Byte,8位)扩展为AX(Word,16位)。
CWD指令(Convert Word to Double Word):把AX(Word,16位)扩展为DXAX(Double Word,32位)。
有符号数的扩展采用"符号扩展"方法,如: 0111 1111B (符号位为0)→0000 0000 0111 1111B (扩展部分全为0) 1000 1111B (符号位为1)→1111 1111 1000 1111B (扩展部分全为1)
5、 十进制数的运算
(1)BCD码的概念
在计算机中,十进制数用二进制编码表示,称为BCD码(Binary Coded Decimal),又称"二--十进制码"。十进制有0~9 十个数码,可用四位二进制码来表示,如:
有两种BCD码:组合BCD码和非组合BCD码.
组合的BCD码:用一字节(8位)表示两位BCD码。因此,一字节能表示的组合BCD码范围是0~99。组合的BCD码又称"压缩的BCD码"(packed BCD format)或"组合十进制数"。
如:一字节0101 0110B (56H)表示组合BCD码56。
非组合的BCD码:用一字节(8位)的低4位表示一位BCD码,高4位为0。因此,一字节能表示的非组合BCD码范围是0~9。非组合的BCD码又称"非压缩的BCD码"(unpacked BCD format)或"分离十进制数"、"非压缩十进制数"。
如:一字节0000 0111B (07H)表示非组合BCD码7。 非组合的BCD码 类似于 数字0~9的ASCII码。非组合的BCD码高4位为0000B,ASCII码的高4位为0011B。
如: 数字7
非组合的BCD码=00000111B
ASCII=00110111B
数字7 BCD码运算的优点:当数据含有小数时,用BCD码运算不会引入截断误差,而用二进制运算会引入截断误差。如12.34的二进制表达: 1100.0101 0111 0000 101…,用有限位数表达,必然引入截断误差。
由于BCD码运算不会引入截断误差,常用于会计软件。另外,在工业控制中,BCD码常用于表示拨号开关位置代表的数值。
(2) BCD码的运算
BCD码的运算方式:ADD,SUB,MUL,DIV等指令是用于运算二进制数的,不能直接用于运算BCD码。要对BCD码进行运算,可采用两种方式:
①设置一套专用于BCD码的指令
②利用二进制运算指令和十进制调整指令
8086CPU采用第二种方式,即利用二进制指令和十进制调整指令。
十进制调整指令:
DAA:Decimal Adjust for Addition,加法的十进制调整指令。
DAS:Decimal Adjust for Subtraction,减法的十进制调整指令。
AAA:ASCII Adjust for Addition,加法的ASCII调整指令。
AAS:ASCII Adjust for Subtraction,减法的ASCII调整指令。
AAM:ASCII Adjust for Multiply,乘法的ASCII调整指令。
AAD:ASCII Adjust for Division,除法的ASCII调整指令。
这里,使用术语"十进制"(Decimal)表示 组合的BCD码,
使用术语"ASCII"表示 非组合的BCD码。
使用二进制运算指令对BCD码进行运算,必须同时使用十进制调整指令进行调整,因为:
① 4位二进制表示的范围是0~9,A,B,C,D,E,F, BCD码只允许0~9。
② 4位二进制运算逢十六进一,而BCD码逢十进一。
(3)BCD码的加法
对BCD码做加法运算,每次只能运算一字节(2位组合BCD码或1位非组合BCD码),首先,使用二进制运算指令ADD/ADC,并将结果存于AL中,然后,对AL的值进行调整(DAA或AAA)。
DAA指令把AL中的值调整为组合BCD码,并存于AL中。
AAA指令把AL中的值调整为非组合BCD码,并存于AX中(AH高位)。
结论:用二进制指令运算BCD码时,必须同时使用调整指令,组合BCD码加法和非组合BCD码加法的调整方法是 "加6调整"。即:当4位二进制码超过9时,或有辅助进位(AF=1)时,调整指令DAA/AAA指令把二进制运算指令ADD/ADC的结果加6。
(4)BCD码的减法
对BCD码做减法运算,每次只能运算一字节(2位组合BCD码或1位非组合BCD码),首先,使用二进制运算指令SUB/SBB,并将结果存于AL中,然后,对AL的值进行调整(DAS或AAS)。
DAS指令把AL中的值调整为组合BCD码,并存于AL中。
AAS指令把AL中的值调整为非组合BCD码,并存于AX中(AH高位)。
结论:用二进制指令运算BCD码时,必须同时使用调整指令,组合BCD码减法和非组合BCD码减法的调整方法是:"减6调整"。即:当4位二进制码超过9时,或有辅助进位(AF=1)时,调整指令DAS/AAS指令把二进制运算指令SUB/SBB的结果减6。
(5)BCD码的乘法和除法
(一)乘法
只能对非组合的BCD码做乘法运算,且每次只能运算一字节(1位非组合BCD码),首先,使用二进制运算指令MUL按二进制运算,然后,使用AAM指令把结果调整为非组合BCD码。
(二)除法
只能进行2位非组合的BCD码(被除数,放在AX中)除以1位非组合的BCD码运算。首先,使用调整指令AAD把被除数调整为二进制。然后,使用二进制运算指令DIV按二进制相除,在AL中获得商的二进制形式,在AH中获得余数的二进制形式。最后,用AAM指令把商调整为非组合BCD码,存于AX中。