编译原理(1):绪论

版权声明:本文为Jurbo原创文章,转载请加上链接和作者名,标明出处。 https://blog.csdn.net/Jurbo/article/details/78009186

本文内容:介绍什么是编译程序,编译过程和编译程序的结构,解释程序和一些软件工具,程序设计语言范型。

声明:本系列文章,是根据中国大学MOOC网 哈工大的编译原理 这门课学习而成的学习笔记。后期整个视频学习结束,会结合龙书,添加自己的理解,进行强化学习。


什么是编译

计算机程序设计语言及概述

计算机程序设计语言分为三个层次,分别是机器语言,汇编语言,高级语言。

机器语言:可以被计算机直接理解的语言,由二进制数0和1构成的序列。1个操作码和两个操作数组成。

机器语言的缺点

  • 与人类表达习惯不同(我们习惯使用10进制,而机器使用二进制数或者十六进制数)
  • 难记忆(要记住操作码代表的是什么操作)
  • 难编写,难阅读
  • 易写错

汇编语言:相比于机器语言,引入了助记符。

汇编语言的缺点:

  • 依赖于特定的机器,非计算机专业人员使用受到限制
  • 编写效率比较低(一个简单的数学表达式都需要几条指令)

高级语言:类似于数学定义或自然语言的简洁形式。

高级语言的优点

  • 接近人类表达习惯
  • 不依赖于特定机器
  • 编写效率高

无论是高级语言还是汇编语言的程序,想要在机器上执行,最终都要翻译成机器语言。

汇编:将汇编语言翻译成机器语言的过程

编译:将高级语言翻译成汇编语言或机器语言的过程。即,源程序->目标程序 的过程。

这里写图片描述

编译器在语言处理系统中的位置

预处理器:将源程序转换成经过预处理的源程序。

预处理过程
- 把存储在不同文件中的源程序聚合在一起。
- 把被称为宏的缩写语句转换为原始语句

编译器:将源程序转换为汇编语言程序。

汇编器:将汇编语言程序转换成可重定位的机器代码。

可重定位的机器代码:汇编器生成的机器代码在内存中存放的起始位置不是固定的,代码中的所有地址都是相对起始位置的相对地址。

而起始位置+相对地址=绝对地址,因此我们需要加载器来修改可重定位地址。

加载器:修改可重定位地址,将修改后的指令和数据放到内存中适当的位置。

链接器:将多个可重定位的机器代码(包括库文件)连接在一起,解决外部内存地址问题。

这里写图片描述

编译过程的概述

一个编译程序的整个工作过程是划分成阶段进行的,每个阶段将源程序的一种表示形式转换成另一种表示形式,各个阶段进行的操作在逻辑上是紧密连接在一起的。

通常,将编译过程划分成词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成六个阶段。

代码优化可以分为,机器无关代码优化和机器相关代码优化。

这里写图片描述

词法分析 概述

词法分析:从左到右逐行扫描源程序的字符,识别出各个单词,确定单词的类型,将识别出的单词转换成统一的机内表示——词法单元(token)的形式。

token:<种别码,属性值>

这里写图片描述

例子

这里写图片描述

语法分析 概述

语法分析器从词法分析器输出的 token 序列中识别出各类短语,并构造语法分析树。

语法分析树描述了句子的语法结构。

这里写图片描述

语法分析所依据的是语言的语法规则,即描述程序结构的规则。通过语法分析确定整个输入串是否构成一个语法上正确的程序。

程序的结构通常是由递归规则表示的。

例如,我们可以用下面的规则来定义表达式。

  1. 任何标识符是表达式
  2. 任何常数(整常数、实常数)是表达式。
  3. 若表达式1 和 表达式2 都是表达式,那么 表达式*表达式,表达式+表达式,都是表达式。

赋值语句的定义则是:标识符=表达式 是赋值语句。

根据表达式和赋值语句的定义规则,我们可以解决例1的问题。

扩展来说,通过语法规则,我们可以进行语法分析,并画出语法分析树。

例1

这里写图片描述

例2

这里写图片描述

语义分析 概述

语义分析是审查源程序有无语义错误,为代码生成阶段收集类型信息。

  • 收集标识符的属性信息(将收集到的信息存放在符号表中)
    • 种属(kind):简单变量,复合变量(数组)、过程…..
    • 类型(type):整型、实型、字符型、布尔型、指针型…
    • 存储位置、长度。
    • 作用域
    • 参数和返回值信息:参数个数、参数类型、参数传递方式、返回值类型…..
  • 语义检查
    • 变量或过程未经声明就使用
    • 变量或过程名重复声明
    • 运算变量类型不匹配
    • 操作符与操作数之间的类型不匹配
    • 数组下标不是整数
    • 对非数组变量使用数组访问操作符
    • 对非过程名使用过程调用操作符
    • 过程调用的参数类型或数目不匹配
    • 函数返回类型有误

