AI摘要

本文详细介绍了计算机编程中的寄存器、堆栈和标志寄存器的相关知识。文章首先解释了push和pop指令如何影响栈顶指针,然后讨论了PE、下断点、WIN32 API、函数调用和堆栈图的绘制。接着,文章深入探讨了标志寄存器中的各个标志位,如CF、PF、AF、ZF、SF和OF,并解释了它们在不同情况下的含义。文章还列举了会改变标志位的指令,包括算术运算、逻辑运算和移位/循环移位指令。最后,文章介绍了一些具体的指令,如ADC、SBB、XCHG、MOVS、STOS和REP,并解释了它们的作用和执行流程。

push 16位寄存器 栈顶+2
push 8位 16位 32位立即数 栈顶+4
push 16位内存数据 栈顶+2
push 32位内存数据 栈顶+4
Pushad
一次性把 8 个 32 位通用寄存器全部压入栈,用来保存现场
popad
一次性把 8 个 32 位通用寄存器全部弹入栈,用来还原现场。
1.PE
2.下断点
3.WIN32 api
4.什么是函数调用
5.熟悉堆栈-画过堆栈图
一个程序执行之前栈顶存放着执行这个程序的返回地址
6.call jcc
标志寄存器->jcc->程序的走向
image.png
CF PF AF ZF SF OF 背 熟记第几位
0 2 4 6 7 11

CF进位标志位

最高位产生了进位或者借位 为1 else 0
EFLAGS 寄存器标志位
00000246 =>001001000110
CF = 0
PF = 1
AF = 0
ZF = 1
SF = 0
OF = 0

PF 奇偶标志位

反映二进制结果中的“1”的个数的奇偶性 如果1是偶数 PF=1 else PF = 0
只看运算结果的「最低有效字节」里,1 的个数是偶数还是奇数。

规则:

  • 最低字节中 1 的个数为偶数PF = 1
  • 最低字节中 1 的个数为奇数PF = 0

哪怕是 16 位、32 位、64 位运算,PF 也只关心最后 8 位,高位全部忽略。

会改变标志位的指令

这些指令执行后,ZF、SF、CF、OF、PF、AF 都会被更新

  1. 算术运算

    • ADDADC
    • SUBSBBCMP
    • INCDEC
    • NEG
    • MULIMUL
    • DIVIDIV
  2. 逻辑运算

    • ANDORXORNOT
    • TEST
  3. 移位 / 循环移位

    • SHLSHRSALSAR
    • ROLRORRCLRCR

AF辅助进位标志位

在以下情况发生时候为1 否则为0
在进行四字节操作时候,发生低字向高字进位
在进行字操作时候,发生低字节向高字节进位
在进行字节操作时候,发生低4位向高4位进位

ZF反映运算结果是否为0

如果运算结果为0 则ZF为1否则为0
Xor eax,eax

SF符号标志位

符号标志SF用来反映运算结果的符号位 他与运算结果的最高位相同
7F+2 = 81h->10000001
最高位 = 1 → SF=1(表示这个结果作为有符号数是负数)

OF溢出标志位

正数 + 正数,结果跑到负数区 = 溢出

负数 + 负数,结果跑到正数区 = 溢出
正数 + 负数,永远不会有溢出
1000 0000->80
1100 0000->C0 ->-40h
符号位有进位 1
最高有效数值位向符号位产生的进位 0
1 xor 0 =/=1 of = 1

homework

无符号数、有符号数都不会溢出
mov al,8
ad al,8
如果是无符号数,那么就看 CF标志位 即原数是否超过数据宽度最大值
如果是有符号数,那么看OF标志位 即原数是否超过数据宽度正数的最大值
无符号数溢出,有符号数不溢出
mov al,0xff
mov al,2
无符号数不溢出,有符号数溢出
mov al,0x7f
add al,2
无符号、有符号都溢出
adc 带进位加法
ADC R/M,R/M/IMM
意思就是如果俩个操作数会产生进位 那么目标操作数 = 源操作数+CF位
SBB 带进位减法
SBB R/M,R/M/IMM
意思就是如果俩个操作数会产生进位 那么目标操作数 = 源操作数-CF位
XCHG 交换俩个寄存器或者内存的值
XCHG R/M,R/M
MOVS 移动数据 内存-内存
byte/WORD/DWORD
MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
MOVS WORD PTR ES: [EDI],BYTE PTR DS: [ESI]
MOVS DWORD PTR ES:[EDI],BYTE PTR DS: [ESI]
movsb
DS:SI 指向的 1 个字节数据,传送到 ES:DI 指向的内存单元,然后根据方向标志位 DF 自动修改 SIDI 的值。

执行流程(固定逻辑)

  1. 取源字节:(ES:DI) = (DS:SI) 也就是根据命令要求长度将esi赋值给edi
  2. 修改地址指针:

    • DF=0正向传送,默认):SI += 1DI += 1 根据宽度加1 2 4
    • DF=1反向传送):SI -= 1DI -= 1根据宽度加1 2 4
低地址 → 高地址SI+1,DI+1正向传送
高地址 → 低地址SI-1,DI-1反向传送

STOS指令 将AL/AX/EAX的值存储到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI]
简写为STOSB AL
STOS WORD PTR ES: [EDI]
简写为STOSW AX
STOS DWORD PTR ES:[EDI]
简写为STOSD EAX
修改地址指针 DI


- **DF=0(CLD,正向)** → `DI += 数据长度`(+1 / +2 / +4)
- **DF=1(STD,反向)** → `DI -= 数据长度`(-1 / -2 / -4)

REP指令 按计数寄存器(ecx)中指定的次数重复执行字符串指令
MOV RCX,10
rep movsd //根据ecx的值决定movsd的执行次数
rep stosd //根据ecx的值决定stosd的执行次数
image.png

  1. 只影响CF位 需注意OF PF AF位
    image.png
  2. 只影响PF位(二进制1为偶数个)
    image.png
  3. 只影响AF位
    image.png
  4. .只影响SF位
    image.png
  5. 只影响OF位
    image.png
    我试了很多的算数指令 都会有类似SF改变的情况 溢出有俩个条件 ① 正数+正数=负数 ② 负数+负数=正数 ① 会SF = 1 ②CF= 1
  6. movs分别移动五个字节 五个字 五个双字
    byte.png
    image.png
    **字和双字
  7. stos
    image.png
  8. 用rep指令重写7 8题
    image.png
END
本文作者: 文章标题:滴水逆向三期-标志寄存器
本文地址:https://blog.cvpotato.cn/Reversenote/34.html
版权说明:若无注明,本文皆INT3 blog原创,转载请保留文章出处。
最后修改:2026 年 04 月 02 日
如果觉得我的文章对你有用,请随意赞赏