x86 64架构汇编语言

6、EFLAGS标志寄存器

1、课程目标

  • 理解EFLAGS寄存器的结构
  • 掌握常用标志位的含义
  • 理解标志位如何影响条件跳转
  • 掌握标志位操作指令

2、名词解释

标志 说明
CF 0 进位标志
PF 2 奇偶标志
AF 4 辅助进位
ZF 6 零标志
SF 7 符号标志
TF 8 陷阱标志
IF 9 中断标志
DF 10 方向标志
OF 11 溢出标志

3、代码实现

1. 标志位查看

#include <stdio.h>
#include <windows.h>

void PrintFlags(DWORD eflags) {
    printf("【EFLAGS: 0x%08X\n", eflags);
    printf("  CF=%d (Carry)\n", (eflags >> 0) & 1);
    printf("  PF=%d (Parity)\n", (eflags >> 2) & 1);
    printf("  ZF=%d (Zero)\n", (eflags >> 6) & 1);
    printf("  SF=%d (Sign)\n", (eflags >> 7) & 1);
    printf("  TF=%d (Trap)\n", (eflags >> 8) & 1);
    printf("  IF=%d (Interrupt)\n", (eflags >> 9) & 1);
    printf("  DF=%d (Direction)\n", (eflags >> 10) & 1);
    printf("  OF=%d (Overflow)\n", (eflags >> 11) & 1);
}

int main() {
    printf("=== EFLAGS标志寄存器 ===\n\n");
    
    DWORD flags;
    
    // 测试零标志
    printf("【测试ZF】0 - 0:\n");
    __asm {
        mov eax, 0
        sub eax, 0      // 结果为0, ZF=1
        pushfd
        pop flags
    }
    PrintFlags(flags);
    
    // 测试进位和溢出
    printf("\n【测试CF】FFFFFFFFh + 1:\n");
    __asm {
        mov eax, 0FFFFFFFFh
        add eax, 1      // CF=1
        pushfd
        pop flags
    }
    PrintFlags(flags);
    
    // 测试符号标志
    printf("\n【测试SF】0 - 1:\n");
    __asm {
        mov eax, 0
        sub eax, 1      // 结果为负, SF=1
        pushfd
        pop flags
    }
    PrintFlags(flags);
    
    return 0;
}

2. 标志位操作

.code
FlagOps PROC
    ; 设置/清除进位标志
    stc                 ; CF = 1
    clc                 ; CF = 0
    cmc                 ; CF = !CF
    
    ; 设置/清除方向标志
    std                 ; DF = 1 (向下)
    cld                 ; DF = 0 (向上)
    
    ; 保存和恢复标志
    pushfd              ; 压栈EFLAGS
    popfd               ; 出栈到EFLAGS
    
    ; LAHF/SAHF - 加载/存储低8位标志到AH
    lahf                ; AH = FLAGS低8位
    sahf                ; FLAGS低8位 = AH
    
    ret
FlagOps ENDP

3、课后作业

3.1、作业1:检测溢出

实现加法并通过OF检测有符号溢出。

3.2、作业2:结果分类

根据运算结果的标志位判断正数/负数/零。