从源代码到可执行文件

由源代码到可执行文件

简介

C或者C++的代码变为一个可执行文件主要需要经过以下几个阶段,1)预编译,2)编译,3)汇编,4)链接。接下来我会分别介绍一下这几个阶段所完成的工作。

预编译

在预编译过程中主要处理代码文件中的以#开始的指令,如#include或者#define之类的。在预处理阶段会执行以下操作:

  • 删除所有的#define,展开所有的宏定义
  • 处理所有的条件预编译指令,如#ifdef,#if等
  • 删除所有的注释
  • 添加行号和文件名标识,从而让编译时能够产生合适的编译错误和警告信息
  • 保留所有#pragma指令,因为这些指令会执导编译器的执行

编译

编译过程会将预处理完成的文件进行词法分析、语法分析、语义分析并在进行相应的优化后产生对应的汇编代码文件。

  • 词法分析:该过程对源代码进行扫描,并将其中的字符序列分割为一系列记号
  • 语法分析:针对词法分析扫描得到的记号进行语法分析,产生语法树,语法树是一种以表达式为节点的树
  • 语义分析:对语法树进行分析,来判断其代表的表达式是否有意义
  • 优化:将语法树转换为中间代码
  • 目标代码生成:有代码生成器将中间代码转换为目标机器代码
  • 目标代码优化:对生成的目标机器代码进行优化

汇编

将汇编代码转换为机器可以执行的指令,最终生成目标文件。在生成的目标文件中除了自己的数据和机器指令外还要包含至少三张表,未解决符号表、导出符号表和地址重定向表,这三张表用于告诉连接器自己需要什么符号、自己可以提供什么符号以及本编译单元对自身地址引用的记录。

链接

链接过程会将生成的目标文件组合为一个可执行文件。由于某个目标文件可能引用其他目标文件中的某个符号,例如函数或者变量等,因此需要链接器来解决这些符号的解析。链接可以大致分为两种,第一种是静态链接:在这种链接方式下,函数的代码将从其所在的静态链接库中拷贝到最终的可执行程序中,这样程序在执行时会将这些代码装载进内存中;另一种是动态链接:这种情况下函数的代码被放到某个动态链接库中,链接程序在进行动态链接时仅会记录需要的共享的动态链接库的部分信息,在执行时动态链接库的内容将映射到相应进程的内存空间中,动态链接程序会根据可执行程序中记录的信息找到相应的函数调用入口。

引用

http://www.cnblogs.com/hongfenglee/archive/2012/02/18/2356808.html