被编译器隐藏的过程

86123158 2019-06-25

从一个.c文件到一个.exe文件,并不是一蹴而就的,我们在调用gcc时候,也并不是直接转化的,gcc是一个工具的集合,它会自动的调用编译器、链接器等等工具来帮助我们进行编译的转换,而一般会分为4个步骤,分别是: 预处理 编译 汇编 链接

预处理

预处理是编译开始的第一步,它主要针对于程序中#开头的各种命令

  • 展开所有的宏定义
  • 处理条件编译指令
  • 处理include预编译指令
  • 删除注释
  • 添加行号以及文件名标识

但是会保留#progma编译器指令
此时从一个.c文件就变成了一个.i文件
gcc -E main.c -o main.i

编译

  • 进行词法分析,语法分析,语义分析

词法分析---利用一个扫描器,将字符序列分割成一个个记号(例如:array 标识符,[ 左方括号)
语法分析---产生语法树,检测语法
语义分析---在语法树的基础上,加上类型,加隐式转换的节点,再次进行分析

  • 进行代码优化

源码级优化器,在下面的资料中有实际的例子,有兴趣可直接转链接

1. 删除多余的运算
 2. 代码外提,把可以在循环外面所执行的代码提出
 3. 强度削弱,将强度大的运算换算成小的运算,例如将乘法转化为加法
 4. 变换循环的控制条件,可以将原本不必要的变量直接在循环内部剔除
 5. 合并已知量和复写传播,将已知量直接替换避免计算
 6. 删除无用赋值
  • 产生相应的汇编代码源文件

代码生成器,目标代码优化器


利用ccl预处理编译程序来编译.i文件
gcc -S main.i -o main.s

汇编

  • 将汇编代码源文件翻译成机器语言
    根据各个平台不同的汇编语言来进行“翻译”
  • 利用汇编器as

gcc -c main.s -o main.o

链接

  • 合并段,进行符号解析,分配虚拟地址空间

    合并各个目标文件的.data段,.test段等等,重新调整偏移地址
      符号解析:找到符号表中的各个符号的唯一的定义
  • 进行符号的重定向

    一开始的目标文件是单独编译的,它的里面很多函数,方法并不知道存在的地址,在进行符号解析,为他们分配了虚拟地址空间之后,
      回过头来为这些符号填充上地址

gcc main.o -o main


gcc 只是一个命令,是多个编译工具的集合,它会根据参数去调用具体的工具
例如汇编时:
gcc -c main.s -o main.o
as main.s -o main.o
他们是一样的

参考博客:https://blog.csdn.net/roger_r...

相关推荐