生成可执行程序的四个步骤——预处理,编译,汇编,链接

瘦欲@ 提交于 2020-02-04 15:14:57

导读

相信大家对下列这段代码都不陌生

a.c

#include<stdio.h>

int main()
{
    printf("Hello World!\n");
    return 0;
}

在Linux中,当我们使用gcc来编译这个程序时,只需使用最简单的命令

gcc -o a a.c

实际上,上述过程可以分解为4个步骤,分别是预处理(又可以被称为预编译),编译,汇编,链接

用命令来体现就是如下四个步骤:

预处理 gcc -E a.c -o a.i
编译 gcc -s a.i -o a.s
汇编 gcc -c a.s -o a.o
链接 gcc a.o -o a//gcc -o a a.o

一.预编译

预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令,比如“#include”,“#define”等,主要处理规则如下:

  • 将所有的“#define”删除,并且展开所有的宏定义。
  • 处理所有条件预编译指令,比如“#if”,“#ifdef”,“#elif”,“#else”,“#endif”。
  • 处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
  • 删除所有的注释“//”和“/**/”。
  • 添加行号和文件名标识,比如#2“a.c”2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
  • 保留所有的#pragma编译器指令,因为编译器需要使用它们。

二.编译

编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件。

三.汇编

汇编过程就是由汇编器将汇编代码转变成机器可以执行的二进制指令。

四.链接

链接的主要内存就是把各个模块之间相互引用长度部分都处理好,使得各个模块之间能够正确的衔接。简单的理解为将各个目标文件链接起来生成最终的可执行文件。

链接又分为

  • 静态链接
  • 动态链接

五.扩展

编译器编译源代码后生成的文件叫做目标文件。

目标文件除了含有汇编后的机器指令代码,数据外,还包括了链接时所需要的一些信息,比如符号表,调试信息,字符串等。一般目标文件将这些信息按不同的属性,以“节”的形式存储,有时候也叫做“段”。

程序源代码编译后的机器指令经常被放在.text段,已初始化的全局变量和局部静态变量都保存在.data段,未初始化的全局变量和局部静态变量一般放在.bss段注意,.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,它并没有内容,所以它在文件中也不占据空间.rodata段存放的是只读数据。

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!