![8f4a4d1acb05af65eac945a5b3f757b4.png](https://i-blog.csdnimg.cn/blog_migrate/37743b09af33193360d676ec45f8c3b2.jpeg)
我们从事单片机开发的时候,往往只会接触到应用层的开发。使用的IDE软件(如keil,IAR等)集成度非常高,因此可能只要会C语言,编译完没问题就可以烧录了。但是如果想要在后期从事如Linux系统移植或者开发,那么光知道C语言编写是远远不够的。
我们编写的C语言程序并不能被我们的单片机识别,因此我们在烧录的时候肯定是不会直接烧录C程序的,肯定要把C语言变成我们单片机能看懂的语言才行。其实任何嵌入式芯片,C程序至芯片可执行程序都会经过以下几个步骤:
1. 预处理:预处理其实就是对程序中的伪指令(以#开头的指令)和特殊符号进行处理的过程。在语言中有#define定义,有#if条件编译指令,或者一些注释等就是在这个期间进行处理的。如果以上你都没接触过,那么包含头文件#include,这个总遇到过吧,预处理也会处理#include后的头文件。
2. 编译:这个词可能你听说过,但是可能不清楚它的具体意义。编译是把预处理的文件进行一系列的语法分析、词法分析、语义分析以及优化成相应的汇编代码。我们在经常在keil等软件中进行编译,而编译后会提示有错误或者有警告,这就是编译的效果,它会提示你的程序中可能有语法错误,比如代码末尾忘记写“;”或者有些变量没定义之类的问题。
3. 汇编:编译好以后的文件其实已经生成了汇编文件。在高级语言没有问世的时候,程序员们都是通过汇编编写的代码(比如现在很牛逼的小米公司老总雷军),因为汇编其实是一种低级的通用编程语言。对汇编文件进行汇编后生成的其实就是二进制文件了。聪明的你可能已经预感到了,到了二进制文件,离芯片识别代码已经不远了,别急,还有一步。
4. 链接:链接是代码变成可执行文件前的最后一步。它主要是解决多个文件之间符号的引用问题。比如你在一个文件里定义了一个全局变量,而另外一个文件中也引用了这个变量,这个时候链接就会把这两个文件连接到一起。我们平常在单片机编程时会使用printf这个函数,但是你会发现,我们自己编写的代码中根本没有对printf定义过,其实printf的定义是在其他的库文件中,这个时候,链接器会帮我们自动去链接该文件,确保我们能够使用printf函数。
链接成功后,其实就生成可执行文件了。我们在用keil或者IAR等开发时,可能并不接触到这些过程,那是因为这些软件已经集成了编译器和链接器,不需要我们去操心,但并不表示这个过程不存在。下图是我在keil编译好以后生成的一些中间文件,你会发现有很多.i,.o等文件格式文件存在。其实.i就是预处理后的文件格式,.o其实就是汇编后的文件格式。
![3937daf604c7cc37fc4abb2b043304ef.png](https://i-blog.csdnimg.cn/blog_migrate/45270aeeb83a3b9dbcad5c61f392897f.png)
本文只是对C程序至单片机可执行文件做一个科普,对于可能只需要单片机开发者来说也许用不着学习这么多,毕竟现在的IDE已经很强大了,无需用户去了解这些过程。但是对于后期想在嵌入式领域继续研究深造的人来说,这个可是入门级的哦。