From:https://blog.csdn.net/zz709196484/article/details/77755243
看过破解教程,都知道 test,cmp 是比较关键,可是我一直不清楚它们究竟是怎么比较的,最后下决心找了很多资料,和大家一起把它们弄清楚.
首先看看:状态寄存器(即标志寄存器)
PSW(Program Flag)程序状态字(即标志)寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,
如下所示:
条件码:
- ① OF(Overflow Flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配.
- ② SF(Sign Flag)符号标志,结果为负时置1,否则置0.
- ③ ZF(Zero Flag)零标志,运算结果为0时置1,否则置0.
- ④ CF(Carry Flag)进位标志,进位时置1,否则置0.注意:Carry标志中存放计算后最右的位.
- ⑤ AF(Auxiliary carry Flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。有进位时1,否则置0.
- ⑥ PF(Parity Flag)奇偶标志.结果操作数中1的个数为偶数时置1,否则置0.
控制标志位:
- ⑦ DF(Direction Flag)方向标志,在串处理指令中控制信息的方向。
- ⑧ IF(Interrupt Flag)中断标志。
- ⑨ TF(Trap Flag)陷井标志。
为举例方便说一下 jnz 和 jz 。测试条件:
JZ ZF=1 即 Jz =jump if ZF ( 结果为 0, 则设置 ZF 零标志为 1,跳转)
JNZ ZF=0 即 Jnz=jump if not ZF ( 结果不为 0,则设置 ZF 为 0 (0表示假) )
好,接着来看 test 和 cmp
test 指令
test 属于逻辑运算指令 (逻辑 与 )
功能: 执行BIT与BIT之间的逻辑运算
测试(两操作数作与运算,仅修改标志位,不回送结果).
Test 对两个参数(目标,源)执行AND逻辑操作,并根据结果设置标志寄存器,结果本身不会保存。
TEST AX,BX 与 AND AX,BX 命令有相同效果
语法: TEST r/m,r/m/data
影响标志: C,O,P,Z,S (其中 C 与 O 两个标志会被设为 0)
运用举例:
1.Test 用来测试一个位,
例如寄存器:
test eax, 100b; b后缀意为二进制
jnz **; 如果eax右数第三个位为1,jnz将会跳转
jnz 跳转的条件是 ZF=0,ZF=0 意味着ZF(零标志)没被置位,即逻辑与结果为1.
2.Test的一个非常普遍的用法是用来测试一个寄存器是否为空:
test ecx, ecx
jz somewhere
如果 ecx 为零,设置 ZF 零标志为1,Jz跳转
CMP 属于算术运算指令
功能: 比较两个值(寄存器,内存,直接数值)
语法: CMP r/m,r/m/data
标志位: C,P,A,Z,O
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
cmp 实际上是只设置标志不保存结构的减法,并设置Z-flag(零标志).
零标志很像carry,也是内部标志寄存器的一位.
例如:
cmp eax, 2; 如果 eax-2=0 即 eax=2 就设置零标志为1
Jz **; 如果设置了零标志就跳转
结论:
- test 逻辑与运算结果为零,就把 ZF(零标志)置 1
- cmp 算术减法运算结果为零,就把 ZF(零标志)置 1