标志寄存器FLASGS
- ZF(Zero Flag)
- 零标志位,执行完相关指令后,其结果是否为0
- 为0则ZF=1;不为0则ZF=0
- CF(Carry Flag)
- 进位标志位,当运行结果的最高有效位有进位(加法)或借位(减法)时,进位标志置1,即CF=1;否则CF=0
- SF(Sign Flag)
- 运行结果最高位为1,则SF=1,否则SF=0
- PF(Parity Flag)
- 当运行结果最低字节的“1”的个数为零或者偶数时,PF=1,否则,PF=0
- OF(Overflow Flag)
- 若算术运算的结果有溢出则OF=1,否则OF=0
数据传送指令
MOV
中文名:传送指令
允许以下操作:
- MOV 寄存器,寄存器/内存单元/段寄存器/立即数
- MOV 内存单元,寄存器/段寄存器/立即数
- MOV 段寄存器,寄存器/内存单元
不允许以下操作:
4. 两个操作数类型不一样
- 例如源操作数是字节,而目的操作数是字
- 两个操作数不能都是内存单元的数
- 主存之间的直接传送不允许
- 段寄存器的操作限制:
- 不允许直接传立即数给段寄存器
不能直接用变量名,因为变量其实也是个立即数
- 不要直接改变CS值
- 不允许段寄存器之间的直接数据传送
- 不允许直接传立即数给段寄存器
PUSH
进栈操作,以一个字为例,系统自动完成两步操作:
- SP ⬅ SP-2 //堆栈指针减2
- (SP+1,SP) ⬅ SRC //将数据压入堆栈
POP
出栈操作,弹出一个字为例,系统自动完成两步操作:
- 操作数 ⬅ SP
- SP ⬅ SP+2
功能:将栈顶内容弹至某一寄存器,段寄存器(CS除外)或存储器
XCHG
XCHG OPR1, OPR2
功能:交换指令,OPR1,OPR2互换
LEA
LEA Reg,Mem
功能:将一个内存变量的有效地址送给指定的寄存器
类型转换指令
CBW AL → AX
- 执行的操作:
- 若(AL)的最高有效位为0则 AH = 00H
- 若(AL)的最高有效位为1则 AH = 0FFH
CWD AX → (DX,AX)
- 执行操作:
- 若(AX)的最高有效位为0,则(DX)= 0000H
- 若(AX)的最高有效位为1,则(DX)= 0FFFFH
算术指令
加法
- 重要的条件标志位:ZF,CF,SF,OF
- ZF,SF设置较为简单
- CF:最高有效位是否有进位
- OF:两个操作数符号(最高有效位)相同,结果与之相反则OF=1;否则OF=0
- INC对符号位无影响
ADD
功能:DST ⬅ DST+SRC
ADC
功能:带进位的加法,DST ⬅ DST+SRC+CF
INC
功能:OPR ⬅ OPR+1
减法
- CF:减数 > 被减数,此时有借位,则CF=1;否则CF=0
- OF:两个数符号(最高有效位)相反,而结果符号与减数相同,则OF=1;否则OF=0
- DEC对符号位无影响
SUB
功能:功能:DST ⬅ DST-SRC
DEC
功能:OPR ⬅ OPR-1
- 对CF标志位无影响
NEG
功能:求补,每位求反(包括符号位)后加1
- OPR ⬅ 0 - OPR
- 因此,除了OPR=0,其他情况CF=1
CMP
功能:得到(OPR1-OPR2)的结果,改变标志位ZF或CF
乘法
- 无符号乘法:MUL SRC
- 有符号乘法:IMUL SRC
- 功能:
- 若是字节数据相乘,AL和SRC相乘的结果放在AX
- AX⬅AL*SRC
- 若是字数据相乘,(AX)和SRC相乘得到的双字数据,高字放入DX,低字放入AX
- DX,AX⬅AX*SRC
- 若是字节数据相乘,AL和SRC相乘的结果放在AX
- 乘法中OF,CF使用来判断相乘的结果是什么类型。
字节相乘的结果是字节还是字。OF=CF=0为字节,OF=CF=1为字
字相乘的结果是字还是双字。OF=CF=0为字,OF=CF=1为双字
除法
- 无符号除法:DIV SRC
- 有符号除法:IDIV SRC
- 执行的操作(低位放商,高位放余数):
- 字节操作:
(AL)⬅(AX)/(SRC)的商
(AH)⬅(AX)/(SRC)的余数 - 字操作:
(AX)⬅(DX,AX)/(SRC)的商
(DX)⬅(DX,AX)/(SRC)的余数
- 字节操作:
- 对标志位没影响,但也会产生溢出
- 可能产生编号为0的内部中断:除法错中断
逻辑指令
逻辑运算指令
AND
功能:两个操作数按位与操作,结果存入操作数
用途:该指令用于清除目的操作数中与源操作数中置0位对应的位
- DST ⬅ DST & SRC
OR
功能:两个操作数按位或操作,结果放入操作数
用途:用于设置目的操作数中与源操作数置1位的对应位
- DST ⬅ DST | SRC
NOT
功能:按位取反
- DST ⬅ ~DST
XOR
功能:两个操作数按位异或,将结果放入操作数
- DST ⬅ DST⊕SRC
TEST
功能:两个操作数相与,但结果不保存,只根据其特征置条件码
- OPR1 & OPR2
注意
- NOT不允许使用立即数,其他4条指令至少有一个操作数必须在寄存器中
- NOT不影响符号位,其他4条指令 将CF,OF置0 ,AF无定义,而SF,ZF,PF根据结果来设置
移位指令
- 移位指令后面的数只能为 1,大于1的时候用cl
- 如:shr xxx,cl;shr xxx,1
算术移位(arithmetic)
算术移位指令有:算术左移SAL和算术右移SAR
- 指令格式为SAL/SAR OPR,CL/Imm
- 受影响的标志位:CF、OF、PF、ZF和SF(AF无定义)
- 功能:
- 算术左移SAL把目的操作数的低位向高位移,空出的低位补0
- 算术右移SAR把目的操作数的高位向低位移,空出的高位用最高位(符号位)填补
- 算术移位指令常用于带符号数*2或/2
逻辑移位(logical)
逻辑左移SHL和逻辑右移SHR它们的指令格式如下:
SHL/SHR OPR, CL/Imm
- 受影响的标志位:CF(移出放在CF)、OF、PF、SF和ZF(AF无定义)。
- 逻辑左移/右移指令只有它们的移位方向不同,移位后空出的位都补0
- 逻辑移位指令常用于无符号数*2或/2
循环移位(rotate)
循环移位指令有:
- 循环:左移ROL,右移ROR;
- 带进位循环:左移RCL,右移RCR
- 指令的格式:ROL/ROR OPR, CL/Imm
- 受影响的标志位:CF和OF
- 循环左移/右移指令只是移位方向不同,它们移出的位不仅要进入CF,而且还要填补空出的位。
- 带进位循环移动将CF加入循环中
总结
无符号数:逻辑移位
有符号数:算术移位
- 逻辑左移和算术左移一致,均把移出的放在CF,末位补0
- 逻辑右位的方法是逻辑左移镜像
- 算术右移移出的放在CF,但是首位补符号位,而不是补0
串处理指令
方向标志
执行串处理指令时会根据DF(direction flag)来使地址自动增加/减少
- CLD(DF=0)增加 和 STD(DF=1)减少
重复前缀指令REP
重复前缀指令是重复其后的字符串操作指令,重复的次数由CX来决定。
- 一般格式为:REP MOVS / STOS / LODS
相等重复前缀指令REPE(REPZ)
重复条件:CX != 0 && ZF = 1
不等重复前缀指令REPNE(REPNZ)
重复条件:CX != 0 && ZF = 0
串比较指令 CMPS
- 语句格式:
- CMPSB——字节串比较
- CMPSW——字串比较
- 功能:将SI所指的源串中的一个字节(或字)存储单元中的数据与DI所指的目的串中的一个字节(或字)存储单元中的数据相减,并根据相减的结果设置标志,但结果并不保存
控制转移指令
无条件转移指令
包括:JMP、子程序调用和返回、中断的调用和返回指令
条件转移指令
分为三类:
- 基于无符号数的条件转移指令
- 基于有符号数的条件转移指令
- 基于特殊算术标志位的条件转移指令
1 | JXX LABEL ;条件满足:转移,(IP)⬅(IP)+位移量 |
- 操作数LABEL采用短转移,成为相对寻址方式
- JXX不影响标志位,但要利用标志位。
根据单个条件标志的设置情况转移
指令助忆符 | 检测转移的条件 | 功能描述 |
---|---|---|
JZ(JE) | ZF=1 | 结果为零或相等则转移 |
JNZ(JNE) | ZF=0 | 结果不为0或不等则转移 |
JS/JNS | SF=1/SF=0 | 结果为负/正则转移 |
JO/JNO | OF=1/OF=0 | 结果溢出/不溢出则转移 |
JP/JNP | PF=1/PF=0 | 奇偶位为1/0则转移 |
无符号数的条件转移
- Below,Equal,Above
指令助忆符 | 检测转移的条件 | 功能描述 |
---|---|---|
JB/JNAE | CF=1 | 小于时,或进位为1则转移 |
JNB/JAE | CF=0 | 不小于,或进位为0转移 |
JBE/JNA | CFvZF=1 | 小于等于则转移 |
JNBE/JA | CF^ZF=0 | 不小于等于,即大于,则转移 |
有符号数的条件转移
- Less,Equal,Greater
指令助忆符 | 检测转移的条件 | 功能描述 |
---|---|---|
JL/JNGE | SF⊕OF=1 | 小于则转移 |
JNL/JGE | SF⊕OF=1 | 不小于,即大于等于转移 |
JLE/JNG | ZF=1 or SF!=OF | 小于等于则转移 |
JG/JNLE | ZF=0 and SF=OF | 不小于等于,即大于,则转移 |
循环指令
LOOP
- 指令格式:LOOP 短标号
- 执行过程:如果CX ≠ 0,转向“标号”所指向的指令,否则,终止循环,执行该指令的下一条指令
- 说明:使用LOOP可以代替以下两条指令:
DEC CX
JNE 短标号
其他
- 相等/为0循环指令 LOOPE/LOOPZ
- 不相等/不为零循环指令LOOPNE/LOOPNZ
子程序调用和返回
调用指令 CALL
类似JMP指令,但是不同于JMP,CALL指令需要保存返回地址(将其入栈)
返回指令 RET
将栈内保存的地址弹出,折返调用该子程序的位置
中断的调用和返回指令
中断指令 INT
- 一般格式:INT TYPE
- 其中:立即数TYPE是一个0~0FFH范围内的整数。
- 指令执行的步骤:
- 把标志寄存器压栈,清除标志位IF和TF;
- 把代码段寄存器CS和指令指针寄存器IP的内容压栈;
- IP ← TYPE4,CS ← TYPE4+2
溢出指令 INTO
当标志位OF为1时,引起中断。
中断返回指令 IRET
- 当一个中断服务程序执行完毕时,CPU将恢复被中断的现场,返回到引起中断的程序中。
- 该指令执行的过程基本上是INT指令的逆过程:
- 从栈顶弹出内容送入IP
- 再从新栈顶弹出内容送入CS
- 再从新栈顶弹出内容送入标志寄存器
中断和子程序的比较
- 相同之处:暂停当前程序的执行,转而执行另一程序段,当该程序段执行完时,CPU都自动恢复原程序的执行。
- 不同之处:
- 调用:子程序人为调用;中断不可预见(除了INT引起的中断)
- 实现方式:子程序调用是用CALL指令来实现的,但没有调用中断的指令,只有发出中断请求的事件(指令INT是发出内部中断信号,而不要理解为调用中断服务程序);
- 返回方式:子程序RET;中断IRET
- 在通常情况下,子程序是由应用系统的开发者编写的,而中断服务程序是由系统软件设计者编写的。