逆向脱壳分析基础学习笔记五 标志寄存器

语言: CN / TW / HK

本文为本人在 大神论坛 逆向破解脱壳学习笔记之一,为本人对以往所学的回顾和总结,可能会有谬误之处,欢迎大家指出。

陆续将不断有笔记放出,希望能对想要入门的萌新有所帮助,一起进步

EFLAGS寄存器

进位标志CF(Carry Flag)

如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0

例子:

MOV AL,0xFF

ADD AL,1

0x80+0x40

加黑的为最高位

0x80:0 1000 0000

0x40:0 0100 0000

结果为1100 0000 最高位并没有发生变化,于是CF位为0

0x80-0x40

注意这里借位的位是1000 0000中的加黑部分

而非0 1000 0000这里的最高位

结果为0100 0000 最高位并没有发生变化,于是CF位为0

0x80-0x81

0x80:1000 0000

0x81:1000 0001

结果为1111 1111= -1,最高位被借位,于是CF位为1

奇偶标志PF(Parity Flag)

奇偶标志PF用于反映运算结果中最低有效字节中“1”的个数的奇偶性

如果“1”的个数为偶数,则PF的值为1,否则其值为0。

例:

MOV AX,803
ADD AX,1

0x803: 0000 1000 0000 0011

执行结果

0x804: 0000 1000 0000 0100 总共2个1 ,PF应为1,但实际运行结果PF为0

因为PF是根据最低有效字节来看,即804后面04的这部分

04: 0000 0100 总共1个1,所以PF为0

辅助进位标志AF(Auxiliary Carry Flag)

在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:

  • 在字操作时,发生低字节向高字节进位或借位时
  • 在字节操作时,发生低4位向高4位进位或借位时

AF与数据宽度相关

32位时 FFFF F FFF

16位时 FF F F

8位时 F F

加黑的字体为AF标志位判断的位置,如果该位置要向前进位则AF为1,否则为0,和CF相似,不过判断的位置不同

32位例:

MOV EAX,55EEFFFF

ADD EAX,2

16位例:

MOV AX,5EFE

ADD AX,2

8位例:

MOV AL,4E

ADD AL,2

零标志ZF(Zero Flag)

零标志ZF用来反映运算结果是否为0

如果运算结果为0,则其值为1,否则其值为0

作用:在判断运算结果是否为0时,可使用此标志位

例子:

XOR EAX,EAX

通过xor将eax清零,会改变zf标志位为1

MOV EAX,0

通过MOV将EAX赋值为0,非运算,不改变zf标志位

符号标志SF(Sign Flag)

符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同

例子:

MOV AL,7F
ADD AL,2

溢出标志OF(Overflow Flag)

溢出标志OF用于反映有符号数加减运算所得结果是否溢出

注意与CF区分!!!

最高位进位与溢出的区别:

进位标志表示无符号数运算结果是否超出范围.

溢出标志表示有符号数运算结果是否超出范围.

溢出主要是给有符号运算使用的,在有符号的运算中,有如下的规律:

  • 正 + 正 = 正 如果结果是负数,则说明有溢出
  • 负 + 负 = 负 如果结果是正数,则说明有溢出
  • 正 + 负 永远都不会有溢出

无符号、有符号都不溢出例

MOV AL,8
ADD AL,8

AL的数据宽度为8,即

无符号数范围为0~FF即0~255

8+8=16在0~255内 不溢出

有符号数的范围为

正数:0~7F 即0~127

负数:80~FF 即 -128~0

8+8=16 在0~127内 两正数相加结果仍为正数,不溢出

无符号溢出、有符号不溢出例

MOV AL,0FF
ADD AL,2

无符号数时

FF+2=255+2=257 在0~255外,溢出

有符号数时

FF+2=-1+2=1

正 + 负 永远都不会有溢出

无符号不溢出、有符号溢出例

MOV AL,7F
ADD AL,2

无符号数时

7F+2=127+2=129 在0~255内 不溢出

有符号数时

7F+2=0x81在80~FF (负数范围)内,两正数相加结果为负数,溢出

