您的位置:首页 > 其它

编译系统四步骤——预处理、编译、汇编、链接

2017-08-17 16:51 197 查看

编译系统

gcc编译器将C程序文件翻译成一个可执行目标文件分为四个阶段(预处理、编译、汇编、链接),执行这四个阶段的程序构成了编译系统



以上图援引自《深入理解计算机系统(原书第三版)》

C程序文件/hello.c

#include <stdio.h>

int main(int argc, const char *argv[])
{
printf("hello world\n");

return 0;
}


一. 预处理:预处理器(cpp)根据以字符#开头的命令,填充、修改、替换源C程序文件;

编译命令:
gcc -E hello.c -o hello.i


主要处理以下内容:

1.头文件包含指令,如
#include<stdio.h>
,在预处理阶段预处理器(cpp)会将系统头文件stdio.h的内容插入到源程序中去;

2.宏定义指令,如
#define N 128
,在预处理阶段预处理器(cpp)会将宏定义的常量N,全部替换成128;#undef将取消对某个宏的定义,在取消后的代码里,不会在进行替换;

3.条件编译指令,如
#ifdef、#ifndef、#if、#else、#elif、#endif
等,将不需要编译的代码过滤掉;

4.特殊符号,如
LINE、FLIE
,将被预处理器(cpp)分别替换为当前行号、当前被编译的C源程序名称;

验证:编写简单hello.c程序,执行预处理编译,然后打开生成的hello.i文件,即可看见一堆头文件理的内容(下图已将stdio.h头文件中代码插入到hello.c源程序中);



二. 编译

编译器(ccl)将hello.i翻译成汇编文件hello.s;

编译命令:
gcc -S hello.i -o hello.s


编译程序通过对hello.i文件的词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码;

下图为hello.s文件



三. 汇编

汇编器(as)将hello.s翻译成机器语言指令,并将这些指令打包成可重定位目标程序,保存在目标文件hello.o中。hello.o是一个二进制文件,打开的话是一堆乱码;

编译命令:
gcc -c hello.s -o hello.o


下图为hello.o文件



凌乱的目标文件hello.o由段构成,通常至少包含两个段(代码段和数据段)。

代码段:包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写

数据段:主要存放程序中要用到的各种全局变量或静态的数据,一般数据段都是可读可写可执行的;

—————————— 拓 展 ————————————

UNIX环境下主要有三种类型的目标文件:可重定位文件、共享目标文件、可执行文件。

四.链接

链接器(ld)将与目标文件有引用关系的文件、调用了库函数的文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。

某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。

编译命令:
gcc hello.o -o hello


下图为hello执行文件,与hello.o文件相比多出了好多乱码(此处为静态链接)



关于链接:静态链接动态链接

静态链接:在编译(由C源代码生成可执行文件,具体为链接时)环节,把所有需要的函数的二进制代码都包含到可执行文件中去;

动态链接:在可执行文件运行时,将需要的动态库加载到内存中;

具体静态与动态链接参考: http://blog.csdn.net/lisongjia123/article/details/49003159
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: