条件码保存在条件码寄存器中,用于描述算术和最近逻辑操作的属性。最常用的条件码有:
CF:进位标志。
ZF:零标志。
SF:符号标志。
OF:溢出标志。
算术和逻辑操作指令都会修改条件码的值,但是leal指令不会修改条件码的值。
此外,cmp指令和test指令也会修改条件码。
cmp S2, S1 将S1-S2的结果与0进行比较,分别对应大于0,等于0和小于0三种情况,不同比较结果会设置不同的条件码的值。
test S2, S1 测试S1 & S2结果值,分别对应大于0,等于0和小于0三种情况,不同比较结果会设置不同的条件码的值。
set系列指令会根据条件码的值设置目的寄存器的值:
sete D,等于0,D=ZF。
setz D,与sete相同。
setne D,不等于0,D=~ZF。
setnz D,与setne相同。
sets D,负数,D=SF。
setns D,非负数,D=~SF。
setg D,有符号大于,D=~(SF ^ OF)& ~ZF。
setnle D,与setg D相同。
setge D,有符号大于等于,D=~(SF ^ OF)。
setnl D,与setge相同。
setl D,有符号小于,D=SF ^ OF。
setnge D,与setl D相同。
setle D,有符号小于等于,D=(SF ^ OF)| ZF。
setng D,与setle D相同。
seta D,无符号大于,D=~CF &~ZF。
setnbe D,与seta D相同。
setae D,无符号大于等于,D=~CF。
setnb D,与setae D相同。
setb D,无符号小于,D= CF。
setnae D,与setb D相同。
setbe D,无符号小于等于,D= CF | ZF。
setna D,与setbe相同。
示例:
char ctest_1(int a, int b)
{
char t1 = a < b;
return t1;
}
gcc -O1 -S -m32 ctest_1.c
ctest_1:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
cmpl %eax, 8(%ebp) //比较a和b
setl %al //如果a<b,al会设置成1,否则设置成0。
movzbl %al, %eax //eax的高位3字节用0来填充。
popl %ebp
ret
char ctest(int a, int b, int c)
{
char t1 = a < b;
char t2 = b < (unsigned) a;
char t3 = (short) c >= (short) a;
char t4 = (char) a != (char) c;
char t5 = c > b;
char t6 = a > 0;
return t1 + t2 + t3 + t4 + t5 + t6;
}
gcc -O1 -S -m32 ctest.c
ctest:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
movl 8(%ebp), %ebx//ebx = a
movl 12(%ebp), %ecx // ecx = b
movl 16(%ebp), %esi //esi = c
cmpl %ecx, %ebx //比较a和b
setl %al //al = (a < b) = t1
testl %ebx, %ebx //测试a的值是正数、负数还是0
setg %dl //dl = (a > 0) = t6
addl %edx, %eax //al = t1 + t6
cmpl %ebx, %ecx //比较b和a
setb %dl //dl = (b <(unsigned) a) = t2
addl %edx, %eax //al = t1 + t6+ t2
cmpl %ecx, %esi //比较c和b
setg %dl //dl = (c > b) = t5
addl %edx, %eax // al = t1 + t6 + t2 + t5
cmpw %bx, %si //把c和a强转成16位整数后进行比较
setge %dl //dl = ((short)c>=(short) a) = t3
addl %edx, %eax // al = t1 + t6+ t2 + t5 + t3
movl %esi, %edx //把c的值装入edx
cmpb %dl, %bl //把a和c强转成8位整数后进行比较
setne %dl // dl = ((char) a !=(char) c) = t4
addl %edx, %eax // al = t1 + t6+ t2 + t5 + t3 + t4
movsbl %al,%eax //对eax高位3字节用0来填充
popl %ebx
popl %esi
popl %ebp
ret