微机 —— 8086/8088 指令系统
8086/8088 指令系统
指令系统:计算机是通过执行指令来完成用户的特定人如,因此每种计算机都有一组指令集供用户使用,这组指令集就称为计算机的指令系统。
一、8086/8088 指令格式
8086/8088指令系统采用了一种灵活的、由1~6个字节组成的变字长的指令格式,包括操作码、寻址方式以及操作数三个部分。
8086/8088 不同字长的指令码格式:
操作码/寻址方式字节格式:
第一字节中,W指示操作数类型
W=0为字节,W=1为字;
D指示操作数的传送方向:D=0表示寄存器操作数为源操作数,D=1表示寄存器操作数为目的操作数。
第二字节指出所用的两个操作数存放的位置,以及存储器中操作数偏移地址的计算方法。
(1)REG字段规定一个寄存器操作数
它作为源操作数还是目的操作数已由第一字节中的D位规定。
(2)MOD字段用来区分另一个操作数在寄存器中(寄存器寻址)还是在存储器中(存储器寻址)。
在存储器寻址的情况下,还用来指出该字节后面有无位移量,有多少位位移量
(3)R/M字段受MOD字段控制,R/M则指出如何计算存储器中操作数的偏移地址
MOD=11为寄存器方式,R/M字段将指出第二操作数所在的寄存器编号;
MOD=00,01,10为存储器方式
二、8086/8088 的寻址方式
操作数
1、 数据操作数
这类操作数是与数据有关的操作数,即指令中操作的对象是数据。数据操作数又可分为:
(1) 立即数操作数。指令中要操作的数据包含在指令中。
(2)寄存器操作数。指令中要操作的数据存放在指定的寄存器中。
(3)存储器操作数。指令中要操作的数据存放在指定的存储单元中。
(4)I/O操作数。指令中要操作的数据来自或送到I/O端口。
2、 地址操作数
这类操作数是与程序转移地址有关的操作数,即指令中操作的对象不是数据,而是要转移的目标地址。
它也可以分为立即数操作数、寄存器操作数和存储器操作数,即要转移的目标地址包含在指令中,或存放在寄存器中,或存放在存储单元之中。
对于数据操作数,有的指令有两个操作数:一个称为源操作数,在操作过程中其值不改变;另一个称为目的操作数,操作后一般被操作结果代替。有的指令只有一个操作数,或没有(或隐含)操作数。
对于地址操作数,指令只有一个目的操作数,它是一个供程序转移的目标地址。
寻址方式
可参见另一篇文章 微机中的主要寻址方式
三、8086/8088 指令系统
1、数据运算指令
数据传送指令是程序中使用最频繁的指令。
数据传送指令按其功能的不同,可以分为
(1)通用数据传送指令
通用数据传送指令又分为:
数据传送指令MOV:指令实现的操作是将源操作数送给目的操作数
指令格式及操作:
MOV dst,src ;(dst)←(src)
dst表示目的操作数,src表示源操作数(下同)。
这种传送实际上是进行数据的“复制”,源操作数本身不变
源操作数可以是存储器、寄存器、段寄存器和立即数;
目的操作数可以是存储器、寄存器(不能为IP)和段寄存器(不能为CS)
>>>必须注意,不能用一条MOV指令实现以下传送:
① 存储单元之间的传送。
我们可以用CPU的内部寄存器为桥梁来解决这个问题
MOV AL, AREA1
MOV AREA2, AL
② 立即数至段寄存器的传送。
③ 段寄存器之间的传送。
需说明一点,对于代码段寄存器CS和指令指针寄存器IP,通常无需用户利用传送指令改变其中的内容。但是CS可以作为源操作数。
堆栈操作指令:PUSH 和 POP :堆栈操作指令中的操作数类型必须是字操作数,即16位操作数。
压入堆栈指令PUSH (PUSH word onto stack)
指令格式及操作:
PUSH src ;(SP)←(SP)−2,((SP)+1:(SP))←(src)
指令完成的操作是“先移后入”,即先将堆栈指针SP减2,使SP始终指向栈顶,然后再将操作数src压入(SP)+1和(SP)两个存储单元中
指令中的操作数src可以是通用寄存器和段寄存器,也可以是由某种寻址方式所指示的存储单元,但不能是立即数
弹出堆栈指令POP (POP word off stack)。
指令格式及操作:
POP dst ;(dst)←((SP)+1:(SP)),(SP)←(SP)+2
指令完成的操作是“先出后移”,即先将堆栈指针SP所指示的栈顶存储单元的值弹出到操作数dst中,然后再将堆栈指针SP加2,使其指向栈顶。
指令中的操作数dst可以是存储器、通用寄存器或段寄存器(但不能是代码段寄存器CS),同样也不能是立即数。
数据交换指令XCHG:段寄存器的内容不能参加交换
指令格式及操作:
XCHG dst,src ;(dst)←→(src)
该指令的操作是使源操作数与目的操作数进行交换,即不仅将源操作数传送到目的操作数,而且同时将目的操作数传送到源操作数。
交换指令的源操作数和目的操作数各自均可以是寄存器或存储器,但不能二者同时为存储器
字节转换指令XLAT
指令格式及操作:
XLAT src_table ;(AL)←((BX)+(AL))
执行XLAT指令后,表中指定序号的元素存于AL。由于需要将元素的序号送AL寄存器,所以被寻址的表的最大长度为255个字节。
这是一种特殊的基址变址寻址方式,基址寄存器为BX,变址寄存器为AL。
(2)输入输出指令
输入指令IN用于从外设端口读入数据,输出指令OUT则向端口发送数据
无论是读入的数据或是准备发送的数据都必须放在寄存器AL(字节)或AX(字)中。
输入输出指令可以分为两大类:
一类是端口直接寻址的输入输出指令;另一类是端口通过DX寄存器间接寻址的输入输出指令。
在直接寻址的指令中只能寻址256个端口(0~255),而间接寻址的指令中可寻址64 K个端口(0~65535)
输入指令IN:
① 直接寻址的输入指令
指令格式及操作:
IN acc,port ;(acc)←(port)
指令中直接给出端口地址(地址小于0FFH),其功能为从指令中直接指定的端口中读入一个字节或一个字送AL或AX。
② 间接寻址的输入指令
指令格式及操作:
IN acc,DX ;(acc)←((DX))
此指令是从DX寄存器内容指定的端口中将8/16位数据送入AL/AX中
这种寻址方式的端口地址由16位地址表示,执行此指令前应将16位地址存入DX寄存器中。
输出指令OUT
① 直接寻址的输出指令
指令格式及操作:
OUT port,acc ;(port)←(acc)
此指令将AL(8位)或AX(16位)中的数据输出到指令指定的I/O端口,端口地址应不大于FFH。
② 间接寻址的输出指令
指令格式及操作:
OUT DX,acc ;((DX))←(acc)
此指令将AL(8位)或AX(16位)中的数据输出到由DX寄存器内容指定的I/O端口中
(3)目标地址传送指令
**取有效地址指令LEA **:LEA指令将一个近地址指针写入到指定的寄存器
指令格式:
LEA reg16,mem
指令中的目的操作数必须是一个16位通用寄存器,源操作数必须是一个存储器操作数,指令的执行结果是把源操作数的有效地址,即16位偏移地址传送到目标寄存器。
地址指针装入DS指令LDS:用于写入远地址指针
指令格式:
LDS reg16,mem32
源操作数是存储器操作数,目的操作数可以是任一个16位通用寄存器。
LDS传送一个32位的远地址指针,其中包括一个偏移地址和一个段地址,前者送指令中指定的寄存器(目的操作数),后者送数据段寄存器DS
**地址指针装入ES指令LES **:用于写入远地址指针
指令格式:
LES reg16,mem32
LES指令与LDS类似,也是装入一个32位的远地址指针
位移地址送指定寄存器,但是,段地址送附加段寄存器ES
目标地址传送指令常常用于在串操作时建立初始的地址指针
(4)标志传送指令等四组
取标志指令LAHF
指令格式:
LAHF
LAHF指令将标志寄存器FLAGS中的5个状态标志位SF、ZF、AF、PF以及CF分别取出传送到累加器AH的对应位,
置标志指令SAHF
指令格式:
SAHF
SAHF指令的传送方向与LAHF相反,将AH寄存器中的第7、6、4、2、0位分别传送到标志寄存器的对应位。
标志压入堆栈指令PUSHF
指令格式及操作:
PUSHF ;(SP)←(SP)−2,((SP)+1):(SP))←(FLAGS)
PUSHF指令先将SP减2,然后将标志寄存器FLAGS的内容(16位)压入堆栈。这条指令本身不影响状态标志位
标志弹出堆栈指令POPF
指令格式及操作:
POPF ;(FLAGS)←((SP)+1:(SP)),(SP)←(SP)+2
POPF指令的操作与PUSHF相反,它将堆栈内容弹出到标志寄存器,然后SP加2。
POPF指令对状态标志位有影响,使各状态标志位恢复为压入堆栈以前的状态。
PUSHF指令可用于调用过程时保护当前标志寄存器的值,过程返回以后再使用POPF指令恢复标志寄存器原来的值。
数据传送指令除了SAHF和POPF外都不影响状态标志位。
2、算术运算指令(20条)
8086/8088的算术运算指令可以处理四种类型的数:无符号的二进制数、带符号的二进制数、无符号的压缩十进制数(压缩型BCD码)和无符号的非压缩十进制数(非压缩型BCD码)
(1)加法指令(影响状态标志位)
(1)不带进位加法指令ADD : ADD dst,src ;(dst)←(dst)+(src)
ADD指令将目的操作数与源操作数相加,并将结果送给目的操作数
(2)带进位加法指令ADC : ADC dst,src ;(dst)←(dst)+(src)+(CF)
ADC指令是将目的操作数与源操作数相加,再加上进位标志CF的内容,然后将结果送给目的操作数
(3)加1指令INC :INC dst ;(dst)←(dst)+1
INC指令将目的操作数加1,并将结果送回目的操作数。
带进位加法指令主要用于多字节数据的加法运算
INC指令将影响状态标志位,如SF、ZF、AF、PF和OF,但对进位标志CF没有影响
INC指令中目的操作数可以是寄存器或存储器,但不能是立即数和段寄存器。其类型为字节操作或字操作均可
(2)减法指令(影响状态标志位)
(1) 减法指令SUB: SUB dst,src ;(dst)←(dst) − (src)
SUB指令将目的操作数减源操作数,结果送回目的操作数。
(2)带借位减法指令SBB: SBB dst,src ;(dst)←(dst)-(src)-(CF)
SBB指令是将目的操作数减源操作数,然后再减进位标志CF,并将结果送回目的操作数
(3)减1指令DEC: DEC dst ;(dst)←(dst) −1
DEC指令将目的操作数减1,结果送回目的操作数
(4)求补指令NEG: NEG dst ;(dst)←0 − (dst)
NEG指令的操作是用“0”减去目的操作数,结果送回原来的目的操作数。
求补指令对状态标志位有影响
(5)比较指令CMP: CMP dst,src ;(dst) − (src)
CMP指令将目的操作数减源操作数,但结果不送回目的操作数
DEC指令对状态标志位SF、ZF、AF、PF和OF有影响,但不影响进位标志CF
(3)乘法指令
(1)无符号数乘法指令MUL :
MUL src ;(AX)←(AL) x (src) (字节乘法)
;(DX:AX)←(AX) x (src) (字乘法)
MUL指令对状态标志位CF和OF有影响,SF、ZF、AF和PF不确定
(2)带符号数的乘法IMUL :
IMUL src ;(AX)←(AL) x (src) (字节乘法)
;(DX:AX)←(AX) x (src) (字乘法)
IMUL指令进行带符号数乘法,指令将两个操作数均按带符号数处理
8位和16位带符号数的取值范围分别是−128~+127和−32768~+32767。
如果乘积的高半部分仅仅是低半部分符号位的扩展,则状态标志位(CF)=(OF)=0;否则,高半部分包含乘积的有效数字而不只是符号的扩展,则(CF)=(OF)=1
(4)除法指令
(1)无符号数除法指令DIV :
DIV src ;(AL)←(AX)/(src)的商 (字节除法)
;(AH)←(AX)/(src)的余数
;(AX)←(DX:AX)/(src)的商 (字除法)
;(DX)←(DX:AX)/(src)的余数
即字节除法中,AX除以src,被除数为16位,除数为8位,执行DIV指令后,商在AL,余数在AH中;
字除法中,DX:AX除以src,被除数为32位,除数为16位。除的结果,商在AX,余数在DX中
(2)带符号数除法指令IDIV:
IDIV src ;(AL)←(AX)/(src)的商 (字节除法)
;(AH)←(AX)/(src)的余数
;(AX)←(DX:AX)/(src)的商 (字除法)
;(DX)←(DX:AX)/(src)的余数
执行IDIV指令时,如除数为0,或字节除法时AL寄存器中的商超出−128~+127的范围,或字除法时AX寄存器中的商超出−32 768~+32 767的范围,则自动产生一个类型为0的中断。
IDIV指令对状态标志位的影响以及指令中操作数的类型与DIV指令相同。
(5)符号扩展指令(不影响状态标志位)
(1)字节扩展指令CBW:
CBW ;如果(AL)<80H,则(AH)←00H,否则(AH)←0FFH
CBW指令将一个字节(8位)按其符号扩展成为字(16位)。
它是一个隐含操作数的指令,隐含的操作数为寄存器AL和AH
(2)字扩展指令CWD :
CWD ;如果(AX)<8000H,则(DX)←0000H,否则(DX)←FFFFH
CWD指令将一个字(16位)按其符号扩展成为双字(32位)。
它也是一个隐含操作数指令,隐含的操作数为寄存器AX和DX。
(6)十进制(BCD码)运算指令
在进行十进制数算术运算时,应分两步进行:
先按二进制数运算规则进行运算,得到中间结果;
再用十进制调整指令对中间结果进行修正,得到正确的结果。
AAA 非压缩性BCD码加法调整指令
DAA 压缩性BCD码加法调整指令
AAS 非压缩性BCD码减法调整指令
DAS 压缩性BCD码减法调整指令
AAM 非压缩性BCD码乘法调整指令
AAD 非压缩性BCD码除法调整指令
3、位操作指令
(1)逻辑运算指令(NOT不影响状态标志位,其他均影响)
(1)AND 逻辑“与” 按位进行与(都真才为真)
AND指令可以用于屏蔽某些不关心的位,而保留另一些感兴趣的位
(2)TEST 测试
TEST指令的操作实质上与AND指令相同,即把目的操作数和源操作数进行逻辑“与”运算。
二者的区别在于TEST指令不把逻辑运算的结果送回目的操作数,只将结果反映在状态标志位上
TEST指令常常用于位测试,它与条件转移指令一起,共同完成对特定位状态的判断,并实现相应的程序转移
(3)OR 逻辑“或” 按位进行或(有真即真)
OR指令的一个常见的用途是将寄存器或存储器中某些特定的位设置成“1”
(4)XOR 逻辑“异或” 按位进行异或(一真一假才为真)
XOR指令将目的操作数和源操作数按位进行逻辑“异或”运算,并将结果送回目的操作数
XOR指令的一个用途是将寄存器或存储器中某些特定的位“求反”,而使其余位保持不变
XOR指令的另一个用途是将寄存器的内容清零,
(5)NOT 逻辑“非”
NOT指令的操作数可以是8位或16位的寄存器或存储器,但不能对一个立即数执行逻辑“非”操作
(2)移位指令
(1) 逻辑左移/算数左移指令SHL/SAL:
SHL dst,1/SAL dst,1 或 SHL dst,CL/SAL dst,CL
这两条指令的操作是将目的操作数顺序向左移1位或移CL寄存器指定的位数。
左移1位时,操作数的最高位移入进位标志CF,最低位补0。
SHL/SAL指令将影响CF和OF两个状态标志位
(2) 逻辑右移指令SHR :
SHR dst,1/CL
SHR指令的操作是将目的操作数顺序向右移1位或移CL寄存器指定的位数。
逻辑右移1位时,操作数的最低位移到进位标志CF,最高位补0
SHR指令也将影响CF和OF状态标志位
(3)算术右移指令SAR:
SAR dst,1/CL
SAR指令的操作数与逻辑右移指令SHR有点类似,即将目的操作数向右移1位或移CL寄存器指定的位数,操作数的最低位移到进位标志CF。
SAR与SHR指令的主要区别是,算术右移时,最高位保持不变。
(3)循环移位指令
(1)循环左移指令ROL :
ROL dst,1/CL
ROL指令将目的操作数向左循环移动1位或移CL寄存器指定的位数。
最高位移到进位标志CF,同时最高位移到最低位形成循环,进位标志CF不在循环回路之内。
(2)循环右移指令ROR式:
ROR dst,1/CL
ROR指令将目的操作数向右循环移动1位或移CL寄存器指定的位数。
最低位移到进位标志CF,同时最低位移到最高位。
(3)带进位循环左移指令RCL (Rotate Left through Carry)。指令格式:
RCL dst,1/CL
RCL指令将目的操作数连同进位标志CF一起向左循环移动1位或移CL寄存器指定的位数。
最高位移入CF,而CF移入最低位
(4)带进位循环右移指令RCR :
RCR dst,1/CL
RCR指令将目的操作数与进位标志CF一起向右循环移动1位或移CL寄存器指定的位数。
最低位移入进位标志CF,CF则移入最高位。
利用循环移位指令可以对寄存器或存储器中的任一位进行位测试
4、串操作指令
串传送指令(MOVS): MOVS指令也称为字符串传送指令,它将一个字节或字从存储器的某个区域传送到另一个区域,然后根据方向标志DF自动修改地址指针
串装入指令(LODS): LODS指令是将一个字符串中的字节或字逐个装入累加器AL或AX中
串送存指令(STOS): STOS指令是将累加器AL或AX的值送存到内存缓冲区的某个位置上
串比较指令(CMPS): 将两个字符串中相应的元素逐个进行比较(即相减),但不将比较结果送回目的操作数,而反映在状态标志位上
串扫描指令(SCAS): 将累加器的内容与字符串中的元素逐个进行比较,比较结果也反映在状态标志位上
5、程序控制指令
(1)转移指令
(1) 无条件转移指令JMP :无条件转移指令的操作是无条件地将控制转移到指令中指定的目标地址
(2)条件转移指令JCC: 在汇编语言程序设计中,常利用条件转移指令来构成分支程序。
(2)循环控制指令
LOOP指令:要求使用CX作为计数器,指令的操作是先将CX的内容减1,如果结果不等于零,则转到指令中指定的短标号处;否则,顺序执行下一条指令
LOOPE/LOOPZ 指令 :先将CX寄存器的内容减1,如结果不为零,且零标志(ZF)=1,则转移到指定的短标号,循环。
LOOPNE/LOOPNZ 指令:将CX寄存器的内容减1,如结果不为零,且零标志(ZF)=0 (表示“不相等”或“不等于零”),则转移到指定的短标号。
(3)过程调用指令
(1)过程调用指令CALL 有以下四种形式:
指令系统中提供了子程序段内直接调用指令,段内间接调用指令,段间直接调用和段间间接调用指令
如:
CALL 2000H ;段内直接调用,调用地址在指令中给出
CALL AX ;段内间接调用,调用地址由AX给出
CALl 2000H: 3000H ;段间直接调用,调用段地址和偏移量都在指令种给出
CALL DWORD PTRR[DI] ;段间间接调用,调用地址在DI、DI+1、DI+2、 DI+3所指的内存单元中,前2个字节为偏移量,后2个字节为段地址
(2)过程返回指令RET
和调用指令相对应的是返回指令。
返回指令是子程序的最后一条指令,是用来返回高一层的程序的指令
(4)中断指令
8086/8088 CPU可以在程序中安排一条中断指令来引起一个中断过程,这种中断称为软件中断。
6、处理器控制指令
(1) 标志位操作指令(7种)
CLC:清进位标志。指令的操作为(CF)←0。
STC:置进位标志。指令的操作为(CF)←1。
CMC:对进位标志求反。指令的操作为 (CF)←(CF)。
CLD:清方向标志。指令的操作为(DF)←0。
STD:置方向标志。指令的操作为(DF)←1。
CLI:清中断允许标志。指令的操作为(IF)←0。
STI:置中断允许标志。指令的操作为(IF)←1。执行这条指令后,CPU将允许外部的可屏蔽中断请求
(2)外部同步指令(4种)
HLT
WAIT: 等待指令
ESC
LOCK:封锁总线指令
(3)空操作指令 NOP