认识计算机系列1 https://blog.csdn.net/weixin_45950563/article/details/103794201
认识计算机系列2 https://blog.csdn.net/weixin_45950563/article/details/103835942
认识计算机系列3 https://blog.csdn.net/weixin_45950563/article/details/103901136
认识计算机系列4 https://blog.csdn.net/weixin_45950563/article/details/103981287
终篇
运行环境 = 操作系统 + 硬件
程序中包含着运行环境这一内容,操作系统和硬件决定了程序的运行环境。
但同一类型的硬件可以选择安装多种操作系统,比如现在大多数电脑既可以安装Windows,也可以安装Linux等操作系统,
从程序的运行环境这一角度来考量硬件时,CPU的种类是特别重要的参数。CPU只能解释其自身固有的机器语言,机器语言是唯一一种CPU能直接理解的编程语言,机器语言的程序称为本地代码。
内存中存储着程序,也就是指令和数据。CPU配合着由时钟发生器发出的滴答滴答的时钟信号,从内存中读出指令,然后再依次对其进行解释和执行,CPU通过反复进行 “读取指令”,“解释和执行指令”,“更新寄存器的值” 这3个操作,使之程序能运行起来。
程序员用C、Java等语言等编写的程序,在编写阶段仅仅是文本文件。文本文件在任何环境下都能显示和编辑。我们称之为源代码。通过对源代码进行编译,就可以得到本地代码。如在市面上出售的包含应用软件的光盘中,收录的就不是源代码,而是本地代码。
计算机的硬件并不仅仅是由CPU构成的,还包括用于存储程序指令和数据的内存,以及通过I/O连接的键盘、显示器、硬盘、打印机等外围设备,而计算机是如何控制这些外围设备的呢,Windows/linux等操作系统对克服这些硬件构成的差异做出了很大贡献,
在以前,不同的计算机中应用都是不同的,同一款软件在只能在一种机型中使用,因为应用软件的功能中,存在着直接操作计算机硬件的部分,而在Windows的应用软件中,键盘输入、显示器输出等并不是直接向硬件发送指令,而是通过向Windows发送指令,由window完成对硬件的操作,这样window的软件就可以在不同的机型上使用。
除Windows之外,还可以采用Unix系列的Linux等多个操作系统。这样,应用软件则必须根据不同的操作系统类型来专门开发。CPU的类型不同,所对应的机器语言也不同,同样的道理,操作系统的类型不同,应用程序向操作系统传递指令的途径也是不同的。应用程序向操作系统传递指令的途径称为API(Application Programming Interface应用程序接口,也称为系统调用,是指应用调用操作系统的手段)。
在同类型操作系统下,不管硬件如何,API基本上没有差别。因而,针对某特定操作系统的API所编写的程序,在任何硬件上都可以运行。由于CPU种类不同,机器语言也不相同,因此本地代码当然也是不同的。这种情况下,就需要利用能够生成各CPU专用的本地代码的编译器,来对源代码进行重新编译了。
解决这个问题的办法也有多种,例如通过对代码进行移植(Ports机制),根据不同的运行环境得到可以运行的本地代码系统,也可以通过虚拟机我们就可以在Mac操作系统上运行Windows应用,或者在window操作系统上运行linux应用,还有一种方法能够提供不依赖于特定硬件及操作系统的程序运行环境,那就是java,这个内容留在以后介绍。
从源文件到可执行文件
源代码(文本文件)完成后,就可以编译生成可执行文件了。负责实现该功能的是编译器。
用某种编程语言编写的程序就称为源代码,保存源代码的文件称为源文件,源代码是无法直接运行的,CPU能直接解析并运行的不是源代码而是本地代码的程序,本地(native)这个术语有“母语的”意思。对CPU来说,母语就是机器语言,而转换成机器语言的程序就是本地代码,用任何编程语言编写的源代码,最后都要翻译成本地代码,否则CPU就不能理解。
Windows中EXE文件的程序内容,使用的就是本地代码,你打开exe文件发现是这样的(如下图):
如果我们把刚才的EXE文件的内容Dump(十六进制表示)一下就会发现本地代码的真面目(如下图)。计算机就是把所有的信息作为数值的集合来处理的。例如,A这个字符数据就是用十六进制数41来表示的。与此相同,计算机指令也是数值的罗列。这就是本地代码。
编译器负责转换源代码
能够把C、Java等高级编程语言编写的源代码转换成本地代码的程序称为编译器,每个编写源代码的编程语言都需要其专用的编译器。例如将C语言编写的源代码转换成本地代码的编译器称为C编译器。
编译器首先读入代码的内容,然后再把源代码转换成本地代码。编译器中就好像有一个源代码同本地代码的对应表。但实际上,仅仅靠对应表是无法生成本地代码的。读入的源代码还要经过语法解析、句法解析、语义解析等,才能生成本地代码。
根据CPU类型的不同,本地代码的类型也不同。因而,编译器不仅和编程语言的种类有关,和CPU的类型也是相关的。因为编译器本身也是程序的一种,所以也需要运行环境。例如,有Windows用的C编译器、Linux用的C编译器等。
因此,编译器跟编程语言,cpu种类和运行环境息息相关。
编译器转换源代码后,就会生成本地文件。不过,此时的本地文件是无法直接运行的。因为编译后生成的不是EXE文件,而是扩展名为“.obj”的目标文件,为了得到可以运行的EXE文件,编译之后还需要进行“链接”处理,
把多个目标文件结合成一个库文件(把多个目标文件集成保存到一个文件中的形式),并生成1个EXE文件的处理就是链接,运行连接的程序就称为链接器(分静态标准函数和动态dll)。链接器指定库文件后,就会从中把需要的目标文件抽取出来,并同其他目标文件结合就生成EXE文件(如下图)。
声明:本文是根据程序是如何跑起来的书籍的总结和提炼,如有侵权联系本人删除。