005 普通位运算


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运算时,操作数的数据类型会影响运算结果。  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值