大多数书籍都会有前言部分,作为一本书的铺垫或介绍。读者往往会忽略这部分文字,或者一掠而过,并不细细阅读。本书的前言虽有点啰唆,却希望读者在阅读正文之前费点工夫读一读。其原因和目的是希望读者了解本书的特点,更重要的是让读者明白本书的某种局限性和讨论的范畴。
在信息技术行业,编译器(compiler)是编程人员在工作中不可或缺的一种软件工具。这种软件工具的出现,使得编程人员能使用更适合阅读、理解的高级语言进行程序设计。它的存在,极大地提高了编程效率,降低了操作和设计的门槛,使软件维护和修改调试变得更容易。这一切,或许将成为计算机应用得到迅猛发展的原因。
也正是如此,很多人对编译器的设计感到好奇:编译器究竟是如何将编程人员编写的高级语言(源程序)“翻译”成计算机能直接运行的机器语言(目标程序)的。自然,各类计算机编程语言的制定、语法规范等细节设计都需要考虑编译器的设计因素,避免在编译过程中因为出现诸如语法的多义性而无法正确应对的情况。编译器的设计过程是复杂和艰难的。其中的困难不仅是语言的“翻译”不得“走样”(不遗失指定的操作细节,不增添额外的运算),而且要保证源程序指定的运算顺序。此外,这种“翻译”其实是将源程序中二维(甚至更多维)的数据结构、算法概念等转换成一维的二进制形式的计算机指令编码,供目标处理器直接运行。
编译器是一种基本软件工具,也是设计、制作应用软件时所使用的工具。编译器本身的设计也属于软件设计,同样需要使用编译器。本书论述的小型C语言编译器的设计过程,使用的是流行的GNU C/C++工具链(GNU C/C++tool chain)。这个设计过程就像是使用一把成品的榔头来打造一把更小巧的榔头。
编译器的设计不容易,困难之处在于涉及复杂的数据结构,以及函数之间可能存在递归和交叉递归的调用关系,从而给调试带来难度。此外,编译器设计的庞大工作量或缺乏经济效益都容易使人难以坚持。另一方面,编译器的设计或许并不如想象得那么神秘或难以企及:首先,编译器的处理对象和本身的运行都属于静态处理过程,作为处理对象的源程序不会在运行中发生变化,没有实时概念;然后,开发环境(如Windows、Linux和macOS)日臻完美,使用的工具不仅免费,而且功能完善。以作者的体会来说,编译器的设计过程既充满挑战,也富有乐趣:眼见自己亲手打造的编译器在运行后输出了盼望的结果(有时甚至优于预期),并在目标机上顺利运行,不免让人产生成就感!
本书着力叙述具体的设计、编程细节,不侧重探究编译器的设计理论。需要说明的是,作者虽然是计算机专业出身,并长期在企业从事应用软件设计工作,但是对编译器的设计却纯属业余爱好。书中论述的算法、数据结构等大都为个人闭门造车的结果,很可能与业界的主流有别。
本书以目前较为流行的加强型 PIC16Fxxxx为目标处理器(RISC 系统结构,小端式体系),论述开发、设计相应的C语言编译器工具包(如解析器、汇编器和连接器)的详细过程。由于受篇幅限制,本书未能将同样流行的STM8微处理器的设计内容包括在内,实属遗憾。
为了便于理解和叙述,本书对C语言编译器的功能进行了适度的削减和弱化,具体如下。
✧ 基本变量只限于整数类型,即char、int、short、long。
✧ 不支持struct/union结构中位域(bit-field)的定义和使用。
✧ 针对函数指针的语法识别进行某些简化。
✧ 只支持有限的预处理(语句)功能。
✧ 采用较为简单的优化算法和流程。
✧ 有限且简单的报错、警示功能。
相信读者能在理解的基础上,逐步添加功能,完善上述不足。希望本书能起到抛砖引玉的功效。
本书所设计的C语言编译器包含4个可执行文件或命令,具体如下。
✧ 预处理器(pre-processor):C语言源程序预处理操作。
✧ 编译解析器(parser):将C语言源程序转换成目标处理器的汇编语言(文件)。
✧ 汇编器(assembler):将目标处理器的汇编语言转换成可浮动目标代码(文件)。
✧ 连接器(linker):将整个目标应用程序的目标代码和编译系统库函数链接并定位,生成最终可运行的二进制代码(文件)。
此外,一个完整的编译系统还包括系统(基本)函数库和相应的头文件(header file)。所有这一切,本书均将一一阐述。
本书叙述的设计过程是在 Windows 环境下完成的,采用了 C/C++语言混合编程,力求所使用的语句简单、易懂。其中,C++语言部分仅使用了类(class)的最基本功能(函数重载),相信具备一般C语言编程基础的读者都能理解。由于所使用的C/C++工具由Linux操作系统移植而来,因此所有代码均可不进行任何修改即可在Linux环境中顺利编译、运行。至于MAX OS环境,也只需极微小的修改便可。
本书设计的编译器是以控制台命令方式运行的,与目前业界流行的图形化集成开发环境(IDE)相比显得原始、落伍。这是因为在集成化开发环境下嵌入的各类插件、工具,会使编译工具的功能、效率,以及用户体验度得到最大的改善和提升。所有这些,都期待有心者逐步实践、完善。
读者可通过扫描下方的二维码查看或下载本书中的程序源代码。读者如有批评、建议及疑问,可通过邮件与作者联系。
苏孟晋
联系方式:diycompiler@gmail.com
程序源代码