目录
-
课程性质 属于原理性课程 课程目的 学习制作编译器和学习计算机思维
-
编译语言是一种严格意义上的翻译程序。 输入的是高级语言的源程序,输出的是面向机器的目标代码
-
源程序 预处理程序 编译器 汇编语言 汇编器 链接器 / 加载器 目标代码
-
词法分析 语法分析 中间代码 代码优化 目标代码
绪论
-
课程性质
一般原理性课程基本上就是讲实验的原理的,就行我们之前学习的计算机组成原理,操作系统原理,数据库原理一样。
原理性课程具备基础性,科学性,普遍性,针对性。一般来说比较难得学习。需要很多的基础知识串通在一起,才能够真正的学懂。
-
学习目的
-
制作编译器:
按照道理来说学习这门课程是用于做编译器的,像我们常用Java语言通用编译器等等,还有一些军用,或者企业内部使用的专用编辑器。但是能够参与制作编辑器的是非常少的,大部分同学还是做别的开发去了。所以更多还是学习其中的编程思维。 -
培养学习思维:
主要是培养计算机思维,什么是计算机思维呢?我们听过逻辑思维(主要强调的是数学能力),实证思维(主要强调的是物理实证思维)。计算思维是近几十年新出的。主要强调的是一种抽象,自然的能力。能够将抽象的东西落地。
-
编译程序
在了解什么是编译程序之前,我们先犹抱琵琶半遮面,卖个关子。来了解一些它的前世今生。
-
历史
虽然计算机的发展不过四五十年,但是 编译程序 在这个家族里面绝对是一个老者。
理论和技术在近三十年里发展得十分得迅速。但是编译程序始终是绕不过得一个门槛。虽然大部分得工作和并不需要对他进行深入。
-
应用
一般来说编译原理是用来做编译器得。但是里面得很多的思想也能够让我们所用。
例如:
有穷状态技术下的:
文本编辑技术、情报检索技术、模式识别技术代码优化技术下的
程序校验技术 、非结构化到结构化程序的转换技术
那我们的编译程序和它有什么关系呢?
-
编译程序
-
严格的来说 编译程序 是一种 严格的 翻译程序
编译程序输入的是高级语言的源程序,输出的是面向机器的代码
-
在这个过程中,还需要汇编语言和装配程序作为工具才能够输出面向机器的代码
-
图解
注意:这里需要汇编语言参与是因为,机器代码和汇编程序一样都是属于低级语言。只能在指定的机器上使用,因为不同的机器的机器指令系统不同。这是面向机器语言的通用的特点。
-
编辑器在语言处理系统中的位置
-
语言处理系统
语言程序系统的模块 (按照语言处理系统的顺序来的) 主要作用 源程序 整个程序的输入口。 由高级语言组成的源程序 预处理器 把存储在各个文件中的源程序聚合在一起。把被称作为宏的编写语言转化成为原始语言。 经过预处理的源程序 编译器 汇编语言程序 汇编器 可重定位的机器代码 可重定位的意思就是,内存中存放的起始位置的地址 L 的位置不是固定的。而后面的代码位置都是相对起始位置的代码而言的 (起始位置+相对地址=绝对地址) 链接器 / 加载器 加载器的作用: 修改可重定位地址。将修改后的指令和数据放到内存中适当的位置 目标机器代码 一般大型文件的代码都是由库文件和其他可重定位目标程序通过链接器 最后完成为目标代码
编译过程
-
大致过程
编译过程还是比较复杂的。需要经历好几个过程。这里我们用翻译一片英语文章为例。
首先是
词法分析阶段词法阶段做的主要是识别,判断是不是符合规定的 标识符、字符串、关键字等等 然后将他们分离出来 。 翻译英文就是看它们的字母是不是对的,单词是不是对的,标点符号是不是对的。 都没得问题再看它的语法是不是符合规则
然后是
语法分析阶段语法分析阶段就是看一些常见的语句是不是正确的。 如 赋值语句,for循环,if语句,go语句是不是正确的。正确再执行下一步 在英文中就是看主谓宾是不是对的,时态是不是对的等等。
再就是
中间代码阶段中间代码阶段就是进行粗略的翻译,不是特别正式的,大致的将原文的意思翻译出来就行。 对照英语中就是,在草稿纸上进行大致意思的翻译,组织一下语言。
再然后
优化代码阶段将代码进行优化,最后合成目标代码 不改变原文意思的情况下,添加一些修饰的词语。使得句子读起来更加的流畅和通顺优美。
最后
产生目标代码大结局
后面会对这些模块做进一步细致的讲解
更为详细的分类:
机器无关代码优化器是在机器代码外部进行优化机器相关代码优化器是在机器代码内进行优化。也就是说对机器代码进行优化。
-
词法分析
-
任务:
从左向右逐行进行扫描源程序的字符。识别出各个单词。确定单词的类型。将识别出的单词转换成为同一的机内表示—词法单元(token)的形式 -
词法单元的组成:
token:<种别码:属性值>
词法单元的组成由种别码和属性值组成
单词类型 种别 种别码 关键字 每个语言的关键字都是不太一样的 一词一码 标识符 变量名、数组名、记录名、过程名 多词一码 常量 整型、浮点型、字符型、布尔型等等 一型一码 运算符 算术、关系、逻辑 一词一码或一型一码 界限符 ;(){} = 、、、 一词一码 -
示例
输入: while (value!=100) {num++;} 输出: 1. while <WHILE , - > 2. ( <SLP , - > 3. value <IDN ,value> 4. != <NE , -> 5. 100 <CONET , 100> 6. ) <SPR , - > 7. { <LP , -> 8. num <IDN ,num> 9. ++ <INC , -> 10. ; <SEMI , - > 11. } <RP , - >
可以看到能够通过 种别码区分的 就不需要填写后面的属性值。
而像变量这样则需要通过后面的属性值来进行区分。
-
-
语法分析
-
用途:
词法分析器 从 语法分析器输出的token序列中,识别出各类短语,并构造语法分析树
-
示例
可以看到语法分析树是逐级逐级的开枝散叶的。标识符+ = + 表达式就会被识别为赋值语句。这是规定
然后再在下面对表达式进行扩充就行。
-
-
任务(收集信息和语义检查):
-
收集标识符的属性等信然后将其存储在字符表中进行存储。
种类 (是数组还是变量还是常量) 类型 (int ,float,double,blean) 存储位置,长度 值 作用域 参数和返回信息
字符表
识别出的结果按照上面的分类存储在字符表中。然后再平时要查的时候还是比较方便的。 -
进行语义检查
进行语义检查,检查出常见的错误
-
-
中间代码
-
任务
对语法分析识别出的各类语法范畴,分析其含义,并进行初步翻译(产生中间代码) -
转换
语法范畴转换为中间代码 -
常用的中间代码的表示形式
-
三地址码表示法:
由 类似于汇编语言的指令序列 组成,每个指令 最多由三个操作数 组成。
-
常见的三地址指令:
在上面的三地址指令中:地址可以具有如下的形式之一
- 源程序中的名字
- 常量
- 编辑器生成的临时变量
-
四元式的表示方法
四元式是三地址指令常用的表示方法
(op,x,y,z): 第一个表示操作码。后面表示操作的数值。这就是四元式的简单的格式。
-
-
中间代码生成的例子
-
代码图解
-
代码生成
j<表示判断跳转,符合条件就进行跳转。不符合条件就不进行跳转。
j 表示无条件跳转。执行这一行就会跳转到对应的行数。
+、=、就是我们理解的加和等于是一样的。
j>表示大的判断。也是符合条件就进行跳转。这就是中间代码生成的部分
-
-
-
代码优化
- 任务
代码优化主要是对中间代码进行加功,以期能够产生更为高效的代码(主要是在时间,空间上进行加工) 还有就是稳定性,可维护性上进行加工 - 转换
中间代码转换成为优化后的代码 - 依据
等价变换原则和数据流方程。
例如我们在实际变换中重点需要注意循环中那些单一不变的量。要把它们提取到循环外面,这样程序运行的速度就会快很多。
- 任务
-
目标代码
-
任务
将中间优化过的代码转换为指向机器的低级语言的代码 -
目标代码的形式
绝对指令 绝对指令是指已经放好了固定不变的指令
可重定位指令 可以重新书写的新的指令的指令
汇编指令 就是我们之前学习的汇编指令 -
转化
中间代码转换为目标代码 -
依据
硬件结构体系,指令系统
-