C 编译过程

​ 二进制文件是通过编译生成的,编译是将人类可读的源代码(如C或C++)转化为处理器可以直接执行的机器码的过程。编译C代码包括4个阶段,分为预处理、编译、汇编和链接

image-20240710112555274

1.1 预处理阶段

​ C的源文件包含了宏(用 #define表示 )和 #include 指令(指定源文件所依赖的头文件,扩展名为 .h)。预处理阶段扩展了源文件中的所有用 #define 和 #include指令。预处理器还完整地扩展了 #define 定义的任何宏的所有用法。

1.2编译阶段

​ 编译阶段采用预处理代码并将代码转换为汇编语言,因此编译阶段的输出是以人类可读的形式进行的汇编的,其中的符号信息完整无缺。使用gcc可以dump下来这个作为中间件的汇编代码gcc -S -masm=intel firstest.c,(.s是汇编文件的常用扩展名)其中-masm=intel是让它以Intel语法去翻译汇编,而不是默认的AT&T语法。

image-20240710113928024

1.3 汇编阶段

​ 汇编阶段的输入是在编译阶段生成的汇编语言集,输出是一组对象文件,有时简称为模块。使用gcc -c firstest.c直接生成对象文件,然后使用file命令对其进行查看,其中 relocatable 表示该文件是可重定位的,LSB意味着数字在内存中的排序是以最低有效字节优先的,可重定位文件不依赖于放置在内存中的任何特定地址,它们可以随意移动,而不会破坏代码中的任何假设。当你在文件输出中看到术语“可重定位”时,你就知道你在处理的是对象文件而不是可执行文件。(.o意味object,意指对象)

image-20240710114626448

1.4链接阶段

​ 此阶段将所有对象文件链接到一个二进制可执行文件中,通常链接器与编译器互相独立,对象文件是可重定位的,因为它们是互相独立编译的,对象文件可以引用其他对象文件或程序外部库中的函数或变量,在链接之前,引用代码和数据的地址尚不清楚,因此对象文件中只包含重定位符号,这些符号指定最终如何解析函数和变量引用。在链接上下文中,依赖于重定位符号的引用称为符号引用。

​ 链接器的工作是获取属于程序的所有对象文件,并将它们合并为一个连贯的可执行文件,然后加载到特定的内存地址,直接使用gcc生成二进制可执行文件,默认情况下,可执行文件名为 a.out,./运行之后打印如下,同时查看一下文件

image-20240710134309161