Skip to content

flags registers

如果说通用寄存器是 CPU 的“工作台”,那么标志寄存器(Flags Register)就是 CPU 的“状态面板”。

在 x86-64 架构中,它被称为 RFLAGS。它不像 RAX 那样用来存一个具体的数值(如 100),而是把 64 位拆开,每一位(Bit)代表一个“开关”。当 CPU 执行完一条指令后,会根据结果自动拨动这些开关。

这些开关(标志位)直接决定了程序接下来的走向(比如 if-else 的跳转)。


一、 标志寄存器的层级

  • FLAGS: 16 位(早期的 8086)
  • EFLAGS: 32 位
  • RFLAGS: 64 位(现代 64 位系统,高 32 位目前保留未用)

二、 最常用的“状态标志位”(重点)

作为初学者,你只需要重点掌握以下 4 到 5 个标志位,它们是汇编逻辑跳转的基石。

1. ZF (Zero Flag) —— 零标志

  • 规则:如果运算结果是 0,则 ZF = 1;如果结果不是 0,则 ZF = 0。
  • 用途:用于判断两个数是否相等。
  • 底层原理:当你执行 CMP eax, ebx 时,CPU 实际上是在做减法。如果 eax == ebx,结果就是 0,ZF 就会被置为 1。

2. CF (Carry Flag) —— 进位标志

  • 规则:在无符号数运算中,如果产生了进位(加法)或借位(减法),则 CF = 1。
  • 比喻:就像你用 8 位存数据(最大 255),算 255 + 1,结果超出了范围,CF 就会亮起,提醒你“溢出”了。

3. OF (Overflow Flag) —— 溢出标志

  • 规则:在有符号数(补码)运算中,如果结果超出了能表达的范围,则 OF = 1。
  • 区别:
    • CF 关注的是物理上的进位(针对无符号数)。
    • OF 关注的是逻辑上的错误(针对有符号数,比如两个正数相加居然得到了一个负数)。

4. SF (Sign Flag) —— 符号标志

  • 规则:结果为负数时 SF = 1,结果为正数时 SF = 0。
  • 底层原理:它其实直接复制了运算结果的最高位。

5. DF (Direction Flag) —— 方向标志

  • 规则:控制字符串操作指令(如 MOVS)。DF = 0 表示正向(地址增加),DF = 1 表示反向(地址减少)。

三、 核心指令:如何改变标志位?

并不是所有指令都会改变标志位(例如 MOV 通常不改变标志位),以下指令是改变标志位的主力军:

  1. ADD / SUB:算术运算,会影响所有的状态标志。
  2. CMP (Compare):极其重要。它的本质是 SUB,但它不保存运算结果,只为了拨动标志位。
  3. TEST:本质是 AND(逻辑与)。常用于检查某个寄存器是否为 0(例如 TEST EAX, EAX)。

四、 实战:标志位如何控制程序流程?

汇编中的“跳转指令”(Jcc)就是通过读取标志位来工作的:

指令 含义 检查的标志位
JE (Jump Equal) 相等则跳转 ZF == 1
JNE (Jump Not Equal) 不相等则跳转 ZF == 0
JG (Jump Greater) 大于则跳转(有符号) ZF == 0 且 SF == OF
JB (Jump Below) 低于则跳转(无符号) CF == 1

五、 在 GDB 中观察标志位

回到你之前的 GDB 界面。当你在 GDB TUI 模式下查看寄存器时,通常会看到一个叫 eflags 的值(例如 0x246)。

如何看懂它? 在 GDB 中,输入:

i r eflags
GDB 会友好地给你展示成这样: eflags 0x246 [ PF ZF IF ]

  • 方括号里出现的名字,说明该标志位当前为 1。
  • 没出现的名字,说明当前为 0。

六、 总结:标志位的“性格”

  1. ZF:它是最常用的。看到 JNE、JE 就要立刻想到它。
  2. CF vs OF:
    • 如果你把数字当成没有正负之分的纯二进制(无符号),看 CF。
    • 如果你把数字当成有正负之分的补码(有符号),看 OF。
  3. 标志寄存器是自动的:你不需要用 MOV 去写它,你只需要通过 CMP 或 TEST 命令“暗示” CPU 去修改它,然后用 Jcc 指令去利用它。

练习建议: 尝试修改你之前的 test.asm 代码,在 mov 后面加一行 cmp eax, 0,然后在 GDB 里单步执行,观察执行完 cmp 后,eflags 里的 ZF 是否出现了!

图示:Pasted image 20260128042431 https://i.sstatic.net/aPbbT.png