EFLAGS是x86架构中最重要的寄存器之一,它记录了CPU运算后的状态信息,并控制着CPU的某些关键行为。理解EFLAGS是编写条件分支、实现算术逻辑和控制程序流程的基石。
下图展示了EFLAGS寄存器中主要标志位的布局:

第一部分:状态标志 (Status Flags)
这些是最常用的标志,由算术或逻辑运算指令自动设置,条件跳转指令(Jxx)正是基于它们来决定是否跳转。
| 标志位 | 位 | 名称 | 触发条件(被置1) | 典型用途与解读 |
|---|---|---|---|---|
| CF | 0 | 进位标志 | 无符号运算发生进位(加法)或借位(减法)。 | 无符号数溢出判断。JC(进位跳),JNC(无进位跳)。注意:移位指令也会影响CF。 |
| PF | 2 | 奇偶标志 | 运算结果低8位中,1的个数为偶数。 | 用于早期的数据通信奇偶校验,现代编程中极少使用。 |
| AF | 4 | 辅助进位标志 | 运算时低4位向高4位发生了进位或借位。 | CPU内部用于BCD码(十进制调整)运算,汇编程序员通常不直接使用。 |
| ZF | 6 | 零标志 | 运算结果为零。 | 相等性判断的核心。CMP AX, BX后,若相等则ZF=1。JZ(为零跳)/JE(相等跳)。 |
| SF | 7 | 符号标志 | 运算结果的最高位为1(即结果为负数,如果视为有符号数)。 | 有符号数正负判断。JS(为负跳)。与OF结合判断有符号数溢出的真正结果。 |
| OF | 11 | 溢出标志 | 有符号运算的结果超出了其数据类型能表示的范围(溢出)。 | 有符号数溢出判断。JO(溢出跳)。 |
状态标志的协同应用:
- 比较两个有符号数:
CMP A, B之后:ZF=1-> A == BSF != OF-> A < B (有符号小于)SF == OF-> A > B (有符号大于)
- 比较两个无符号数:
CMP A, B之后:ZF=1-> A == BCF=1-> A < B (无符号低于)CF=0&&ZF=0-> A > B (无符号高于)
第二部分:控制标志 (Control Flags)
这些标志由程序主动设置,用于控制CPU的某些特定行为。
| 标志位 | 位 | 名称 | 作用与操作指令 |
|---|---|---|---|
| DF | 10 | 方向标志 | 控制字符串操作指令的指针移动方向。DF=0时,LODS/STOS等指令后指针递增;DF=1时递减。用CLD清零,用STD置位。 |
第三部分:系统标志 (System Flags)
这些标志通常由操作系统内核设置和管理,用于控制CPU的底层工作模式和保护机制。
| 标志位 | 位 | 名称 | 作用与权限 |
|---|---|---|---|
| TF | 8 | 陷阱标志 | TF=1时,CPU进入单步执行模式,每执行一条指令就触发一次调试异常(#DB),这是调试器的理论基础。 |
| IF | 9 | 中断允许标志 | IF=1时,CPU响应可屏蔽硬件中断(通过INTR引脚)。用STI置位,CLI清零。注:不影响不可屏蔽中断(NMI)和软件中断(INT n)。 |
| IOPL | 12-13 | I/O特权级 | 两位字段,指定当前运行程序执行IN/OUT等I/O指令所需的最低特权级(0-3)。仅CPL=0时可修改。 |
| NT | 14 | 嵌套任务标志 | 表示当前任务是否嵌套于另一个任务中,与硬件任务切换机制相关。现代操作系统较少使用。 |
| AC | 18 | 对齐检查标志 | AC=1且CR0.AM=1时,若进行未对齐的内存访问(如访问奇地址的字),会触发对齐检查异常(#AC)。用于调试。 |
| ID | 21 | 识别标志 | 若程序能置位/清除此位,则表示CPU支持CPUID指令。 |
关键操作指令
- 设置/清除标志:
STC/CLC/CMC:设置/清除/取反 CF。STD/CLD:设置/清除 DF。STI/CLI:设置/清除 IF(特权指令)。
- 标志位传送:
LAHF:将EFLAGS的低字节(含SF, ZF, AF, PF, CF)加载到AH寄存器。SAHF:将AH的值存回EFLAGS的低字节。这两条指令用于快速保存/恢复部分标志。
- 标志位栈操作:
PUSHFD/PUSHFQ:将EFLAGS/RFLAGS压栈。POPFD/POPFQ:将栈顶数据弹出到EFLAGS/RFLAGS。POPF是可以修改IF等系统标志的非特权指令,但在保护模式下使用受限。
- 条件跳转:超过30条
Jcc指令,如JZ、JNZ、JC、JNC、JO、JNO、JS、JNS等。
编程提示与常见误区
- 明确影响:不是所有指令都影响所有标志。数据传送指令(
MOV,PUSH)通常不影响任何状态标志。务必查阅指令手册。 - 区分有/无符号:
CMP之后,判断大小时必须根据数据类型的解释来选择条件码:- 有符号数:使用
JG(大于)、JL(小于)、JGE(大于等于)、JLE(小于等于)。 - 无符号数:使用
JA(高于)、JB(低于)、JAE(高于等于)、JBE(低于等于)。
- 有符号数:使用
- 注意进位与溢出:
CF和OF是独立的。例如ADD AL, 0FFh(AL=80h时),有符号运算80h+FFh=7Fh发生溢出(OF=1),无符号运算128+255未超过255(CF=0)。