如何在 gcc 中进行编译时计算/数学运算?



如果我编译一个具有-O2优化的程序,那么具有数学运算的任何函数都是"内联"完成的,没有物理 CPU 指令在汇编中在此处输入链接描述。所以在c有这个:

#include <stdio.h>
#include <stdlib.h>
int f(int a, int b, int c){
return a*b+c;
}
int main(){
printf("%in",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 "%in"
.section    .text.startup,"ax",@progbits
.p2align 4,,15
.globl  main
.type   main, @function
main:
.LFB23:
subq    $8, %rsp    #,
# a.c:8:    printf("%in",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

在这里你可以看到,f函数甚至不会从main调用。因此,简单地避免了该函数,并且在编译时以某种方式计算其返回值到某些指令周期。但是,当编译器不直接在 CPU 上运行时,数学计算是如何在编译时完成的,而 CPU 只进行汇编?还是编译器在编译时执行一些 cpu 任务,然后再编译为 asm?当编译器可以直接转换为操作码并执行程序而无需汇编程序的"一步"时,为什么需要asm?

编译器是一个程序,它只是执行所需的计算。 它不会模拟 CPU 这样做,此步骤(称为恒定折叠(早在生成任何指令之前就发生了。

最新更新