无符号、有符号都溢出

MOV AL,0FE
ADD AL,80

无符号数时

FE+2=254+2=256=0x100 在0~255外 溢出

有符号数时

FE+2=0x100在0~FF外,溢出

CPU如何计算OF位

首先引入两个概念:

  • 符号位有进位
  • 最高有效数值位向符号位产生的进位

对于一个有符号数:如0x80和0xC0

符号位有进位

0x80:1 000 0000

0xC0:**1 **100 0000

最高有效数值位向符号位产生的进位

0x80:1 0 00 0000

0xC0:1 1 00 0000

接下来看一组汇编指令

MOV AL,80
ADD AL,0C0

就是运算0x80+0xc0

0x80:1 0 00 0000

0xC0:1 1 00 0000

符号位1+1有产生进位,于是符号位有进位为1

最高有效数值位向符号位产生的进位0+1没有产生进位,于是最高有效数值位向符号位产生的进位为0

OF = 符号位有进位 xor 最高有效数值位向符号位产生的进位

OF = 1 xor 0 = 1 所以此时OF=1

方向标志DF(Direction Flag)

DF:方向标志位

DF=1时串操作为减地址方式 DF=0为增地址方式

下面的MOVS指令有说明DF的具体应用

相关汇编指令

ADC指令:带进位加法

格式:ADC R/M,R/M/IMM 两边不能同时为内存 数据宽度要一样

例:

MOV AL,1
MOV CL,2
手动修改CF为1
ADC AL,CL

计算结果为4,原本1+2=3,但是现在变成了4,注意与ADD的区别就在于进位

SBB指令:带借位减法

格式:SBB R/M,R/M/IMM 两边不能同时为内存 数据宽度要一样

MOV AL,4
MOV CL,2
手动修改CF为1
SBB AL,CL

计算结果为1,原本4-2=2,但是现在变成了1,注意与SUB的区别就在于进位

XCHG指令:交换数据

格式:XCHG R/M,R/M 两边不能同时为内存 数据宽度要一样

XCHG AL,CL
XCHG DWORD PTR DS:[12FFC4],EAX
XCHG BYTE PTR DS:[12FFC4],AL

例:

MOV AL,1
MOV CL,2
XCHG AL,CL

执行前:AL=1 CL=2

执行后:AL=2 CL=1

MOVS指令:移动数据 内存-内存

BYTE/WORD/DWORD

MOVS指令常用于复制字符串

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]        简写为:MOVSB
MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]        简写为:MOVSW
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]        简写为:MOVSD

例:

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

执行后,EDI内存里的值被修改为ESI内存里的值,且EDI和ESI各加4

为什么各加4?

和DOWRD数据宽度相关,如果为WORD 则各加2

为什么执行完是加而不是减?

由DF(Direction Flag)方向标志位决定,当DF位为1时为减,当DF位为0时,则为加

STOS指令

将Al/AX/EAX的值存储到[EDI]指定的内存单元,和数据宽度相关

STOS BYTE PTR ES:[EDI]                将AL存储到[EDI]
STOS WORD PTR ES:[EDI]                将AX存储到[EDI]
STOS DWORD PTR ES:[EDI]                将EAX存储到[EDI]

注意这里使用的是ES: 之前写的都是DS:

当后面为[EDI]时要使用ES: 这和后面要学的段寄存器有关,先记住

存储完数据后EDI地址的变化方向也受DF标志控制,1减0增

REP指令

按计数寄存器 (ECX) 中指定的次数重复执行指令

MOV ECX,10
REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]        也可以写成REP MOVSD

这里的10为十六进制,也就是0x10=16

代码将会重复执行16次,会不会往同一个地方覆盖?

不会,因为每执行一次EDI和ESI都会变化4,变化方向由DF决定

本系列逆向脱壳基础学习都在下方学习论坛中,欢迎加入并交流沟通

大神论坛 www.dslt.tech

版权声明:本文由 lyl610abc 原创,欢迎分享本文,转载请保留出处

「其他文章」