转自:http://blog.csdn.net/javajiawei/article/details/61914253
本文主要分享一下自己对于源代码到可执行程序中间的一些过程的理解。
以前我在windows上面使用微软的那一套IDE环境,将源代码编译生成最后的可执行程序,很方便,很少去关注从源代码到最后的可执行程序这个过程中究竟发生了哪些事情。直到开始在linux平台上面写程序,才逐渐了解这个过程,简单记录一下自己的学习过程。以下面简单的test.c程序为例说明整个过程。
以前我在windows上面使用微软的那一套IDE环境,将源代码编译生成最后的可执行程序,很方便,很少去关注从源代码到最后的可执行程序这个过程中究竟发生了哪些事情。直到开始在linux平台上面写程序,才逐渐了解这个过程,简单记录一下自己的学习过程。以下面简单的test.c程序为例说明整个过程。
#include<stdio.h>
#include<stdlib.h>
//可打印字符串
#define PRINTSTR "Hello World"
int main(int argc,char **argv)
{
printf(PRINTSTR"\n");
exit(0);
}
下图的过程就是在 Linux 上面的编译执行过程。
直接使用gcc编译,则会生成默认的可执行文件a.out,如果想要指定生成文件名,则使用-o选项进行指定,这里面指定生成的文件名为test.exe。
使用man gcc来查看,gcc不仅包括了-o选项,还包括了-E,-S,-c等选项。而执行这些选项,则能够更加直观的了解从源码到可执行文件的不同阶段。
gcc test.c 主要包括1、预处理;2、编译;3、汇编;4、链接这四个阶段。
预处理:
编译:
gcc -S test.c -o test.S生成的test.S是编译生成的汇编指令文件,可以看到生成了一堆汇编指令代码。
汇编:
gcc -c test.S -o test 生成test是机器指令文件。这时候执行./test会提示该文件是不可执行的二进制文件,因为还需要最后一步的链接工作,也就是文件不齐全。
链接:
无论是动态的链接还是静态的链接就是把程序所需要的文件统一起来,生成最终的可执行文件。虽然我们只有test.c这一个文件,但是让程序跑起来,还是需要诸如程序的启动,结束等目标文件,如图中的crt1.o, crti.o等文件,因此链接命令需要将这些目标文件进行统一。这也是为什么上面的test文件运行不起来的原因,因为找不到程序的入口地址。
以上的四个步骤gcc test.c -o test.exe就可以直接搞定,但是通过上述的分解,我对整个编译的过程有了更多的了解。其实gcc是完成了对预处理器,编译器,汇编器以及连接器的封装工作。