自己动手构造编译系统:编译、汇编与链接1.2 历史渊源-阿里云开发者社区

开发者社区> 华章出版社> 正文

自己动手构造编译系统:编译、汇编与链接1.2 历史渊源

简介:

1.2  历史渊源

  

   历史上很多新鲜事物的出现都不是偶然的,计算机学科的技术和知识如此,编译系统也不例外,它的产生来源于编程工作的需求。编程本质上是人与计算机交流,人们使用计算机解决问题,必须把问题转化为计算机所能理解的方式。当问题规模逐渐增大时,编程的劳动量自然会变得繁重。编译系统的出现在一定程度上降低了编程的难度和复杂度。

  在计算机刚刚诞生的年代,人们只能通过二进制机器指令指挥计算机工作,计算机程序是依靠人工拨动计算机控制面板上的开关被输入到计算机内部的。后来人们想到使用穿孔卡片来代替原始的开关输入,用卡片上穿孔的有无表示计算机世界的“0”和“1”,让计算机自动读取穿孔卡片实现程序的录入,这里录入的指令就是常说的二进制代码。然而这种编程工作在现在看起来简直就是一个“噩梦”,因为一旦穿孔卡片的制作出现错误,所有的工作都要重新来过。

  人们很快就发现了使用二进制代码控制计算机的不足,因为人工输入二进制指令的错误率实在太高了。为了解决这个问题,人们用一系列简单明了的助记符代替计算机的二进制指令,即我们熟知的汇编语言。可是计算机只能识别二进制指令,因此需要一个已有的程序自动完成汇编语言到二进制指令的翻译工作,于是汇编器就产生了。程序员只需要写出汇编代码,然后交给汇编器进行翻译,生成二进制代码。因此,汇编器将程序员从烦琐的二进制代码中解脱出来。

  使用汇编器提高了编程的效率,使得人们有能力处理更复杂的计算问题。随着计算问题复杂度的提高,编程中出现了大量的重复代码。人们不愿意进行重复的劳动,于是就想办法将公共的代码提取出来,汇编成独立的模块存储在目标文件中,甚至将同一类的目标文件打包成库。由于原本写在同一个文件内的代码被分割到多个文件中,那么最终还需要将这些分离的文件拼装起来形成完整的可执行代码。但是事情并没有那么简单,由于文件的模块化分割,文件间的符号可能会相互引用。人们需要处理这些引用关系,重新计算符号的引用地址,这就是链接器的基本功能。链接器使得计算机能自动把不同的文件模块准确无误地拼接起来,使得代码的复用成为可能。

  图1-2描述的链接方式称为静态链接,但这种方式也有不足之处。静态链接器把公用库内的目标文件合并到可执行文件内部,使得可执行文件的体积变得庞大。这样做会导致可执行文件版本难以更新,也导致了多个程序加载后相同的公用库代码占用了多份内存空间。为了解决上述的问题,现代编译系统都引入了动态链接方式(见图1-3)。动态链接器不会把公用库内的目标文件合并到可执行文件内,而仅仅记录动态链接库的路径信息。它允许程序运行前才加载所需的动态链接库,如果该动态链接库已加载到内存,则不需要重复加载。另外,动态链接器也允许将动态链接库的加载延迟到程序执行库函数调用的那一刻。这样做,不仅节约了磁盘和内存空间,还方便了可执行文件版本的更新。如果应用程序模块设计合理的话,程序更新时只需要更新模块对应的动态链接库即可。当然,动态链接的方式也有缺点。运行时链接的方式会增加程序执行的时间开销。另外,动态链接库的版本错误可能会导致程序无法执行。由于静态链接和动态链接的基本原理类似,且动态链接器的实现相对复杂,因此本书编译系统所实现的链接器采用静态链接的方式。

 

               图1-2  静态链接                                   图1-3  动态链接

  汇编器和链接器的出现大大提高了编程效率,降低了编程和维护的难度。但是人们对汇编语言的能力并不满足,有人设想要是能像写数学公式那样对计算机编程就太方便了,于是就出现了如今形形色色的高级编程语言。这样就面临与当初汇编器产生时同样的问题——如何将高级语言翻译为汇编语言,这正是编译器所做的工作。编译器比汇编器复杂得多。汇编语言的语法比较单一,它与机器语言有基本的对应关系。而高级语言形式比较自由,计算机识别高级语言的含义比较困难,而且它的语句翻译为汇编语言序列时有多种选择,如何选择更好的序列作为翻译结果也是比较困难的,不过最终这些问题都得以解决。高级语言编译器的出现,实现了人们使用简洁易懂的编程语言与计算机交流的目的。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接