目录
从功能上包括六大类:
- 数据传送
- 算术运算
- 逻辑运算和移位
- 串操作
- 程序控制
- 处理器控制
一、数据传输指令
- 注意点:
- 两操作数字长必须相同;
- 两操作数不允许同时为存储器操作数
- 两操作数不允许同时为段寄存器;
- 在源操作数是立即数时,目标操作数不能是段寄存器;
- IP和CS不作为目标操作数,FLAGS一般也不作为操作数在指令中出现。
①通用数据传输指令
1、传送指令MOV
? MOV 目的操作数,源操作数
? 注意:目的操作数和源操作数不能是IP寄存器、类型必须相同,不可以同时为段寄存器
? 不允许在两个存储单元中直接传送数据
? 目的操作数不允许是立即数
? 立即数不允许直接送入段寄存器
? 2、交换指令XCHG
-
格式:
-
注意:
- 操作数不能为立即数、段寄存器
- 两操作数必须有一个是寄存器操作数,不能同时为存储单元。
②堆栈操作指令
- 堆栈操作的原则
- 先进后出
- 以字节为单位
- 指令的操作数必须是16位
- 操作数可以是寄存器或存储器两单元,但不能是立即数;
- 不能从栈顶弹出一个字给CS;
? 1、进栈指令PUSH
? PUSH 源操作数
? 2、出栈指令POP
? POP 目的操作数
③累加器(即AX或AL)专用传输指令
-
指令寻址方式
- 根据端口地址码的长度,指令具有两种不同的端口地址表现形式。
- 直接寻址
- 端口地址为8位时,指令中直接给出8位端口地址;
- 寻址256个端口。
- 间接寻址
- 端口地址为16位时,指令中的端口地址必须由DX指定;
- 可寻址64K个端口。
-
acc(AL/AX)
-
PORT(端口地址)
? 1、输入指令IN
? IN acc,PORT
? 2、输出指令OUT
? OUT PORT,acc
? 3、查表指令XLAT
? XLAT
- 说明:
- 用BX的内容代表表格首地址,AL内容为表内位移量,BX+AL得到要查找元素的偏移地址
- 操作:
? 注意:执行该指令前需先执行 :MOV BX,换码表的偏移首地址MOV AL,被转换码
④目标地址传输指令
- 取近地址指令:LEA
- 取远地址指令:LDS、LES
- LDS和LES均用于将一个32位的远地址指针写入到目标寄存器。
1、LEA(有效地址传输到寄存器)
- 操作
- 当程序中用符号表示内存偏移地址时,须使用该指令。
- 格式:
- 指令要求
- 源操作数必须是一个存储器操作数,目标操作数通常是间址寄存器。
2、LDS(装入一个新的物理地址)
? 将源操作数的偏移地址送目标寄存器,将源操作数的段地址送DS
3、LES(装入一个新的物理地址)
? 将源操作数的偏移地址送目标寄存器,将源操作数的段地址送ES
⑤标志寄存器传送指令
? 1、LAHF:将FR寄存器的低八位放入AH
? 2、SAHF:将AH放入FR寄存器的低八位
? 3、PUSHF:将FR寄存器推入堆栈中
? 4、POPF:将堆栈栈顶弹如FR
⑥扩展指令
- 字节到字的扩展指令
- 格式:
- 操作:
- 规则:
- 若最高位=1,则执行后AH=FFH
- 若最高位=0,则执行后AH=00H
- 字到双字的扩展指令
- 格式:
- 操作:
- 规则:
- 若最高位=1,则执行后DX=FFFFH
- 若最高位=0,则执行后DX=0000H
二、算术运算指令
①算术加法指令
1、算术加法ADD
? ADD 目的操作数,源操作数
? 功能:目的操作数 ← 目的操作数 + 源操作数
? 注意:目的操作数不能立即寻址
? 加法操作中产生进位影响CF标志
? 带符号数相加要考虑溢出
? 2、带进位算术加法ADC(多字节相加时使用(大于2字节))
? ADC 目的操作数,源操作数
? 功能:目的操作数 ← 目的操作数+ 源操作数 + CF
? 注意:目的操作数不能立即寻址
? 加法操作中产生进位影响CF标志
? 带符号数相加要考虑溢出
? 3、加1指令INC
? INC 目的操作数
? 功能:目的操作数 ← 目的操作数 + 1
? 注意:目的操作数不能立即寻址
? 加法操作中产生进位不影响CF标志
? 带符号数相加要考虑溢出
②算术减法指令
- 算术减法SUB
? SUB 目的操作数,源操作数
? 功能:目的操作数<——目的操作数-源操作数
? 注意:目的操作数不能立即寻址
? 减法操作中产生借位影响CF标志
? 带符号数相减要考虑溢出
? 无符号数相减,若CF=1,则结果为补码
- 带进位算术加法SBB(多字节相加减使用(大于2字节))
? ADC 目的操作数,源操作数
? 功能:目的操作数<——目的操作数-源操作数-CF
? 注意:目的操作数不能立即寻址
? 减法操作中产生进位影响CF标志
? 带符号数相减要考虑溢出
? 无符号数相减,若CF=1,则结果为补码
- 减1指令DEC
? DEC 目的操作数
? 功能:目的操作数<——目的操作数-I
? 注意:目的操作数不能立即寻址
? 加法操作中产生进位不影响CF标志
? 操作数为内存寻址时必须使用伪指令 如DEC WORD PTR[BX]
- 求补指令NEG
- 格式:
- 操作:
- 说明:
- 执行NEG指令后,一般情况下都会使CF为1,除非给定的操作数为零才会使CF为0;
- 当指定的操作数的值为80H(-128)或为8000H(-32768),则执行NEG指令后,结果不变,但0F置1,其它情况下OF均置0。
对一个负数取补码就相当于用零减去此数
用0减去操作数,可以得到负数的绝对值
- 比较指令CMP
? CMP 目的操作数,源操作数
? 功能:仅影响标志位,不产生结果
? 注意:目的操作数不能立即寻址
? 目的操作数和元操作数不能同时为存储器操作数
③算术乘除指令
- 无符号数乘法指令MUL
? MUL 源操作数
? 功能:AX+DX/AX ← AX/AL存的数*源操作数
? 注意:操作数不能立即寻址
? AL*BL放入AX
? AX*BX放入DX和AX
- 带符号数乘法指令IMUL(多字节相加时使用(大于2字节))
? IMUL 源操作数
? 功能:AX+DX/AX ← AX/AL存的数*源操作数
? 注意:操作数不能立即寻址
? AL*BL放入AX
? AX*BX放入DX和AX
? 有符号数再计算机中是其补码,用MUL计算结果有错,IMUL会对符号数处理
-
无符号数除法指令DIV
DIV OPRD
-
带符号数除法指令IDIV
IDIV OPRD
算术乘除运算指令总结:
- 指令执行影响状态标志位
- 乘法指令执行结果为相乘数的双倍字长;除法指令要求被除数是除数的双倍字长。
④标志寄存器传送指令
? 1、LAHF:将FR寄存器的低八位放入AH
? 2、SAHF:将AH放入FR寄存器的低八位
? 3、PUSHF:将FR寄存器推入堆栈中
? 4、POPF:将堆栈栈顶弹如FR
算术运算类指令总结:
- 算术运算类指令的执行会影响状态标志位。其中:
- 该类指令中,全部双操作数指令对操作数的要求与MOV指令完全相同;
- 所有单操作数指令都要求操作数:
- 不能是立即数
- 如果是存储器操作数,需要声明操作数的字长( 用PTR运算符)
- 乘法运算中:乘积是乘数的双倍字长
- 除法指令要求被除数是除数的双倍字长
三、逻辑运算和移位指令
- 对操作数的要求
- 大多与MOV指令相同
- “非”运算指令要求操作数不能是立即数
- 对标志位的影响
- 除“非”运算指令,其余指令的执行都会影响除AF外的5个标志;
- 无论执行结果是什么,都会使标志位OF=CF=0;
- “非”运算指令的执行不影响标志位。
①“与”指令:
- 格式:
- 操作:
- 应用:
- 实现两操作数按位相与的运算
- 使目标操作数的某些位不变,某些位清零
- 在操作数不变的情况下使CF和OF清零
②“或”运算指令
- 格式:
- 操作:
- 应用:
- 实现两操作数相 “或”的运算
- 使某些位不变,某些位置“1”
- 在不改变操作数的情况下使OF=CF=0
③“非”运算指令
注意:“非”运算指令的执行对标志位无影响
④“异或”运算指令
xor al,al 相当于 mov al,0
⑤“测试”指令
⑥移位操作指令
- 控制二进制位向左或向右移动的指令
- 分类:
- 说明:
- 指令格式在形式上为双操作数,本质上为单操作数;
- 指令的目标操作数为被移动对象,源操作数为移动次数
- 移动移动1位时由指令直接给出;移动两位及以上时,移位次数必须由CL指定。
1、非循环移位指令
- 算术 —— 有符号数
- 逻辑 —— 无符号数
- 左移最低位补零,最高位移入CF
- 逻辑右移最低位移入CF,最高位补零
- 算术右移最低位移入CF,最高位复制符号位
- 应用:
- 逻辑左移
- 算术左移
- 逻辑右移
- 算术右移
2、循环移位指令
- 指令格式、对操作数的要求与非循环移位指令相同
- 应用:
- 用于对某些位状态的测试;
- 高位部分和低位部分的交换;
- 与非循环移位指令一起组成32位或更长字长数的移位
-
不带进位位的循环移位
-
左移最高位移入CF,同时移入最低位
-
右移最低位移入CF,同时移入最高位
-
左移ROL
-
右移ROR
-
带进位位的循环移位
-
左移CF移入最低位,最高位移入CF
-
右移CF移入最高位,最低位移入CF
-
左移RCL
-
右移RCR
四、串操作指令
-
说明:
- 针对数据块或字符串的操作
- 可实现存储器到存储器的数据传送;
- 待操作的数据串称为源串,目标地址称为目标串。
- 串操作指令的操作对象是多个字节数(一串字符或数据)因此,指令的执行需要确定:
- 串所在的区城
- 串的首地址(原串、目标串起始地址)
- 串长度(大小)
- 串的操作方向
-
串操作指令的要求:
- 串所在区域及首地址:
- 源串一般存放在数据段,偏移地址由SI指定。允许段重设。
- 目标串必须在附加段,偏移地址由DI指定。
- 串长度:
- 串的操作方向:
- 由DF标志位决定。指令根据DF状态自动修改地址指针:
- DF=0 → 增地址方向(cld指令:将标志寄存器的DF位置0)
- DF=1 → 减地址方向(std指令:将标志寄存器的DF位置1)
-
重复前缀:
- 无条件重复
- REP
- 当CX≠0时,REP后的指令将继续重复执行
- 常用于传送类指令前 → 未传完则继续传送
- 条件重复
- 相等(为零)重复: REPE (REPZ)
CX≠0 ∩ ZF=1
,则前缀后的指令将继续重复执行
- 不相等(不为零)重复: REPNE ( REPNZ)
CX≠0 ∩ ZF=0
,则前缀后的指令将继续重复执行
条件前缀常用于运算类指令前,当:
- 操作未结束AND结果=0
- 操作未结束AND结果≠0
使其后的指令继续重复执行。
- 若按增地址方向操作,串操作结束时:
- 串传送指令:指针将指向串尾+1
- 串比较类指令:指针将指向结束位+1
- 若按减地址方向操作,串操作结束时:
- 串传送指令:指针将指向串尾-1
- 串比较类指令:指针将指向结束位-1
①串传送MOVS
-
说明:
-
格式:
- MOVS OPRD1,OPRD2
- MOVSB
- MOVSW
-
串传送指令常与无条件重复前缀连用
②串比较CMPS
-
说明:
-
操作:
- 目标串-源串,结果不写回目标地址
- 常与条件重复前缀连用
-
格式:
- CMPS OPRD1,OPRD2
- CMPSB
- CMPSW
-
前缀的操作对标志位不影响
-
例:
lea si,mem1
lea di,mem2
mov cx,200
cld
repe cmpsb
jz stop ; 两数据串相同
dec si ; 指向存放不相等数据的地址
mov al,[si]
mov bx,si
stop:
hlt
③串扫描 SCAS
- 常用于在指定存储区域中寻找某个关键字
- 格式:
- 执行与CMPS指令相似的操作,区别是:
④串装入LODS
-
说明:
- 用于将内存某个区域的数据串依次装入累加器,以便显示或输出到接口。
- LODS指令一般不加重复前缀。
-
格式:
-
LODS OPRD(源操作数)
-
LODSB
-
LODSW
-
操作:
- 对字节:[ DS : SI ] → AL
- 对字: [ DS : SI ] → AX
⑤(串存储)串送存STOS
-
格式:
-
STOS OPRD(目标操作数)
-
STOSB
-
STosW
-
操作:
- 对字节:AL → [ ES : DI ]
- 对字: AX → [ ES : DI ]
-
应用:
- 常用于将内存某个区域置同样的值
- 此时:
- 将待送存的数据放入AL(字节数)或AX(字数据);
- 确定操作方向(增地址/减地址)和区域大小(串长度值);
- 使用串存储指令+无条件重复前缀,实现数据传送。
串操作指令应用注意事项
- 需要定义附加段
- 需要设置数据的操作方向
- 源串和目标串指针分别为SI和DI
- 串长度值必须由CX给出
- 注意重复前缀的使用方法
- 传送类指令前加无条件重复前缀
- 串比较类指令前加条件重复前缀,但前缀不影响ZF状态
五、程序控制
- 程序控制类指令的本质:
- 决定程序执行方向的因素:
- 程序控制类指令以‘‘隐含” 的方式修改CS和IP,以实现控制程序走向的目的( Intel指令集不允许由指令直接修改CS和IP)
- 通过修改IP或CS和IP,实现程序的三种基本控制结构
①转移指令
- 通过修改指令的偏移地址或段地址及偏移地址实现程序的转移
-
无条件转移指令
- 无条件转移到目标地址,可以实现在当前代码段内或段间转移
- 格式:
(1)无条件段内转移
- 转移的目标地址在当前代码段内,段地址不改变。
- 即:目标地址是16位偏移地址。
- 目标地址可以由 指令中直接给出目标地址,段内直接转移。也可以由指令中的寄存器或存储器操作数指出目标地址段内间接转移。
-
段内直接转移
-
段内间接转移
(2)无条件段间转移
- 转移的目标地址不在当前代码段内。
- 目标地址为32位,包括段地址和偏移地址。
- 目标地址可以由指令中直接给出目标地址,即段间直接转移;也可以由指令中的32位存储器操作数指出目标地址,即段间间接转移。
- 段间直接转移
- 段间间接转移
- 转移的目标地址由指令中的32位操作数给出
- 32位目标地址须存放于内存中
- 格式:
- 低地址存放IP,高地址存放CS
-
条件转移指令
转移指令 |
条件 |
意义 |
英文助记 |
jz/je |
ZF = 1 |
相减结果等于0/ 相等时转移 |
jump if Zero/Equal |
jnz/jne |
ZF = 0 |
不等于0 / 不相等时转移 |
Jump if Not Zero / Not Equal |
js |
SF = 1 |
负数时转移 |
Jump if Sign |
jns |
SF = 0 |
整数时转移 |
Jump if Not Sign |
jo |
OF = 1 |
溢出时转移 |
Jump if Overflow |
jno |
OF = 0 |
未溢出时转移 |
jump if Not Overflow |
jp/jpe |
PF = 1 |
低字节中有偶数个1时转移 |
jump if Parity/Parity Even |
jnp/jpo |
PF = 0 |
低字节中有奇数个1时转移 |
jump if Not Parity/Parity Odd |
jbe/jna |
CF = 1或ZF = 1 |
小于等于/不大于时转移 |
jump if Below or Equal/Not Above |
jnbe/ja |
CF = ZF = 0 |
不小于等于/大于时转移 |
Jump if Not Below or Equal/ Above |
jc/jb/jnae |
CF = 1 |
进位/小于/不大于等于时转移 |
Jump if Carry/ Below /Not Above Equal |
jnc/jnb/jae |
CF = 0 |
未进位/不小于/大于等于时转移 |
Jump if Not Carry /Not Below /Above Equal |
jl/jnge |
SF != OF |
小于/不大于等于时转移 |
Jump Less /Not Great Equal |
jnl/jge |
SF = OF |
不小于/ 大于等于时转移 |
Jump if Not Less /Great Equal |
jle/jng |
ZF != OF或ZF = 1 |
小于等于/不大于 |
Jump if Less or Equal /Not Great |
jnle/jg |
SF = OF且ZF = 0 |
不小于等于/ 大于时转移 |
Jump Not Less Equal /Great |
jcxz |
CX 寄存器值 = 0 |
cx寄存器值为0时转移 |
Jump if register CX‘s value is Zero |
②循环控制
- 循环范围
- 以当前IP为中心的
[-128 , +127]
范围内循环。
- 循环次数由CX寄存器指定。
- 循环指令:
- 无条件循环指令:LOOP
- 条件循环指令:LOOPZ、LOOPNZ
-
无条件循环指令
-
格式:
-
循环条件:
-
操作:
完全相当于
DEC CX
JNZ 符号地址
-
条件循环指令
- 功能:
- 先使CX-1,再根据CX中的值及ZF值来决定是否继续循环
- 格式:
- LOOPZ Label:继续循环的条件: CX≠0,且ZF=1
- LOOPNZ Label:继续循环的条件: CX≠0,且ZF=0
③过程调用
-
过程调用指令
-
与转移指令的比较
-
调用指令的执行过程
- 保护断点
- 获取子过程的入口地址
- 执行子过程
- 恢复断点,返回原程序。
断点保护和恢复由系统自动完成,但会影响堆栈的栈顶指针
-
直接调用:
指令中直接给出子过程的入口地址
-
间接调用:
由内存获得子过程的入口地址
-
段内调用
-
段间调用
-
说明:
- 子过程与原调用程序不在同一代码段,调用前需保护断点的段基地址和偏移地址
- 先将断点的CS压栈,再压入IP。
-
段间直接调用
-
段间间接调用
-
返回指令
子程序的最后一条指令必须是RET
④中断控制
- 中断的概念
- 某种异常或随机事件(中断源)使处理器暂时停止正在运行的程序,转去执行一段特殊处理程序,并在处理结束后返回原程序被中断处继续执行的过程。
中断与过程调用:
- 相似点:
- 从一个正在执行的过程转向另一个过程(处理程序) ,并在执行完后返回原程序继续执行
- 区别:
- 中断是随机事件或异常事件引起,调用是事先已在程序中安排好;
- 调用指令在指令中直接给出子程序入口地址,中断指令只给出中断向量码,入口地址则在向量码指向的内存单元中。
- 调用可以是近过程调用或远过程调用,中断处理程序均为远过程;
- 响应中断请求不仅要保护断点地址,还要保护FLAGS内容。
中断指令
- 引起CPU产生一次中断的指令
- 格式:
- 说明:
n * 4
:存放中断服务子程序入口地址的单元的偏移地址
n * 4 + 2
:存放中断服务子程序入口地址的单元的段地址
- 中断指令的执行过程:
- 将FLAGS压入堆栈;
- 将INT指令的下一条指令的CS、IP压栈;
- 由n x 4得到存放中断向量的地址;
- 将中断向量(中断服务程序入口地址)送CS和IP寄存器;
- 转入中断服务程序。
中断返回指令
- 格式: IRET
- 中断服务程序的最后一条指令,负责:
中断服务子程序的最后一条指令也必须是IRET指令
六、处理器控制
- 这类指令用来对CPU进行控制,如修改标志寄存器,使CPU暂停,使CPU与外部设备同步等。
- 处理器控制指令的控制对象是CPU均为零操作数格式指令
①对标志位的操作
-
置标志位状态
指令 |
执行后变化 |
指令说明 |
CLC |
CF=0 |
清进位标志位 |
STC |
CF=1 |
进位标志位置位 |
CMC |
CF取反 |
进位标志位取反 |
CLD |
DF=0 |
清万向标志位,串操作从低地址到高地址 |
STD |
DF=1 |
方向标忐位置位,串操作从高地址到低地址 |
CLI |
IF=0 |
清中断标志位,即关中断 |
STI |
IF=1 |
中断标志位置位,即开中断 |
②与外部设备的同步
- 处理器暂停指令HLT
- HLT指令经常和中断过程联系在--起,它的执行实际上是用软件的方法使CPU处于暂停状态等待硬件中断,而硬件中断的进入又使CPU退出暂停状态。由NMI引脚上引入的不可屏蔽(非屏蔽)中断和在中断允许(IF=1) 的情况下,INTR引脚上引入的可屏蔽中断,会使CPU退出暂停状态;同时对系统复位操作也会使CPU退出暂停状态。
- 等待指令WAIT
- WAIT指令使CPU处于等待状态,直到CPU的TEST引脚上的信号为有效。 8086 CPU的第23号引脚TEST,是用来使处理器与外部硬件同步的,也称为同步指令,为低电平有效的输入信号。若测试到该信号无效,CPU继续执行WAIT指令,以令CPU处于空闲等待状态;若测试到该信号有效,CPU转去执行WAIT指令的下一条指令。
- 换码指令/交权指令ESC
- ESC指令可以使其他处理器接收米自8086指令流中的指令,且可用8086的寻址方式对存储器操作数进行操作。执行ESC指令,仅仅完成访问一个存储器操作数并把它放在总线上。
- 总线封锁指令LOCK
- LOCK指令可以放在任何一条指令前面,所以LOCK指令实际上是一个特殊的1字节封锁线。它使工作在最大模式下的8086CPU,在执行下一条指令期间发出总线封锁信号,即LOCK引脚变为低电平有效信号。这样,在CPU访问存储器或外设时,总线控制器会对总线进行封锁,使其他处理器得不到总线控制权,从而就不能访问存储器或外设。
- 空操作指令NOP
- NOP指令不执行任何操作,也不影响任何标志,其机器码占1个存储单元,其功能等同于交换指令“XCHG AX, AX"。在调试程序时往往用NOP指令占据一定的存储单元,以便在正式运行前用其他必要的指令代替。由于CPU执行任何一条指令都是需要时间的,故当程序中需要用软件进行延时时,可以使用NOP指令来较精确地定时,而不会影响程序的其他功能。
指令系统小结
- 8种寻址方式:
2. 直接寻址
4. 寄存器间接寻址
5. 寄存器相对寻址
6. 基址变址寻址
7. 基址变址相对寻址
6. 寄存器寻址
7. 立即寻址
8. 隐含寻址
8086常用指令集
原文:https://www.cnblogs.com/tanjiangtao/p/13584983.html