c语言精彩编程百例 的第三个例子 关系和逻辑运算
源程序如下:
#include<stdio.h> int main() { int logic; int a = 1; int b = 2; int c = 3; logic = a+b>c&&b<=c; printf("logic = %d\n",logic); logic = a>=b+c||b==c; printf("logic = %d\n",logic); logic = !(a<c)+b!=1&&(a+c)/2; printf("logic = %d\n",logic); return 0; }
使用gcc 3.2 编译器
gcc 03.c -S -o 003.s 生成汇编文件
logic = a+b>c&&b<=c;
movl $1, -8(%ebp) ## a
movl $2, -12(%ebp) ## b
movl $3, -16(%ebp) ## c
movl $0, -4(%ebp) ## logic
movl -12(%ebp), %eax ## b
addl -8(%ebp), %eax ## a+b
cmpl -16(%ebp), %eax ## c 和 a+b 比较
jle L4 ## 不大于则跳
movl -12(%ebp), %eax ## b
cmpl -16(%ebp), %eax ## b 和 c 比较
jg L4 ## 大于则跳转
movl $1, -4(%ebp) ## logic = 1
L4:
subl $8, %esp ##不明白为什么调整栈大小
pushl -4(%ebp)
pushl $LC0 ## 输出结果
call _printf
addl $16, %esp
按照 ((a+b)>c)&&(b<=c) 运算。
logic = a>=b+c||b==c;
movl $0, -4(%ebp) ##logic =0
movl -16(%ebp), %eax ##c
addl -12(%ebp), %eax ##b+c
cmpl %eax, -8(%ebp) ##比较a和b+c
jge L6 ## 大于等于跳
movl -12(%ebp), %eax ## b
cmpl -16(%ebp), %eax ## 比较b,c
je L6 ## 等于则跳
jmp L5
L6:
movl $1, -4(%ebp) ## logic = 1
L5:
subl $8, %esp ## 打印结果
pushl -4(%ebp)
pushl $LC0
call _printf
addl $16, %esp
按照(a>=(b+c))&&(b==c)运算
logic = !(a<c)+b!=1&&(a+c)/2;
movl $0, -4(%ebp) ## logic = 0
movl -8(%ebp), %eax ## a
cmpl -16(%ebp), %eax ## 比较c和a
jl L8 ## 小于跳
cmpl $0, -12(%ebp) ## 判断b=0
jne L9
jmp L7
L8:
cmpl $1, -12(%ebp) ## 判断 b是否为1
jne L9 ## 1 则跳
jmp L7
L9:
movl -16(%ebp), %eax ## c
movl -8(%ebp), %edx ## a
addl %eax, %edx ## c+a
movl %edx, %eax ##
sarl $31, %eax ##计算 (c+a)/2
shrl $31, %eax
leal (%eax,%edx), %eax
sarl %eax
testl %eax, %eax #测试结果
je L7
movl $1, -4(%ebp) #logic=1
L7:
subl $8, %esp #打印结果
pushl -4(%ebp)
pushl $LC0
call _printf
表达式执行为((!(a<c)+b)!=1)&&(a+c)/2)
在((!(a<c)+b)!=1)部分编译器的处理非常牛啊,他做了这样的处理如果!(a<c)成立就判断b是否为1, 如果不成立判断b是否为0. 这样就直接优化掉了 !(a<c)+b)!=1这个整体判断。 厉害!
总结:
1. 运算的优先级是比较要命的事情,最好还是用括号写清楚。
logic = !(a<c)+b!=1&&(a+c)/2; 和 logic =((!(a<c)+b)!=1)&&(a+c)/2) 在生成的汇编代码是一样的。
2. 逻辑运算在汇编中的处理方式,判断和跳转是关键。 编译器会做一些神奇的优化。