86123158 2019-06-25
从一个.c文件到一个.exe文件,并不是一蹴而就的,我们在调用gcc时候,也并不是直接转化的,gcc是一个工具的集合,它会自动的调用编译器、链接器等等工具来帮助我们进行编译的转换,而一般会分为4个步骤,分别是: 预处理 编译 汇编 链接
预处理是编译开始的第一步,它主要针对于程序中#开头的各种命令
但是会保留#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
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
他们是一样的