对于 gcc 而言:
第一步 预处理
命令: gcc -E test.c-o test.i
或者 cpp -o test.i test.c (这里 cpp 不是值 c plus plus,而是 the C Preprocessor)
结果: 生成预处理后的文件 test.i(可以打开后与预处理前进行比对,当然长度会吓你
一跳)
作用: 读取 c 源程序,对伪指令和特殊符号进行处理。包括宏,条件编译,包含的头
文件,以及一些特殊符号。基本上是一个 replace 的过程。
第二步 编译及优化
命令: gcc -S test.i -o test.s 也可以直接写成 gcc -S test.i (预处理则不能写成 gcc -E
test.c)
或者 /路径/cc1 -o test.s test.i
结果: 生成汇编文件 test.s(可打开后查看源文件生成的汇编码)
作用:通过词法和语法分析,确认所有指令符合语法规则(否则报编译错),之后翻译成
对应的中间码,在 linux 中被称为 RTL(Register Transfer Language),通常是平台无关的,这
个过程也被称为编译前端。编译后端对 RTL 树进行裁减,优化,得到在目标机上可执行的
汇编代码。gcc 采用 as 作为其汇编器,所以汇编码是 AT&T 格式的,而不是 Intel 格式,所
以在用 gcc 编译嵌入式汇编时,也要采用 AT&T 格式。S 一定要为大写
第三步 汇编
命令: gcc -c test.s -o test.o 也可以直接写成 gcc -c test.s
或者 as -o test.o test.s
结果: 生成目标机器指令文件 test.o(可用 objdump 查看)
作用: 把汇编语言代码翻译成目标机器指令 , 用 file test.o 可以看到 test.o 是一个
relocatable 的 ELF 文件,通常包含.text .rodata 代码段和数据段。可用 readelf -r test.o 查看需
要 relocation 的部分。
第四步 链接
命令: gcc test.o -o test 也可以直接写成 gcc test.o
或者 ld -o test test.o
结果: 生成可执行文件 test (可用 objdump 查看)
作用: 将在一个文件中引用的符号同在另外一个文件中该符号的定义链接起来,使得
所有的这些目标文件链接成为一个能被操作系统加载到内存的执行体。(如果有不到的符号
定义,或者重复定义等,会报链接错)。用 file test 可以看到 test 是一个 executable 的 ELF 文
件。
当然链接的时候还会用到静态链接库,和动态连接库。静态库和动态库都是.o 目标文
件的集合。
静态库:
命令:ar -v -q test.a test.o
结果: 生成静态链接库 test.a
作用: 静态库是在链接过程中将相关代码提取出来加入可执行文件的库(即在链接的时