8086/8088指令系统
8086/8088指令系统
参考自:吴宁,乔亚男.微型计算机原理与接口技术(第4版)[M].北京:清华大学出版社,2016-9:102-149.
常用指令
寻址方式
有效地址(Effective Address,EA ),即操作数真实地址。
方式 | 解释 | 示例 |
---|---|---|
立即寻址 | 操作数就在指令上 | MOV AX,3102H |
直接寻址 | 操作数在内存,地址偏移量在指令上。段地址在DS,可设置为ES。 | MOV AX,[3102H] 、MOV BL,ES:[1200H] |
寄存器寻址 | 操作数在寄存器在CPU内部的寄存器上。可以是数据寄存器、地址寄存器、变址寄存器或段寄存器。 | MOV SI,AX |
寄存器间接寻址 | 操作数在内存,地址偏移量在寄存器中。存放偏移地址的寄存器只能是SI、DI、BX和BP。为SI、DI、BX时段地址在DS,为BP时段地址在SS。允许使用段重设。 | MOV AX,[SI] 、MOV AX,ES:[SI] |
寄存器相对寻址 | 操作数在内存中,地址偏移量为间址寄存器的内容加指令上的位移量。段地址规则同寄存器间接寻址。 | MOV AX,DATA[BX] |
基址-变址寻址 | 操作数在内存中,地址偏移量为基址寄存器(BX/BP)加变址寄存器(SI/DI)的内容。默认情况下BX为基址寄存器,段地址在DS;如果使用BP做基址寄存器,段地址在SS中。允许使用段重设。 | MOV AX,[BX][SI] |
基址-变址-相对寻址 | 操作数在内存中,地址偏移量为基址寄存器加变址寄存器的内容加指令上的位移量。段地址规则同上。允许使用段重设。 | MOV AX,5[DI][BX] |
隐含寻址 | 操作码隐含了操作数地址 | MUL BL |
指令系统
符号解释:
传送指令
通用数据传送指令
指令 | 解释 | 示例 |
---|---|---|
MOV dest,src |
将一个操作数从源地址传送到目标地址,而源地址中的数据保持不变。注意:两个操作数字长必须相同;不能同时为存储器操作数;不能用立即数直接给段寄存器赋值;一般情况下,IP、CS不能为dest;FLAGS整体不能为操作数。 | MOV BX,SI |
PUSH src 、POP dest |
压栈与出栈。注意:栈堆的存取必须时一个字;压栈时高地址向低地址生长;堆栈段位置由SS确定,SP内容等于当前栈顶的偏移地址。 | PUSH AX 、POP DS |
XCHG OPRD1,OPRD2 |
交换操作数。注意:两操作数不能同时为存储器;操作数不能为段寄存器;两个操作数字长必须相同。 | XHAG AX,BX |
XLAT 或XLAT src_table |
查表转换指令。表首偏移地址送BX,要查找元素索引送AL,查询结果放AL。可以直接指出表首偏移地址src_table。 | XLAT |
输入输出指令
在8088的I/O指令中,允许用两种方式来表示端口地址:
- 直接寻址:指令中I/O端口地址为8位,允许寻址256个端口。
- 寄存器间接寻址:端口地址为16位,由DX指定。注意:此时只能使用DX作为间指寄存器。
指令 | 解释 | 示例 |
---|---|---|
IN acc,port 或IN acc,DX |
从端口输入一个字节到AL或一个字到AX | IN AL,DX |
OUT port,acc 或OUT DX,acc |
将AL/AX的内容输出到指定的端口 | OUT 43H,AL |
取偏移地址指令
指令 | 解释 | 示例 |
---|---|---|
LEA reg16,mem |
将存储器操作数mem的16位偏移地址送到指定的寄存器。注意:源操作数必须是存储器操作数,目标操作数必须是16位通用寄存器。 | LEA BX,BUFFER |
其他传送指令
算术运算指令
会影响标志位:AF、CF、OF、PF、SF、ZF。
加法运算指令
指令 | 解释 | 示例 |
---|---|---|
ADD OPRD1,OPRD2 |
将源操作数与目标操作数相加,结果送回目标地址中。注意:不允许两个操作数都是存储器操作数;不允许把段寄存器作为操作数。 | ADD CL,20H 、ADD DX,[BX+SI] |
ADC OPRD1,OPRD2 |
带进位位的加法指令。与ADD指令基本相同,只是CF也参与运算。主要用于多字节加法运算。 | ADC AL,0ABH |
INC OPRD |
指定操作数内容加1,再送回该操作数。不影响CF标志位。注意:操作数不能是段寄存器、立即数。常用于循环程序修改循环次数。 | INC AX |
减法指令
指令 | 解释 | 示例 |
---|---|---|
SUB OPRD1,OPRD2 |
不考虑借位的减法指令。将目标操作数减去源操作数,并将结果送目标操作数地址中。对状态位的影响与ADD指令相同。 | SUB BL,30H |
SBB OPRD1,OPRD2 |
考虑借位的减法指令。与SUB指令基本相同,只是CF也参与运算。主要用于多字节减法运算。 | SBB BL,30H |
DEC OPRD |
指定操作数内容减1,再送回该操作数。不影响CF标志位。常用于循环程序修改循环次数。 | DEC AX |
NEG OPRD |
求补指令。用0减去操作数OPRD,结果送回该操作数所在地址。注意:除非操作数为0,一般情况下执行完CF置1,因为0减一个数自然会产生借位;当操作数为80H/8000H,执行完后依然为80H/8000H,但OF置1,其他情况置0。 | |
CMP OPRD1,OPRD2 |
比较指令。相当于使用了SUB但结果不送回,只影响标志位,标志位影响与SUB相同。主要用来比较两个数大小。①对于相等关系,ZF为1两者相等。②对于大小关系,对于两个无符号数,CF为0则被减数大于减速;对于两个有符号数,当OF⊕SF=0时,被减数大于减数,当OF⊕SF=1时,减速大于被减数。一般在比较指令之后紧跟一个条件转移指令,以根据比较结果决定程序的转向 | CMP AL,[BX] |
乘法指令
采用隐含寻址方式,目标操作数为AX(与DX),源操作数由指令给出。
对无符号数乘法,如果乘积的高半部分(AH/DX)不为0,则CF=OF=1,否则CF=OF=0。对有符号数乘法,如果乘积的高半部分是低半部分的符号位扩展,则CF=OF=0,否则CF=OF=1。对其它标志均无定义。
指令 | 解释 | 示例 |
---|---|---|
MUL OPRD |
无符号数乘法。 | MUL BX |
除法指令
采用隐含寻址方式,隐含被除数,要求除数不为立即数。
要求被除数的字长必须为除数的两倍。若被除数字长不够,就要使用字位扩展指令扩展位数。
指令 | 解释 | 示例 |
---|---|---|
DIV OPRD |
无符号数除法。商放AL/AX,余数放AH/DX。若除法运算的结果大于寄存器可保存的值,则在CPU内部会产生一个类型0中断。除法指令对6个标志位均无影响。 | DIV BL |
其他算术运算指令
逻辑运算和移位指令
会影响标志位:AF、CF、OF、PF、SF、ZF。
逻辑运算指令
除NOT外,其他4条指令都会使CF=OF=0,AF值不定,并对SF、PF和ZF有影响。
指令 | 解释 | 示例 |
---|---|---|
AND OPRD1,OPRD2 |
逻辑与。结果送回目标操作数。 | AND AX,[BX] |
OR OPRD1,OPRD2 |
逻辑或。结果送回目标操作数。 | OR [BX],AL |
NOT OPRD |
逻辑非。按位取反,结果送回目标操作数。 | NOT AX |
XOR OPRD1,OPRD2 |
逻辑异或。结果送回目标操作数。 | XOR AX,AX |
TEST OPRD1,OPRD2 |
测试指令。与AND指令类似,只是不将结果送回,只影响标志位。 | TEST AL,02H |
移位指令
包括循环移位指令和非循环移位指令。移位次数为1或CL。大多会影响那6个标志位。
对于非循环移位:
左移高位进CF,低位补0。在移动次数为1的情况下,移位后操作数最高位与CF不同,则OF=1,否则为0。OF=1对SHL不表示左移后溢出,而对SAL表示移位后超出了符号数的表示范围。
右移低位进CF,对于SHR高位补0,在移动次数为1的情况下,移位后操作数最高位与次高位不同,则OF=1,否则为0;若移位次数不为1,OF不定。对于SAR高位不变。
指令 | 解释 |
---|---|
SAL OPRD,1 或SAL OPRD,CL |
算术左移 |
SHL OPRD,1 或SHL OPRD,CL |
逻辑左移 |
SAR OPRD,1 或SAR OPRD,CL |
算术右移 |
SHR OPRD,1 或SHR OPRD,CL |
逻辑右移 |
对于循环移位指令:
指令 | 解释 |
---|---|
ROL OPRD,1 或ROL OPRD,CL |
不带CF的循环左移 |
ROR OPRD,1 或ROR OPRD,CL |
不带CF的循环右移 |
RCL OPRD,1 或RCL OPRD,CL |
带CF的循环左移 |
RCR OPRD,1 或RCR OPRD,CL |
带CF的循环右移 |
串操作指令
串指令既可处理字串,也可处理字节串,并在每完成一次字/字节操作后自动修改指针,去执行下一个字/字节操作。8086指令集中的串操作指令可处理的最大串长度为64KB。
源串默认DS:SI,允许段重设。目标串为ES:DI,不允许段重设。串长度值在CX,使用了重复前缀该值自动减1。SI、DI的修改方向与标志位DF有关,0则增反之减。
重复操作前缀
指令 | 解释 |
---|---|
REP | 无条件重复,直到CX=0。 |
REPE/REPZ | 相等/结果为0时重复,ZF=1且CX≠0时重复。 |
REPNE/REPNZ | 不相等/结果不为0时重复,ZF=0且CX≠0时重复。 |
串操作指令
传送指令:
指令 | 解释 | 示例 |
---|---|---|
MOVS OPRD1,OPRD2 |
将源串地址中的字节/字传送到目标串地址中 | |
MOVSB |
一次传一字节 | REP MOVSB |
MOVSW |
一次传一字 |
串比较:将源串和目标串按字/字节比较,结果反应到标志位上。CMPS OPRD1,OPRD2
(主要用在需要段重设的情况下)、CMPSB
、CMPSW
。串比较指令的后边需要一条指令来判断是何种原因结束了串比较(ZF)。
串扫描:将AX/AL与ES:DI指定值进行字/字节比较,结果反应到标志位上。SCAS OPRD
、SCASB
、SCASW
。
串装入:把DS:SI指向的装入AL/AX,然后根据DF自动修改SI。对标志位没影响。一般不带重复前缀,因为重复一次AL/AX会被取代。LODS OPRD
、LODSB
、LODSW
。
串存储:把AL/AX存到ES:DI内存单元中,然后根据DF自动修改DI。对标志位没影响。STOS OPRD
、STOSB
、STOSW
。
程序控制指令
无条件跳转
JMP无条件跳转。分为4种:
-
段内直接跳转:
JMP LABEL
或JMP NEAR LABEL
。LABEL是个标号/符号地址,该标号在本程序所在的代码段内。指令被汇编时,汇编程序会计算下条指令到LABEL指示地址之间的位移量(可正可负),指令操作就是将IP当前值加上计算出的位移量形成新的IP,并使CS保持不变,从而使程序按新地址继续执行。
-
段内间接跳转:
JMP OPRD
。OPRD是16位寄存器或存储器地址。指令的执行是用指定的16位寄存器内容或存储器内容作为转移目标的偏移地址,用其取代原来IP的内容,从而实现程序的转移。CS内容不变。
-
段间直接转移:
JMP FAR LABEL
。FAR表明其后LABEL是一个远标号,他在另一个代码段内。汇编程序根据LABEL位置确定段基地址和偏移地址,然后送入CS、IP,结果使程序转移到另一个代码段继续执行。
-
段间间接转移:
JMP OPRD
。OPRD使32位存储器地址。指令的执行是将指定的连续4个内存单元内容送入IP(低字)、CS(高字),从而程序转移到另一个代码段继续执行。
条件跳转
JCC条件跳转如下:
循环控制
控制转向的目标地址是当前IP内容为中心的-128~+127字节范围内。循环次数必须先送入CX。
指令 | 解释 |
---|---|
LOOP LABEL |
相当于DEC CX +JNZ NEXT |
LOOPZ LABEL 或LOOPE LABEL |
先将CX内容减1,若CX≠0且ZF=1继续循环,否则退出循环。 |
LOOPNZ LABEL 或LOOPNE LABEL |
与LOOPZ指令类似,先将CX内容减1,若CX≠0且ZF=0继续循环,否则退出循环。 |
过程调用和返回
调用CALL执行时,CPU先将下一条指令地址压栈,然后将子程序入口地址赋给IP,以便转到子程序执行。
由于子程序有可能与主程序不在同一个段,所以CALL指令也有4种形式:
- 段内直接调用:
CALL NEAR PROC
。 - 段内间接调用:
CALL OPRD
。 - 段间直接调用:
CALL FAR PROC
。 - 段间间接调用:
CALL OPRD
。
RET一般安排在子程序末尾,执行RET时,CPU出栈到IP(或CS和IP,区分看是远过程还是近过程)中,继续执行主程序。
中断
中断指令格式为:INT n
。n为中断向量码/中断类型码,是一个常数,取值范围为0~255。指令执行时,CPU根据n计算除中断向量的地址,然后从该地址种取出中断服务程序的入口地址,并转到该中断服务子程序去执行。
中断返回指令为IRET
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构