引言在日常的学习和工作中, 我们常常使用IDE(集成开发环境,Integrated Development Environment)进行开发,比如嵌入式经常用到的Keil, IAR等等。当我们编写一段代码后,只需要轻轻一点IDE中编译按钮,工具就会自动帮我们生成可执行文件 。IDE的“智能化”在背后帮我们做了很多工作,从一个.c源文件是如何一步一步生成可执行文件的呢? 今天我们就分析下背后的原理和过程。 编译过程分析我们还是以最经典的HelloWorld为例子,这里用C语言来编写: #include <stdio.h>int main(void){ printf('Hello World .\n'); return 0;} 编译过程可以分四个阶段:
使用-E参数来生成.i文件,具体指令:
我们用vi打开HelloWorld.i文件查看下内容: 从内容我们可以看出,短短的几行HelloWorld.c在预处理后却是高达800多行代码,其中前面的800多行都stdio.h的内容,全都包含进来了,只有最后的几行代码才是我们写的~ 相信这么大家都理解预处理的作用了吧。 2. 编译: (.i—>.s)转换为汇编语言文件 这个阶段编译器主要做词法分析,语法分析,语义分析等,检查无错误后,把代码翻译成汇编语言。 使用-S参数来生成.s文件,具体指令: gcc -S HelloWorld.i -o HelloWorld.s 我们用vi打开HelloWorld.s文件查看下内容: 可以看到.s文件的内容都是一些汇编指令,与我们的预想是一致的。 3. 汇编:(.s—>.o) 得到目标文件(在Windows中.obj文件格式,linux中.o文件) 我们知道在计算器中只认识机器语言,即0或1,因此在上一步编译得到的汇编文件(汇编本质就是机器指令的助记符,什么是助记符呢? 比如机器码1000010000101111,用asd来代替,相信大家更倾向于记asd,而不是一大串二进制码吧~~) ,而汇编就是将汇编代码转为机器代码,本质就是一种翻译的过程。 使用-c参数来生成.o文件,具体指令:
可以看到成功生成了HelloWorld.o文件, 上面说过汇编就是翻译汇编指令为机器指令, 因此.o内容都是二进制(0和1),故我们将不打开看拉~ 4. 链接:到了最后一步,并是将之前得到的各个机器代码和库文件(当然也是机器代码)按照一定规则合并成一个可执行的文件。 在gcc编译工具链中使用ld命令进行链接,考虑到链接时需要提供链接规则或指定脚本配置,这里为了简化学习,我们可以直接使用gcc工具链提供的默认规则,直接调用gcc来链接即刻。 gcc HelloWorld.o -o HelloWorld.exe 其中-o是指定生成可执行文件名(随意,如果不指定默认生成名a.out), 我们来执行下: 成功打印了“Hello world.”信息 总结好了,经过上面所述,相信大家都能清楚从一个源文件编译生成可执行文件的过程拉: 源文件(.c, .cpp) ---> 预处理(.i) ---> 编译(.s) ---> 汇编(.o) ---> 链接(elf或.exe可执行文件)。 好啦,今天的分析到此,对嵌入式,物联网感兴趣的小伙伴,记得点击收藏,转发,关注,不迷路~ |
|
来自: 天朗气清uizw04 > 《计算机》