标志寄存器
标志寄存器代表某种状态。在32位CPU中有32个不同的标志寄存器,不过不用担心,我们只关心其中的3个:ZF、OF、CF。在逆向工程中,你了解了标志寄存器就能知道程序在这一步是否会跳转,标志寄存器就是一个标志,只能是0或者1,它们决定了是否要执行某个指令。
Z-Flag(零标志):
ZF是破解中用得最多的寄存器(通常情况下占了90%),它可以设成0或者1。若上一个运算结果为0,则其值为1,否则其值为0。(你可能会问为什么‘CMP’可以操作ZF寄存器,这是因为该指令在做比较操作(等于、不等于),那什么时候结果是0什么时候是1呢?待会再说)
The O-Flag(溢出标志):
OF寄存器在逆向工程中大概占了4%,当上一步操作改变了某寄存器的最高有效位时,OF寄存器会被设置成1。例如:EAX的值为7FFFFFFFF,如果你此时再给EAX加1,OF寄存器就会被设置成1,因为此时EAX寄存器的最高有效位改变了(你可以使用电脑自带计算器将这个16进制转化成2进制看看)。还有当上一步操作产生溢出时(即算术运算超出了有符号数的表示范围),OF寄存器也会被设置成1。
The C-Flag(进位标志):
进位寄存器的使用大概占了1%,如果产生了溢出,就会被设置成1。例,假如某寄存器值为FFFFFFFF,再加上1就会产生溢出,你可以用电脑自带的计算器尝试。
CMP
CMP指令【比较】两个值并且设置CF、OF、ZF标记的值
指令 | 条件 | 标志位状态 |
---|---|---|
JA* | 如果大于就跳转(无符号) | CF=0 and ZF=0 |
JAE | 如果大于或等于就跳转(无符号) | CF=0 |
JB* | 如果小于就跳转(无符号) | CF=1 |
JBE | 如果小于或等于就跳转(无符号) | CF=1orZF=1 |
JC | 如果CF被标记就了跳转 | CF=1 |
JCXZ | 如果CX等于0就跳转 | CX=0 |
JE** | 如果相等就跳转 | ZF=1 |
JECXZ | 如果ECX等于0就跳转 | ECX=0 |
JG* | 如果大于就跳转(有符号) | ZF=0andSF=OF(SF=SignFlag) |
JGE* | 如果大于或等于就跳转(有符号) | SF=OF |
JL* | 如果小于就跳转(有符号) | SF!=OF(!=isnot) |
JLE* | 如果小于或等于就跳转(有符号 | ZF=1andOF!=OF |
JMP** | 跳转 | 强制跳转 |
JNA | 如果不大于就跳转(无符号) | CF=1orZF=1 |
JNAE | 如果不大于等于就跳转(无符号) | CF=1 |
JNB | 如果不小于就跳转(无符号) | CF=0 |
JNBE | 如果不小于等于就跳转(无符号) | CF=0andZF=0 |
JNC | 如果CF未被标记就跳转 | CF=0 |
JNE** | 如果不等于就跳转 | ZF=0 |
JNG | 如果不大于就跳转(有符号) | ZF=1orSF!=OF |
JNGE | 如果不大于等于就跳转(有符号) | SF!=OF |
JNL | 如果不小于就跳转(有符号) | SF=OF |
JNLE | 如果不小于等于就跳转(有符号) | ZF=0andSF=OF |
JNO | 如果OF未被标记就跳转 | OF=0 |
JNP | 如果PF未被标记就跳转 | PF=0 |
JNS | 如果SF未被标记就跳转 | SF=0 |
JNZ | 如果不等于0就跳转 | ZF=0 |
JO | 如果OF被标记就跳转 | OF=1 |
JP | 如果PF被标记就跳转 | PF=1 |
JPE | 如果是偶数就跳转 | PF=1 |
JPO | 如果是奇数就跳转 | PF=0 |
JS | 如果SF被标记就跳转 | SF=1 |
JZ | 如果等于0就跳转 | ZF=1 |
– | – | – |
指令
AND(逻辑与)
AND运算对两个数进行逻辑与运算。AND指令会清空OF,CF标记,设置ZF标记。
mov eax,5678912
and eax,1000
结果eax=5678000,低3位被and清零
OR (逻辑或)
OR指令对两个值进行逻辑或运算。这个指令会清空OF、CF标记,设置ZF标记
TEST(检查标志位)
这个指令99%都是用于”test eax,eax”,它执行与AND相同的功能,但是并不储存数据。如果EAX=0就会标记ZF,如果EAX不是0,就会清空ZF
XOR(逻辑非)
XOR指令对两个数进行异或操作这个指令清空OF、CF,但会标记ZF
mov eax,5678912
xor eax,eax
结果eax=0,清楚操作值为零
LEA(地址传送)
LEA可以看成和MOV差不多的指令LEA ,它本身的功能并没有被太广泛的使用,反而广泛
lea eax,dword ptr [2*edx+ebx]
将[2*edx+ebx]的地址传递给eax