标志寄存器(FLAGS)

FLAGS 寄存器(也称 PSW,程序状态字)不像其他寄存器那样存放数据,而是按位记录 CPU 执行指令后的状态信息。这些标志位决定了条件转移指令的行为。

前置知识

需要了解 01-寄存器 中 FLAGS 寄存器的基本概念,以及 08-过程调用与算术指令 中的 adc/sbb(它们依赖 CF 标志)。

标志位一览

8086 的 FLAGS 是 16 位寄存器,用到了其中 9 位:

标志名称含义
0CFCarry Flag(进位标志)无符号运算是否产生进位/借位
2PFParity Flag(奇偶标志)结果中1的个数是否为偶数
4AFAuxiliary Carry Flag辅助进位(BCD运算用)
6ZFZero Flag(零标志)运算结果是否为0
7SFSign Flag(符号标志)运算结果是否为负
8TFTrap Flag(陷阱标志)单步执行(debug的t命令使用)
9IFInterrupt Flag(中断标志)是否响应可屏蔽中断
10DFDirection Flag(方向标志)串操作方向
11OFOverflow Flag(溢出标志)有符号运算是否溢出

常用标志位详解

ZF:零标志(第6位)

记录指令执行后结果是否为 0:

  • 结果为 0 → ZF = 1
  • 结果不为 0 → ZF = 0
mov ax, 1
sub ax, 1        ; 结果为0,ZF=1

mov ax, 2
sub ax, 1        ; 结果为1,ZF=0

不是所有指令都影响标志位

movpushpop 等传送指令不影响标志位。只有运算指令(add、sub、mul、div、inc、dec、and、or 等)才会根据结果设置标志位。

PF:奇偶标志(第2位)

记录结果二进制表示中 1 的个数是否为偶数:

  • 1的个数为偶数 → PF = 1
  • 1的个数为奇数 → PF = 0
mov al, 1        ; 二进制 00000001,1个1(奇数)→ PF=0
add al, 2        ; 结果 00000011,2个1(偶数)→ PF=1

PF 主要用于通信中的奇偶校验,一般编程用得不多。

SF:符号标志(第7位)

记录有符号运算结果是否为负:

  • 结果为负(最高位为1)→ SF = 1
  • 结果非负(最高位为0)→ SF = 0
mov al, 10000001B    ; 作为有符号数是 -127
add al, 1            ; 结果 10000010B = -126,SF=1(负数)

SF 和最高位

对于有符号数,最高位就是符号位(0正1负),所以 SF 记录的就是结果的最高位值。

CF:进位标志(第0位)

记录无符号数运算时,最高有效位是否产生了进位(加法)或借位(减法):

  • 有进位/借位 → CF = 1
  • 无进位/借位 → CF = 0
; 加法进位
mov al, 98H
add al, al     ; 98H + 98H = 130H → AL=30H,CF=1(有进位到高位)
add al, al     ; 30H + 30H = 60H → AL=60H,CF=0

; 减法借位
mov al, 97H
sub al, 98H    ; 97H - 98H 需要借位 → CF=1
sub al, al     ; 0 - 0 不需要借位 → CF=0

CF 是 adc/sbb 指令的基础。

OF:溢出标志(第11位)

记录有符号数运算结果是否溢出(超出了有符号数能表示的范围):

  • 有溢出 → OF = 1
  • 无溢出 → OF = 0
mov al, 97H    ; 作为有符号数是 -105
add al, al     ; -105 + (-105) = -210,超出8位有符号数范围(-128~127) → OF=1

CF 和 OF 的区别

  • CF 关心无符号数:结果是否超过了 N 位无符号数的范围(0~2
  • OF 关心有符号数:结果是否超过了 N 位有符号数的范围(-2^(N-1)~2
  • 它们是独立判断的!同一条指令可能 CF=0 同时 OF=1(有符号溢出但无符号没进位),反之亦然。

cmp 指令:比较

cmp 是减法指令,但不保存结果,只根据减法结果设置标志位。相当于”做减法但只改标志位”。

格式:cmp 操作对象1, 操作对象2 → 计算 操作对象1 - 操作对象2

通过 cmp 设置标志位后,可以用条件转移指令判断大小关系:

有符号数比较

指令含义条件
je / jz等于(Equal/Zero)ZF=1
jne / jnz不等于ZF=0
jl / jnge小于(Less)SF≠OF
jle小于等于ZF=1 或 SF≠OF
jg / jnle大于(Greater)ZF=0 且 SF=OF
jge大于等于SF=OF

无符号数比较

指令含义条件
je / jz等于ZF=1
jne / jnz不等于ZF=0
jb / jnae低于(Below)CF=1
jbe低于等于CF=1 或 ZF=1
ja / jnbe高于(Above)CF=0 且 ZF=0
jae高于等于CF=0
; 比较 ax 和 bx,如果 ax > bx 则跳到 greater
cmp ax, bx
ja greater          ; 无符号比较用 ja/jb
; 或
jg greater          ; 有符号比较用 jg/jl

greater:
    ; ...

记忆技巧

无符号比较:a=above(大于), b=below(小于), e=equal 有符号比较:g=greater(大于), l=less(小于), e=equal 加 n 表示 not(如 jne = jump if not equal)

其他标志位

标志作用
TF(陷阱标志)TF=1 时 CPU 执行完一条指令后触发单步中断,debug 的 t 命令就是通过设置 TF 实现的
IF(中断标志)IF=1 时 CPU 响应可屏蔽中断,IF=0 时屏蔽。详见 10-中断与端口
DF(方向标志)控制串操作指令(movsb/cmpsb等)地址增减方向,DF=0时地址递增,DF=1时递减

debug 中查看标志位

在 debug 中用 r 命令查看寄存器时,最后会显示标志位状态,用字母表示:

标志置1(=1)置0(=0)
OFOVNV
SFNGPL
ZFZRNZ
PFPEPO
CFCYNC
DFDNUP
IFEIDI

相关