前言
一、ZF 标志
Zero Flag,零标记位。用于记录相关指令执行后,其结果是否为 0。如果结果为 0,则 ZF=1,如果结果非 0,则 ZF=0
mov ax,1 sub ax,1 ;ZF = 1
mov ax,2 sub ax,1 ;ZF=0
二、PF 标志
Parity Flag,奇偶标记位。它用于记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数。如果1的个数为偶数,则pf=1,如果为奇数,则pf=0
mov al,1 add al,10 ;PF=0
mov al,1 or al,2 ;PF=1
三、SF 标志
Sign Flag,符号标记位。它用于记录相关指令执行后,其结果是否为负。如果结果为负,则SF=1,如果结果非负,则SF=0
四、CF 标志
Carry Flag,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值
mov al 98H add al,al ;执行后:(a1)=30H,CF=1,CE 记录了从最高有效位向更高位的进位值
五、OF 标志
Overflow Flag,溢出标志位。在进行有符号数运算的时候,如果计算结果超出了机器所能表示的范围则发生溢出,此时OF=1。否则,OF=0。
注意区分CF和OF的区别:CF是对无符号数运算有意义的标志位,OF是对有符号数运算有意义的标志位
六、abc 指令
adc是带进位加法指令,它利用了CF位上记录的进位值。
指令格式:
adc 操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
比如指令 adc ax,bx 实现的功能是:(ax)= (ax)+ (bx)+ CF
mov ax 1 add ax,ax adc ax,3 ;ax=5
七、sbb 指令
sbb是带借位减法指令,它利用了CF位上记录的错位值。
指令格式:
sbb 操作对象1,操作对象2
功能:操作对象1=操作对象1-操作对象2-CF
sbb指令和adc指令是基于同样的思想设计的两条指令,在应用思路上和adc指令类似
八、cmp 指令
cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响
指令格式:
cmp 操作对象1,操作对象2
功能:计算操作对象 1 - 操作对象 2 但并不保存结果,仅仅根据计算结果对标志寄存器进行设置
利用 cmp ax, bx 指令对两个无符号数ax和bx进行比较,如果执行后:
zf = 1,说明 (ax) = (bx) zf = 0,说明 (ax) ≠ (bx) cf = 1,说明 (ax) < (bx) cf = 0,说明 (ax) ≥ (bx) cf = 0 并且 zf = 0,说明 (ax) > (bx) cf = 1 或 zf = 1,说明 (ax) ≤ (bx)
利用 cmp ah,bh 指令对两个有符号数ah和bh进行比较,由于有符号数的比较较为复杂,主要是考虑到溢出的特殊情景,我们分类讨论:
(1) 如果 sf = 1 并且 of = 0
of = 0 说明没有溢出,并且 sf = 1 说明逻辑上真正的结果为负数。所以 (ah) < (bh)。
(2) 如果 sf = 1 并且 of = 1
of = 1 说明存在溢出,针对补码求和来说,如果结果非0并且产生溢出,正确的逻辑结果符号与实际的结果符号必然相反。 sf = 1 说明实际结果为负,那么正确的逻辑结果应该为正。所以 (ah) > (bh)。
(3) 如果 sf = 0 并且 of = 1
of = 1 说明存在溢出,针对补码求和来说,如果结果非0并且产生溢出,正确的逻辑结果符号与实际的结果符号必然相反。 sf = 0说明实际运算结果必然不小于0,因为存在溢出所以实际运算结果必不等于0,所以实际运算结果必然大于0,进而推导出正确的逻辑运算结果必然小于0。所以 (ah) < (bh)。
(4) 如果 sf = 0 并且 of = 0
of = 0 说明没有溢出,并且 sf = 0,说明逻辑上真正的结果为非负数。所以 (ah) ≥ (bh)。
(5) 如果 zf = 1
这种情形比较简单。此时 (ah) = (bh)。
九、检测比较结果的条件转移指令
“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP。比如,jcxz就是一个条件转移指令,它可以检测cx中的数值,如果 (cx) = 0,就修改IP,否则什么也不做。所有条件转移指令的位移都是 [-128, 127](即它们都是短转移)。
jcxz是根据寄存器cx的值来判断是否转移,除此之外还存在其他条件转移指令,大多数条件转移指令都检测标志寄存器相关标志位,根据检测的结果来决定是否修改IP。
下表列出了常用的根据无符号数的比较结果进行转移的条件转移指令:
指令 | 含义 | 检测的相关标志位 | 备注 |
je | 等于则转移 | zf = 1 | e 表示 equal |
jne | 不等于则转移 | zf = 0 | ne 表示 not eauql |
jb | 低于则转移 | cf = 1 | b 表示 below |
jnb | 不低于则转移 | cf = 0 | nb 表示 not blow |
ja | 高于则转移 | cf = 0 且 zf = 0 | a 表示 above |
jna | 不高于则转移 | cf = 1 或 zf = 1 | na 表示 not above |
注意,条件转移指令通常与cmp指令配合使用。
十、DF 标志和串传送指令
Direction Flag,方向标志位。在串传送指令中,控制每次操作后 si、di 的增减
df = 0 ,每次操作后 si、di 递增 df = 1 ,每次操作后 si、di 递减
movsb 指令
格式:
movsb
功能:将ds:si指向的内存单元中的字节送入es:di中,并根据标志寄存器df的值,将si和di递增或递减
movsw 指令
movsw 的功能是将 ds:si 指向的内存字单元中的字送入 es:di 中,然后根据标志寄存器df位的值,将 si和 di 递增 2 或递减 2
rep 指令
movsb 和 movsw 进行的是串传送操作中的一个步骤,一般来说,movsb 和 movsw 都配合 rep 配合使用,格式如下:
rep movsb
功能:根据cx的值来决定是否重复执行 movsb操作
cld 指令和 std 指令
cld 指令:将标志寄存器的 df 位置设置为 0
std 指令:将标志寄存器的 df 位置设置为 1
十一、pushf 和 popf
pushf 的功能是将标志寄存器的值压栈,而 popf 是从栈中弹出数据,送入标志寄存器中。
pushf 和 popf 为直接访问标志寄存器提供了一种方法。
十二、标志寄存器在 Debug 中的表示