编译器之编译过程

(狭义)编译大致可分为下面4个阶段。

1.语法分析

2.语义分析

3.生成中间代码

4.代码生成

 

语法分析:

对代码进行解析。将其转换为易于计算机理解的形式。这里的解析也称为语法分析。解析代码的程序模块称为解析器语法分析器

那么,什么是易于计算机理解的形式呢?那就是称为语法树的形式。

 

语义分析:

通过解析代码获得语法树后,接着就要解析语法树,除去多余的内容,添加必要的信息,生成抽象语法树(AST)这样一种数据结构。上述的处理就是语义分析

语法分析只是对代码的表象进行分析,语义分析则是对表象之外的部分进行分析。举例来说,语义分析包括以下这些处理:

  • 区分变量为局部变量还是全局变量
  • 解析变量的声明和引用
  • 变量和表达式的类型检查
  • 检查在引用变量之前是否进行了初始化
  • 检查函数是否按照定义返回了结果

    上述处理的结果都会反映到抽象语法树中。语法分析生成的语法树只是将代码的构造照搬了过来,而语义分析生成的抽象语法树还包含了语义信息。例如,在变量的引用和定义之间添加链接,适当地增加类型转换等命令,使表达式的类型一致。另外,语法树中的表达式外侧的括号、行末的分号等,在抽象语法树中都被省略了。

     

生成中间代码:

生成抽象语法树后,接着将抽象语法树转化为只在编译器内部使用的中间代码。之所以特地转化为中间代码,主要是为了支持多种编程语言或者机器语言。

例如,GCC不仅支持C语言,还可以用来编译C++和Fortran。CPU方面,不仅是Inter的CPU,还可以生成面向Alpha、SPARC、MIPS等各类CPU的机器语言。

根据编译器的不同,也存在不经过中间代码,直接从抽象语法树生成机器语言的情况。解析代码转化为中间代码为止的这部分内容,称为编译器的前端

 

代码生成:

最后把中间代码转换为汇编语言,这个阶段称为代码生成。负责代码生成的程序模块称为代码生成器

代码生成的关键在于如何来填补编程语言和汇编语言之间的差异。一般而言,比起编程语言,汇编语言在使用上面的限制要多一些。例如,C和Java可以随心所欲地定义局部变量,而汇编语言中能够分配给局部变量的寄存器只有不到30个而已。处理流程控制方面也只有和goto语句功能类似的跳转指令。在这样的限制下,还必须以不改变程序的原有语义为前提进行转换。

 

优化:

除了之间讲述的4个阶段之外,现实的编译器还包优化阶段。

现在的计算机,即便是同样的代码,根据编译器优化性能的不同,运行速度也会有数倍的差距。由于编译器要处理相当多的程序,因此在制作编译器时,最重要的一点就是尽可能地提高编译出来的程序的性能。

优化可以在编译器的各个环节进行。可以对抽象语法树进行优化,可以对中间代码的代码进行优化,也可以对转换后机器语言进行优化。进一步来说,不仅是编译器,对连接以及运行时调用的程序库的代码也都可以进行优化。

 

经过上述4个阶段,以文本形式编写的代码就被转换为了汇编语言。之后就是汇编器和连接器的工作了。

posted @ 2018-09-07 16:51  bosslv  阅读(374)  评论(0编辑  收藏  举报