高级语言编写的程序想在操作系统运行,需要被翻译为机器指令,在按照可执行目标文件格式打包并以二进制形式存储在文件中
编译器作用:把高级语言编写的程序转换为目标语言编写的程序
编译器的结构可分为前端(Frontend)和后端(Backend)两部分
编译过程大概有下面五个部分:
测试代码 hello.c
#include<stdio.h>
int main()
{
printf("Hello World!\n");
}
编译时添加"-save-temps"和"--verbose"编译选项
编译hello.c
gcc hello.c -o -save-temps --verbose
GCC的编译经过四个阶段:预处理(Preprocess),编译(Compile),汇编(Assemble),链接(Link)
cc1是编译器,对应一二阶段,hello.c ---> hello.s
as是汇编器,对应第三阶段,hello.s ---> hellos.o
collect2链接器,对应第四阶段,把程序运行库(CRT)中的目标文件(crt1.o,文件以.o结尾)和动态链接库(libgcc.so,文件以.so结尾)链接到hello
主要处理源代码的 "#include","#define"这样的预处理指令,转换后插入程序文本得到 .i 文件
gcc -E参数:可以单独处理预处理过程
gcc -E hello.c -o hello.i
程序处理规则:
可以查看文件的类型
对 .i 文件分析词法,语法,语义以及优化,生成汇编代码
gcc -S:单独处理编译阶段,这个指令包含预处理和编译阶段
gcc -S hello.c -o hello.s
汇编器会把根据汇编指令和机器指令的对照表进行编译,生成.o文件
gcc -C:操作对象可以是.c
gcc -c hello.c -o hello.o
.o是一个可重定向文件,使用objdump命令可查看
objdump -sd hello.o -M intel
objdump是一个反汇编工具,用于查看二进制可执行文件或目标文件的汇编代码。通过使用-sd选项,可以显示详细的符号表和反汇编代码。-M intel选项指定以 Intel 格式显示汇编代码。
输出结果将包含以下信息:
此时由于还未Link,对象文件中符号的虚拟地址无法确定。
把目标文件及其依赖库进行链接,生成可执行文件;链接操作由链接器(id.so)完成,主要工作是地址和空间重新分配,符号绑定和重定位操作;链接有静态,动态两种,gcc默认动态;-static 可指定使用静态链接。
gcc hello.o -o hello -static
通过链接操作,对象文件无法确定的符号,地址都已修正,程序可加载到内存正常执行。
linux可执行文件是elf格式,对应的二进制特征 7F 45 4C 46