符号表:用于存放标识符的属性信息的数据结构。

这里写图片描述

中间代码生成 概述

在进行了上述的词法分析、语法分析、语义分析的工作之后,有的编译程序将源程序变成一种内部表示形式,这种内部表示形式叫做中间代码。

中间代码是一种结构简单、含义明确的记号,设计原则为两点:一是容易生成,二是容易将它翻译成目标代码。

常用的中间代码表示形式

  • 三地址指令:由类似于汇编语言的指令序列组成,每个指令最多有三个操作数。
  • 语法结构树/语法树

三地址指令的四元式表示,四元式的形式为:(运算符,运算对象1,运算对象2,结果)

这里写图片描述

代码优化 概述

为改进代码所进行的等价程序变化,使其运行的更快一些、占用空间更少一些,或者两者兼顾。

例如,公共子表达式的删除、强度削弱,循环优化等工作。

目标代码生成 概述

目标代码生成以源程序的中间表示形式作为输入,并把它映射到目标语言。

目标代码生成的一个重要任务是为程序中使用的变量合理分配寄存器。

编译程序的结构

上述编译过程的六个阶段的任务,可以分别由六个模块完成,它们称作词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、代码优化程序、目标代码生成程序。此外,一个完整的编译程序还必须包括“表格管理程序”和“出错管理程序”。

编译程序的结构框图

这里写图片描述

表格管理和出错处理与上述六个阶段都有联系。

编译过程中源程序的各种信息被保留在种种不同的表格里,编译各阶段的工作都涉及到构造、查找及更新有关的表格,因此需要表格管理的工作。

如果编译过程中发现源程序有错误,编译程序应报告错误的性质和错误发生的地点,并且将错误所造成的影响限制在尽可能小的范围内,使得源程序的其余功能能继续被编译下去,有些编译程序还能自动校正错误,这些工作由出错处理程序完成。

前端,后端和遍

常常把编译的过程分为前端和后端。

前端阶段的工作主要依赖于源语言而与目标机无关。通常包括,词法分析、语法分析、语义分析和中间代码生成。

后端工作指那些依赖于目标机而不依赖与源语言。包括中间代码有关的阶段,即目标代码生成,以及出错处理和符号表操作。

一个编译过程可以由一遍、两遍或多遍完成。所谓“遍”,也称作“趟”,是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。

多遍的编译程序,内存占用小,整个编译程序的逻辑结构更清晰。但遍数多,意味着增加读写中间文件的次数,编译的时间则会增加。

编译程序和解释程序的区别

解释程序:它不需要在运行前先把源程序翻译成目标代码,也可以让我们实现在某台机器上运行程序并生成结果。

解释程序接受某个语言的程序并立即运行这个源程序。它的工作模式是一个个的获取、分析并执行源程序语句,一旦第一个语句分析结束,源程序便开始运行并生成结果。它适合程序员交互方式的工作情况,即希望在获取下一个语句之前了解每个语句的执行结果,允许执行时修改程序。

编译程序和解释程序的不同工作模式,如下图所示:

这里写图片描述

习题

  1. 编译是对高级语言的翻译
  2. 把汇编语言程序翻译成机器可执行的目标程序的工作是由汇编器完成的
  3. 用高级语言编写的程序经编译后产生的程序叫目标程序
  4. 设备管理程序不是编译程序的组成部分
  5. 通常一个编译程序中,不仅包含词法分析,语法分析,语义分析,中间代码优化,目标代码生成等六个部分,还应包括表格处理和出错处理
  6. 源程序是句子的集合,树可以较好地反映句子的结构
  7. 编译程序是一种翻译程序
  8. 按逻辑上划分,编译程序第三步工作是语义分析
  9. 编译程序中语法分析器接受以单词为单位的输入
  10. 编译过程中,语法分析器的任务就是分析单词串是如何构成语句和声明的
  11. 编译原理各个阶段的工作都涉及表格管理
  12. 构造编译程序应掌握源程序、目标语言、编译方法
  13. 编译程序绝大多数时间花在表格管理
  14. 语法分析时所依据的是语法规则
  15. 将编译程序分成若干“遍”,是为了利用有限的机器内存并提高机器的执行效率。

猜你喜欢

转载自blog.csdn.net/Jurbo/article/details/78009186