从一个.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
他们是一样的
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。