C语言精彩编程百例 第5个例子。
源程序如下:
#include<stdio.h>
void main()
{
unsigned char result;
int a,b,c,d;
a=2;
b=4;
c=6;
d=8;
result =a&c;
printf("result=%d\n",result);
result =b|d;
printf("result=%d\n",result);
result =a^d;
printf("result=%d\n",result);
result =~a;
printf("result=%d\n",result);
}
变量赋值部分
movl $2, -8(%ebp) ## a
movl $4, -12(%ebp) ## b
movl $6, -16(%ebp) ## c
movl $8, -20(%ebp) ## d
result =a&c;printf("result=%d\n",result);
movb -16(%ebp), %al ## c
andl -8(%ebp), %eax ## a & c
movb %al, -1(%ebp)
subl $8, %esp
##movl $0, %eax ## 编译器生成了这2句被我注释掉了,结果不变
##movb -1(%ebp), %al ## 编译器生成了这2句被我注释掉了,结果不变
pushl %eax
pushl $LC0
call _printf
addl $16, %esp
这部分的运算过程还算比较简单, c语言的 & 运算符,在汇编中用 and指令转换。编译器根据数据类型选择了andl。
编译器将运算结果从al寄存器保存到内存后,又对eax进行了清零,然后从内从将运算结果再放回eax, 给printf传递参数。对eax清零,然后再从内存把运算结果放回eax没有什么实际变化,我手工注释掉了这句,结果不变。 目前尚不清楚编译器的目的。
result =b|d;printf("result=%d\n",result);
movb -20(%ebp), %al ## d
orl -12(%ebp), %eax ## d | b
movb %al, -1(%ebp)
subl $8, %esp
#movl $0, %eax ## 编译器生成了这2句被我注释掉了,结果不变
#movb -1(%ebp), %al ## 编译器生成了这2句被我注释掉了,结果不变
pushl %eax
pushl $LC0
call _printf
addl $16, %esp
或运算 | ,在汇编中使用 or , 和上面的 and 基本一样。 编译器的处理方法也是一样的。
result =a^d;printf("result=%d\n",result);
movb -20(%ebp), %al ## d
xorl -8(%ebp), %eax ## a ^ d
movb %al, -1(%ebp)
subl $8, %esp
##movl $0, %eax ## 编译器生成了这2句被我注释掉了,结果不变
##movb -1(%ebp), %al ## 编译器生成了这2句被我注释掉了,结果不变
pushl %eax
pushl $LC0
call _printf
addl $16, %esp
异或 ^ 在汇编中表示为xor 情况一致。
result =~a;printf("result=%d\n",result);
movb -8(%ebp), %al ## a
notl %eax ## ~a
movb %al, -1(%ebp)
andl $255,%eax ## 编译器没有这句 如果删除movl $0, %eax movb -1(%ebp), %al 就要添加
subl $8, %esp
##movl $0, %eax ## 编译器生成了这2句被我注释掉了,结果会变,需添加andl $255,%eax
##movb -1(%ebp), %al ## 编译器生成了这2句被我注释掉了,结果会变,需添加andl $255,%eax
pushl %eax
pushl $LC0
call _printf
addl $16, %esp
这个和前面3个例子不同,如果删掉将运算结果从al寄存器保存到内存后,又对eax进行了清零,然后从内从将运算结果再放回eax,的两句汇编指令,运算结果发生变化。
我理解: and , or ,xor 的运算结果中,eax的高16位和ah 都保持了0。 但notl %eax 运算结果eax的高16位和ah将会是1, 但实际运算结果是在al中的,我们传递给printf的参数是eax,这就导致我们必须在printf前将eax的高16位和ah置为0, 我这里添加了andl $255,%eax。 运算效果保持了一致。
由此看来movl $0, %eax ,movb -1(%ebp), %al是printf函数在接受8位参数时处理办法。
and, or ,xor 运算不管数据前面有几个零问题都不大, 但not会吧高位的0变成1。所以在not运算时,操作数的数据类型会影响运算结果。