如果我使用-O2
优化来编译程序,则带有数学运算的任何函数都可以“内联”完成,而在程序集enter link description here中无需物理cpu指令。所以在c
中有此内容:
#include <stdio.h>
#include <stdlib.h>
int f(int a, int b, int c){
return a*b+c;
}
int main(){
printf("%i\n",f(1,2,4));
return 0;
}
并编译为cc -O2 -fverbose-asm -S a.c
,气体输出:
.text
.p2align 4,,15
.globl f
.type f, @function
f:
.LFB22:
# a.c:5: return a*b+c;
imull %esi, %edi # b, tmp93
# a.c:5: return a*b+c;
leal (%rdi,%rdx), %eax #, tmp92
# a.c:6: }
ret
.LFE22:
.size f, .-f
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%i\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
subq $8, %rsp #,
# a.c:8: printf("%i\n",f(1,2,4));
movl $6, %esi # HERE, I can change the value and gcc will not even notice
leaq .LC0(%rip), %rdi #,
xorl %eax, %eax #
call printf@PLT #
# a.c:10: }
xorl %eax, %eax #
addq $8, %rsp #
ret
.LFE23:
.size main, .-main
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
[这里可以看到,甚至不会从main调用f
函数。因此,可以简单地避免使用该函数,并在某些指令周期的编译时间内以某种方式计算其返回值。但是,当编译器不直接在CPU上直接运行而仅汇编时,如何在compile-time中完成数学计算?还是在编译时编译器在编译为asm之前执行一些cpu任务?为什么当编译器可以直接转换为操作码并执行程序而无需汇编程序的“分步执行”时,为什么需要asm?
编译器是一个程序,它仅执行所需的计算。它不会模拟CPU这样做,并且此步骤(称为恒定折叠)在生成任何指令之前就已经进行了很长时间。