关系运算符的运算结果只有0和1
关系运算符 | 含义 |
---|---|
== | 等于(a==b) |
!= | 不等于(a!=b) |
>= | 大于等于(a>=b) |
<= | 小于等于(a<=b) |
> | 大于(a>b) |
< | 小于(a<b) |
set指令:
功能: 若条件(标志位的值)成立,则字节寄存器reg8或字节存储器单元被设置为1,否则被设置为0.条件见下表:
指令 | 含义 | 标志位 |
---|---|---|
SETBE/SETNA | 小于等于/不大于 | CF=1 或 ZF=1 |
SETE/SETZ | 等于/为零 | ZF=1 |
SETNE/SETNZ | 不等于/不为零 | ZF=0 |
SETG/SETNLE | 大于/不小于等于(有符号) | SF=0 且 ZF=0 |
SETGE/SETNL | 大于等于/不小于(有符号) | SF=0 |
SETL/SETNGE | 小于/不大于等于(有符号) | SF=1 |
SETLE/SETNG | 小于等于/不大于(有符号) | SF=1 或 ZF=1 |
SETC | 有进位或借位 | CF=1 |
SETNC | 无进位或借位 | CF=0 |
SETO | 有溢出 | OF=1 |
SETNO | 无溢出 | OF=0 |
SETP/SETPE | 低8位1的个数为偶数 | PF=1 |
SETNP/SETPO | 低8位1的个数为奇数 | PF=0 |
SETS | 结果为负 | SF=1 |
SETNS | 结果为正 | SF=0 |
其中在CE中SETNC指令相当于SETNE,一般都会把SETNE写成SETNC。
例如:
CMP EAX,EBX
SETNC CL //如果EAX不=EBX,那么CL=01,否则CL=00
CMP EAX,ECX
SETE [20401000] //如果EAX=ECX,那么0x20401000处=01,否则=00
注意目标为地址时,不需要用 XXXX PTR 来区分数据的操作长度。
同样在修改时,如果不知道前面判定的结果会是什么,那么可以直接把
SETE AL改成MOV AL,01或者是MOV AL,00这两种指令,来看游戏中的实际影响。
SETE AL指令占3字节,MOV AL,01指令占2字节,再补上一个NOP指令,正好可以替换
关系运算符汇编代码:
//"=="运算符
void Function()
{
int a = 10;
int b = 20;
int c = a==b;
//汇编代码为:
//mov dword ptr [ebp-4],0Ah int a = 10;
//mov dword ptr [ebp-8],14h int b = 20;
//mov eax,dword ptr [ebp-4] 将a的值10放入eax中
//xor ecx,ecx ecx置零
//cmp eax,dword ptr [ebp-8] a减去b不保存结果,只影响标志位
//sete cl 如果zf=1则将cl的值设置为1,这里zf=0,所以ecx的值还是0
//mov dword ptr [ebp-0Ch],ecx 将ecx的值给变量C,这里ecx=0,所以C=0;
}
//"!="运算符
void Function()
{
int a = 10;
int b = 20;
int c = a!=b;
//汇编代码为:
//mov dword ptr [ebp-4],0Ah
//mov dword ptr [ebp-8],14h
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx
//cmp eax,dword ptr [ebp-8]
//setne cl 如果zf=0则将cl设置为1.这里zf=0,ecx=1
//mov dword ptr [ebp-0Ch],ecx ecx=1,c=ecx,c=1;
}
//">"运算符
void Function()
{
int a = 1;
int b = 2;
int c = a > b;
//汇编代码:
//mov dword ptr [ebp-4],1
//mov dword ptr [ebp-8],2
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx
//cmp eax,dword ptr [ebp-8]
//setg cl 如果sf=0且zf=0,则cl设置为1,这里sf=1,ecx=0
//mov dword ptr [ebp-0Ch],ecx c = 0
}
//"<"运算符
void Function()
{
int a = 1;
int b = 2;
int c = a < b;
//汇编代码:
//mov dword ptr [ebp-4],1
//mov dword ptr [ebp-8],2
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx
//cmp eax,dword ptr [ebp-8]
//setl cl 如果sf=1,则cl设置为1,这里sf=1,ecx=1
//mov dword ptr [ebp-0Ch],ecx c = 1
}
//">="运算符
void Function()
{
int a = 1;
int b = 2;
int c = a >= b;
//汇编代码:
//mov dword ptr [ebp-4],1
//mov dword ptr [ebp-8],2
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx
//cmp eax,dword ptr [ebp-8]
//setge cl 如果sf=0,则cl设置为1,这里sf=1,ecx=0
//mov dword ptr [ebp-0Ch],ecx c=0
}
//"<="运算符
void Function()
{
int a = 1;
int b = 2;
int c = a <= b;
//汇编代码:
//mov dword ptr [ebp-4],1
//mov dword ptr [ebp-8],2
//mov eax,dword ptr [ebp-4]
//xor ecx,ecx
//cmp eax,dword ptr [ebp-8]
//setle cl 如果sf=1或zf=1,则cl设置为1,这里sf=1,ecx=1
//mov dword ptr [ebp-0Ch],ecx c=1
}