C 语言精彩编程百例 第10个例子
源程序如下:
#include<stdio.h>
void main()
{
int x,y;
printf("请输入自变量 x:");
scanf("%d",&x);
if(x<6)
{
y= x-12;
printf("x=%d,y=%d\n",x,y);
}
else if(x<15)
{
y=3*x-1;
printf("*x=%d,y=%d\n",x,y);
}
else
{
y=5*x+9;
printf("*x=%d,y=%d\n",x,y);
}
}
对应的汇编内容:
subl $12, %esp
pushl $LC0
call _printf
addl $16, %esp
subl $8, %esp
leal -4(%ebp), %eax #scanf("%d",&x)
pushl %eax
pushl $LC1
call _scanf
addl $16, %esp
cmpl $5, -4(%ebp) # x 和 5 比较 , 想不到啊
jg L4 # 大于跳, 如果和4比较就是不小于跳,有jge, 或jns的吧? 为什么编译器会这么处理呢? 不明白
movl -4(%ebp), %eax # eax=x
subl $12, %eax # eax=eax-12
movl %eax, -8(%ebp) # y=eax
subl $4, %esp # printf
pushl -8(%ebp)
pushl -4(%ebp)
pushl $LC2
call _printf
addl $16, %esp
jmp L3 #退出
L4:
cmpl $14, -4(%ebp) # 和上面一样,在比较整形数据是否小于$count 时,用$count-1参与运算
jg L6
movl -4(%ebp), %eax # x=eax
movl %eax, %edx # edx=eax
addl %edx, %edx # edx*2
addl %eax, %edx # edx+eax ; 计算3*x, 貌似addl imull快所以~~ , 这个时候 addl %edx,%edx 是 4*x
leal -1(%edx), %eax # %eax = %edx -1; 这个... lea是取有效地址的,但在这里它用来做数学运算了. 由于lea 是取出偏移地址的,所以 %eax中得到的是按照取偏移地址算出的值。
movl %eax, -8(%ebp) # y = %eax
subl $4, %esp # printf
pushl -8(%ebp)
pushl -4(%ebp)
pushl $LC3
call _printf
addl $16, %esp
jmp L3 # 退出
L6:
movl -4(%ebp), %eax # %eax=x
movl %eax, %edx # %edx =%eax
sall $2, %edx # %edx=%edx<<2 ; 相当于 edx*4
addl %eax, %edx # %edx=%edx+eax ; 相当于 edx*5
leal 9(%edx), %eax # %eax=%edx+9
movl %eax, -8(%ebp) # y=%eax
subl $4, %esp # printf
pushl -8(%ebp)
pushl -4(%ebp)
pushl $LC3
call _printf
addl $16, %esp
L3:
leave
ret
1. else if 和 第9个例子 if语句 在处理上没有多大的差别。
2. 编译器在处理比较大小时,很有意思的优化:在比较整形数据是否小于$count 时,用$count-1参与运算, 估计大于也会使用类似的思路。
3. 用lea 是取出偏移地址指令,按照取偏移地址算出的值做数学运算。编译器不是每个数学运算都选择这种方式,估计这个方式效率也是有问题的。