一个.c文件从程序员编写到在机器中运行需要执行以下步骤
示例代码:
#include<stdio.h>
int main()
{
printf("Hello world!\n");
reteun 0;
}
gcc编译C源码有四个步骤:
预处理 ----> 编译 ----> 汇编 ----> 链接
1. 预处理(Pre-processing)
在该阶段,编译器将C源代码中的包含的头文件如stdio.h添加进来
参数:”-E”
用法:gcc -E hello.c -o hello.i
作用:将hello.c预处理输出hello.i文件。
2. 编译(Compiling)
第二步进行的是编译阶段,在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
参数:”-S”
用法:gcc –S hello.i –o hello.s
作用:将预处理输出文件hello.i汇编成hello.s文件。
3. 汇编(Assembling)
汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码“.o”文件
参数:“-c”
用法:gcc –c hello.s –o hello.o
作用:将汇编输出文件hello.s编译输出hello.o文件。
扩展:汇编输出的.o文件属于可重定位的目标文件,后续需要经过重定位、链接以后才能形成可执行文件。在可重定位目标文件中,都是以零地址为链接起始地址进行链接的。每个目标文件中都有数据段和代码段等,在链接之后的可执行文件中只有一个代码段和数据段,这就需要连接器将各个目标文件组装在一起之后需要重新修改各个目标文件中的变量或者函数的地址,这个过程称为重定位。其中需要重定位的代码使用符号表和重定位表进行存储。
4. 链接(Link)
在成功编译之后,就进入了链接阶段。
用法:gcc hello.o –o hello
作用:将编译输出文件hello.o链接成最终可执行文件hello。
运行该可执行文件,出现正确的结果如下:
[root@localhost gcc]# ./hello
Hello World!
扩展:链接过程可分为三个步骤:分段组装、符号决议和重定位。分段组装也就是需要使用链接脚本去控制一个可执行文件的每个段的具体位置,链接脚本可以使用ld、显式链接脚本scatter等。符号决议:可以分为强符号和弱符号;重定义也就是位置偏移的过程。