机器始源,归为“0”“1”
为什么文章标题叫做“机器始源,归为“0”“1””,且听我慢慢道来! 论程序如何成为单片机的可执行文件?
相信每一个工科生学校里面都接触过单片机这一门课,简单的说就是通过配置芯片内部已封装好的相关寄存器,来实现系统时钟、看门狗、内外部中断、PWM、GPIO的输入输出等。通过这些配置及控制就可以实现LED、电机、蜂鸣器、传感器等相关负载的运作。
1、时钟驱动程序执行
实现这些配置肯定需要程序来执行,而程序的执行就是通过系统时钟来驱动程序运行的。时钟又分为内振和外振,外振就是芯片口接外部振荡器来产生程序执行的时钟,显然内振的话就是芯片内部自带的振荡器,现在的芯片一般都支持内外振,而且可进行多个等级的时钟分频或倍频。
有了供程序运行的时钟就可以执行所编写好的代码来完成一系列的功能,但问题是完成一个功能可以有很多种不同的写法,特别对于一个大型项目来说还有许许多多的文件,这么多的文件芯片又是如何执行的呢?这就需要使用我们的编译器出马了。(注意区分编译器与编辑器的区别)
2、预处理-编译-汇编-链接
对于芯片而言其内部是由一个个的逻辑门电路组成的,我们所要执行的就是通过控制芯片GPIO输出或输入一个个的“0”或“1”电平信号来实现相应的控制功能,而我们所写的程序之所以能够在芯片上运行就是因为编译器帮我们进行了如下的转化(一般都为集成的IDE,如常用的keil,当然也有很多出名的芯片厂家开发了自家芯片的IDE,比如东芝、富士通、塞普拉斯、恩智浦等等)。
① 预处理:读取c源程序,对其中的伪指令(以# 开头的指令)和特殊符号进行处理,处理后生成“.i”为后缀的文件;
② 编译:将得到的i文件翻译成汇编语言,生成“.s”文件;
③ 汇编:把汇编语言代码翻译成目标机器指令(二进制文件)的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。
目标文件中所存放的也就是与源程序等效的目标的机器语言代码,后缀名为“.o”。
目标文件由段组成。通常一个目标文件中至少有两个段:
A.代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
B.数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读、可写、可执行的。
④ 链接:由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,将一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。通过这个过程就可生成芯片可执行的文件,根据芯片厂家的不同,后缀名可能会有所差别,比如“hex,mhx,tk”等等。
同时,根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
A.静态链接:在这种链接方式下,函数的代码将从其所在的静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
B.动态链接:在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所做的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
如上就是所编写的程序生成芯片所能执行的文件的整个过程,可以看出不管我们写的程序有多花里胡哨,最终芯片所能执行的终究是那一个个由“0”和“1”组成的二进制文件。小到单片机,大到电脑的CPU,无一例外,终究要归为“0”“1”才能发挥它应有的作用!
|