Linux 编译器:GCC

  GCC是GNU编译套装,是一套由GNU开发的编程语言编译器。

1. 编译过程:

   

     中间经历的若干阶段,分别是预处理,编译,汇编,链接。

2.预处理:

  GCC在第一阶段会调用预处理器cpp来对C源程序进行预处理,所谓的预处理就是解释源程序当中所有的预处理命令,那些例如#include,#define,#if等以井号(#)开头的语句就是预处理命令,预处理命令实际上并不是C语言本身的组成部分,而是为了更好的组织程序所使用的一些“预先处理的”工作,这些工作用一种称为与处理指令的语句来描述,然后用预处理器来解释,这些工作包括我们熟悉的诸如文件包含,宏定义,条件编译等。

  这些预处理指令将会在预处理阶段被解释,比如会把文件包含语句所指定的文件复制过来,覆盖原来的#include语句,所有的宏定义被展开(因此宏展开是不占用运行时间时),所有的条件编译语句将被执行等。

  另外,在这个阶段,除了处理这些预处理指令外,GCC还会把文件中的注释删除,另外添加必要的调试信息。

3 编译:

  经过预处理后生成的.i文件依然是一个文本文件,不能被处理器直接编译,我们需要进一步的编译。接下来的编译阶段是4个阶段中最为复杂的阶段,它包括词法和语法的分析,最终生成对应硬件平台的汇编语言(不同的处理器有不同的汇编格式),具体生成什么平台的汇编文件取决于所采用的编译器,如果用的是GCC,那么将会生成x86平台的汇编文件,如果是针对ARM平台的交叉编译器,那么就会生成ARM格式的汇编文件。

4 汇编:

  接下来的步骤比较简单,编译器gcc将会调用汇编器as将汇编程序翻译为可重定义文件。汇编指令跟处理器直接运行的二进制指令流之间基本是一一对应的关系,该阶段只需要将.s文件里面的汇编翻译为指令即可。所谓重定义,指的是该文件虽然已经包含可以让处理器直接运行的指令流,但是程序中所有的全局符号尚未定位,所谓的全局符号,就是指函数和全局变量,函数和全局变量默认情况下是可以被外部文件引用的,由于定义和调用可以出现在不同的文件当中,因此他们在编译过程中需要确定其入口地址。

5 链接:

  如前面所说,经过汇编之后的可重定义文件不能直接运行,因为还有两个很重要的工作没完成,首先是重定义,其次是合并相同权限的段。一般情况下,我们编译一个程序通常要链接系统的标准C库,gcc内置库等基本库文件,因为Linux下任何一个程序编译都需要用到这些基本库的全局符号。

  链接的另一工作就是合并相同权限的段。我们知道一个可执行的镜像文件可以由多个可重定义文件链接而成,如:a.o,b.o,c.o 三个可重定义文件

猜你喜欢

转载自www.cnblogs.com/eokey/p/11771164.html