本文内容:介绍什么是编译程序,编译过程和编译程序的结构,解释程序和一些软件工具,程序设计语言范型。
声明:本系列文章,是根据中国大学MOOC网 哈工大的编译原理 这门课学习而成的学习笔记。后期整个视频学习结束,会结合龙书,添加自己的理解,进行强化学习。
计算机程序设计语言分为三个层次,分别是机器语言,汇编语言,高级语言。
机器语言:可以被计算机直接理解的语言,由二进制数0和1构成的序列。1个操作码和两个操作数组成。
机器语言的缺点:
汇编语言:相比于机器语言,引入了助记符。
汇编语言的缺点:
高级语言:类似于数学定义或自然语言的简洁形式。
高级语言的优点:
无论是高级语言还是汇编语言的程序,想要在机器上执行,最终都要翻译成机器语言。
汇编:将汇编语言翻译成机器语言的过程
编译:将高级语言翻译成汇编语言或机器语言的过程。即,源程序->目标程序 的过程。
预处理器:将源程序转换成经过预处理的源程序。
预处理过程:
- 把存储在不同文件中的源程序聚合在一起。
- 把被称为宏的缩写语句转换为原始语句
编译器:将源程序转换为汇编语言程序。
汇编器:将汇编语言程序转换成可重定位的机器代码。
可重定位的机器代码:汇编器生成的机器代码在内存中存放的起始位置不是固定的,代码中的所有地址都是相对起始位置的相对地址。
而起始位置+相对地址=绝对地址,因此我们需要加载器来修改可重定位地址。
加载器:修改可重定位地址,将修改后的指令和数据放到内存中适当的位置。
链接器:将多个可重定位的机器代码(包括库文件)连接在一起,解决外部内存地址问题。
一个编译程序的整个工作过程是划分成阶段进行的,每个阶段将源程序的一种表示形式转换成另一种表示形式,各个阶段进行的操作在逻辑上是紧密连接在一起的。
通常,将编译过程划分成词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成六个阶段。
代码优化可以分为,机器无关代码优化和机器相关代码优化。
词法分析:从左到右逐行扫描源程序的字符,识别出各个单词,确定单词的类型,将识别出的单词转换成统一的机内表示——词法单元(token)的形式。
token:<种别码,属性值>
语法分析器从词法分析器输出的 token 序列中识别出各类短语,并构造语法分析树。
语法分析树描述了句子的语法结构。
语法分析所依据的是语言的语法规则,即描述程序结构的规则。通过语法分析确定整个输入串是否构成一个语法上正确的程序。
程序的结构通常是由递归规则表示的。
例如,我们可以用下面的规则来定义表达式。
赋值语句的定义则是:标识符=表达式 是赋值语句。
根据表达式和赋值语句的定义规则,我们可以解决例1的问题。
扩展来说,通过语法规则,我们可以进行语法分析,并画出语法分析树。
语义分析是审查源程序有无语义错误,为代码生成阶段收集类型信息。
符号表:用于存放标识符的属性信息的数据结构。
在进行了上述的词法分析、语法分析、语义分析的工作之后,有的编译程序将源程序变成一种内部表示形式,这种内部表示形式叫做中间代码。
中间代码是一种结构简单、含义明确的记号,设计原则为两点:一是容易生成,二是容易将它翻译成目标代码。
常用的中间代码表示形式:
三地址指令的四元式表示,四元式的形式为:(运算符,运算对象1,运算对象2,结果)
为改进代码所进行的等价程序变化,使其运行的更快一些、占用空间更少一些,或者两者兼顾。
例如,公共子表达式的删除、强度削弱,循环优化等工作。
目标代码生成以源程序的中间表示形式作为输入,并把它映射到目标语言。
目标代码生成的一个重要任务是为程序中使用的变量合理分配寄存器。
上述编译过程的六个阶段的任务,可以分别由六个模块完成,它们称作词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、代码优化程序、目标代码生成程序。此外,一个完整的编译程序还必须包括“表格管理程序”和“出错管理程序”。
编译程序的结构框图:
表格管理和出错处理与上述六个阶段都有联系。
编译过程中源程序的各种信息被保留在种种不同的表格里,编译各阶段的工作都涉及到构造、查找及更新有关的表格,因此需要表格管理的工作。
如果编译过程中发现源程序有错误,编译程序应报告错误的性质和错误发生的地点,并且将错误所造成的影响限制在尽可能小的范围内,使得源程序的其余功能能继续被编译下去,有些编译程序还能自动校正错误,这些工作由出错处理程序完成。
常常把编译的过程分为前端和后端。
前端阶段的工作主要依赖于源语言而与目标机无关。通常包括,词法分析、语法分析、语义分析和中间代码生成。
后端工作指那些依赖于目标机而不依赖与源语言。包括中间代码有关的阶段,即目标代码生成,以及出错处理和符号表操作。
一个编译过程可以由一遍、两遍或多遍完成。所谓“遍”,也称作“趟”,是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。
多遍的编译程序,内存占用小,整个编译程序的逻辑结构更清晰。但遍数多,意味着增加读写中间文件的次数,编译的时间则会增加。
解释程序:它不需要在运行前先把源程序翻译成目标代码,也可以让我们实现在某台机器上运行程序并生成结果。
解释程序接受某个语言的程序并立即运行这个源程序。它的工作模式是一个个的获取、分析并执行源程序语句,一旦第一个语句分析结束,源程序便开始运行并生成结果。它适合程序员交互方式的工作情况,即希望在获取下一个语句之前了解每个语句的执行结果,允许执行时修改程序。
编译程序和解释程序的不同工作模式,如下图所示: