编译原理第七章中间代码生成汇编

合集下载

编译原理-中间代码生成程序解析

编译原理-中间代码生成程序解析

实验报告课程名称编译原理实验学期至学年第学期学生所在系部年级专业班级学生姓名学号任课教师实验成绩计算机学院制开课实验室:年月日实验题目分析中间代码生成程序一、实验目的分析PL/0编译程序的总体结构、代码生成的方法和过程;具体写出一条语句的中间代码生成过程。

二、设备与环境PC兼容机、Windows操作系统、Turbo Pascal软件等。

三、实验内容1.分析PL/0程序的Block子程序,理清PL/0程序结构和语句格式。

画出Block子程序的流程图,写出至少两条PL/0程序语句的语法格式。

2.分析PL/0程序的Block子程序和Gen子程序,了解代码生成的方法和过程。

使用概要算法来描述语句的代码生成过程。

3.自己编写一个简单的PL/0程序,能够正确通过编译,得到中间代码。

列出自己编写的源程序和编译后得到的中间代码。

4.从中选择一个语句或表达式,写出代码生成的过程。

要求从自己的源程序中选择一条语句,结合这条语句写出语义分析和代码生成过程。

在描述这个过程中,要说清楚每个功能有哪个子程序的哪条语句来完成,说清楚语句和参数的含义和功能。

四、实验结果及分析(一)程序标注levmax = 3; { max depth of block nesting } { 最大允许的块嵌套层数}{ 语法分析过程block }{ 参数:lev:这一次语法分析所在的层次}{ tx:符号表指针}{ fsys:用于出错恢复的单词集合}procedure block(lev, tx: integer; fsys: symset);vardx: integer; { data allocation index } { 数据段内存分配指针,指向下一个被分配空间在数据段中的偏移位置}tx0: integer; { initial table index } { 记录本层开始时符号表位置}cx0: integer; { initial code index } { 记录本层开始时代码段分配位置}{ 登陆符号表过程enter }procedure enter(k: object1);begin { enter object into table } { 参数:k:欲登陆到符号表的符号类型}tx := tx + 1; { 符号表指针指向一个新的空位}with table[tx] do { 开始登录}beginname := id; { name是符号的名字,对于标识符,这里就是标识符的名字}kind := k; { 符号类型,可能是常量、变量或过程名}case k of { 根据不同的类型进行不同的操作}constant: { 如果是常量名}beginif num > amax then { 在常量的数值大于允许的最大值的情况下}beginerror(31); { 抛出31号错误}num := 0; { 实际登陆的数字以0代替}end;val := num { 如是合法的数值,就登陆到符号表}end;variable: { 如果是变量名}beginlevel := lev; { 记下它所属的层次号}adr := dx; { 记下它在当前层中的偏移量}dx := dx+1; { 偏移量自增一,为下一次做好准备}end;procedur: { 如果要登陆的是过程名}level := lev { 记录下这个过程所在层次}EndEndend { enter };{ 登录符号过程没有考虑到重复的定义的问题。

中间代码生成实验报告

中间代码生成实验报告

一、实验目的1. 理解编译原理中中间代码生成的基本概念和作用。

2. 掌握中间代码生成的常用算法和策略。

3. 提高对编译器构造的理解和实际操作能力。

二、实验环境1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse三、实验内容1. 中间代码生成的基本概念2. 中间代码的表示方法3. 中间代码生成算法4. 实现一个简单的中间代码生成器四、实验步骤1. 了解中间代码生成的基本概念中间代码生成是编译过程中的一个重要环节,它将源程序转换成一种中间表示形式,便于后续的优化和目标代码生成。

中间代码生成的目的是提高编译器的灵活性和可维护性。

2. 研究中间代码的表示方法中间代码通常采用三地址代码(Three-Address Code,TAC)表示。

TAC是一种低级表示,由三个操作数和一个操作符组成,例如:(t1, t2, t3) = op,其中t1、t2、t3为临时变量,op为操作符。

3. 学习中间代码生成算法中间代码生成算法主要包括以下几种:(1)栈式中间代码生成算法(2)归约栈中间代码生成算法(3)递归下降中间代码生成算法4. 实现一个简单的中间代码生成器本实验采用递归下降中间代码生成算法,以一个简单的算术表达式为例,实现中间代码生成器。

(1)定义语法规则设表达式E由以下语法规则表示:E → E + T | E - T | TT → T F | T / F | FF → (E) | i(2)设计递归下降分析器根据语法规则,设计递归下降分析器,实现以下功能:①识别表达式E②识别项T③识别因子F(3)生成中间代码在递归下降分析器中,针对不同语法规则,生成相应的中间代码。

例如:当遇到表达式E时,生成以下中间代码:(t1, t2, t3) = op1(t1, t2) // op1表示加法或减法(t4, t5, t6) = op2(t4, t5) // op2表示乘法或除法(t7, t8, t9) = op3(t7, t8) // op3表示赋值(4)测试中间代码生成器编写测试用例,验证中间代码生成器的正确性。

编写中间代码生成程序

编写中间代码生成程序

武夷学院实验报告课程名称:编译原理项目名称:编写中间代码生成程序二、实验过程记录1:(一)实验目的:在分析理解PL/0编译程序的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。

(二)实验内容:对PL/0语言作如下功能扩充:(1)扩充条件语句的功能使其为:if <条件> then <语句>[else <语句>](2)增加repeat语句,格式为:repeat <语句> {; <语句>} until <条件>(三)实验过程语句语法描述图:1注:实验过程记录要包含实验目的、实验原理、实验步骤,页码不够可自行添加。

EBNF表示:<程序>::= <分程序>.<分程序>::= [<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句> <常量说明部分>::= const<常量定义>{,<常量定义>};<常量定义>::= <标识符>=<无符号整数><无符号整数>::= <数字>{<数字>}<标识符>::= <字母>{<字母>|<数字>}<变量说明部分>::= var<标识符>{, <标识符>};<过程说明部分>::= <过程首部><分程序>{;<过程说明部分>}<过程首部>::= procedure<标识符>;<语句> ::= <赋值语句>|<条件语句>|<当循环语句>|<过程调用语句><复合语句>|<读语句>|<写语句>|<空><赋值语句>::= <标识符> := <表达式><表达式> ::= [+|-]<项>{<加法运算符><项>}<项>::= <因子>{<乘法运算符><因子>}<因子>::= <标识符>|<无符号整数>| ‘ ( ’ <表达式> ‘ ) ’<加法运算符>::= +|-<乘法运算符>::= *|/<条件>::= <表达式><关系运算符><表达式>|odd<表达式>程序描述图:三、实验结果与讨论:2实验结果:实验小结:通过在PL/0的编译程序的实验中,认识了许多关于中间代码生成的知识,掌握了中间代码中的作用所谓“中间代码”是一种结构简单、含义明确的记号系统,这种记号系统复杂性介于源程序语言和机器语言之间,容易将它翻译成目标代码,产生中间代码的过程叫中间代码生成。

第7章 语义分析与中间代码生成

第7章 语义分析与中间代码生成

(4) 无条件转移语句goto L,即下一个将被执 行的语句是标号为L的语句。 (5) 条件转移语句if x rop y goto L,其中rop为 关系运算符,如<、<=、==、!=、>、>=等。 若x和y满足关系rop就转去执行标号为L的语 句,否则继续按顺序执行本语句的下一条语 句。
(6) 过程调用语句par x和call p,n。源程序中的 过程调用语句p(x1, x2, …, xn)可用下列三地址 代码表示: par x1 par x2 par xn call p,n 其中,整数n为实参个数。 过程返回语句为return y,其中y为返回值, 可选。
{enter(, T.type, offset); offset := offset + T.width} {T.type := int; T.width := 4} {T.type := float; T.width := 8} {T.type := array(num.val, T(1).type); T.width := num.val * T(1).width} {T.type := pointer(T(1).type); T.width := 4}
2.三地址语句的种类 三地址语句非常类似于汇编代码,它可以 有符号标号和各种控制流语句。 常用的三地址语句: (1) x = y op z形式的赋值语句,其中op为二目 的算术运算符或逻辑运算符。 (2) x = op y形式的赋值语句,其中op为一目运 算符,如一目减uminus、逻辑否定not、移位 运算符以及类型转换符。 (3) x = y形式的复制语句,将y的值赋给x。
例如,赋值语句a = b * (c + d)的四元式代码: ① (+, c, d, t1) ② (*, b, t1, t2) ③ (=, t2, _, a) 约定:一元运算符一律使用arg1。此外,如果 op是一个算术或逻辑运算符,则result总是一 个新引进的临时变量,它用来存放运算结果。 结论:四元式出现的顺序与表达式计值的顺序 是一致的,四元式之间的联系是通过临时变量 实现的。四元式由于其表示更接近程序设计的 习惯而成为一种普遍采用的中间代码形式。

编译原理中间代码生成

编译原理中间代码生成

编译原理中间代码生成在编译原理中,中间代码生成是编译器的重要阶段之一、在这个阶段,编译器将源代码转换成一种中间表示形式,这种中间表示形式通常比源代码抽象得多,同时又比目标代码具体得多。

中间代码既能够方便地进行优化,又能够方便地转换成目标代码。

为什么需要中间代码呢?其一,中间代码可以方便地进行编译器优化。

编译器优化是编译器的一个核心功能,它能够对中间代码进行优化,以产生更高效的目标代码。

在中间代码生成阶段,编译器可以根据源代码特性进行一些优化,例如常量折叠、公共子表达式消除、循环不变式移动等。

其二,中间代码可以方便地进行目标代码生成。

中间代码通常比较高级,比目标代码更具有表达力。

通过中间代码,编译器可以将源代码转换成与目标机器无关的形式,然后再根据目标机器的特性进行进一步的优化和转换,最终生成目标代码。

中间代码生成的过程通常可以分为以下几步:1.词法分析和语法分析:首先需要将源代码转换成抽象语法树。

这个过程涉及到词法分析和语法分析两个步骤。

词法分析将源代码划分成一个个的词法单元,例如标识符、关键字、运算符等等。

语法分析将词法单元组成树状结构,形成抽象语法树。

2.语义分析:在语义分析阶段,编译器会对抽象语法树进行静态语义检查,以确保源代码符合语言的语义规定。

同时,还会进行类型检查和类型推导等操作。

3.中间代码生成:在中间代码生成阶段,编译器会将抽象语法树转换成一种中间表示形式,例如三地址码、四元式、特定的中间代码形式等。

这种中间表示形式通常比较高级,能够方便进行编译器的优化和转换。

4.中间代码优化:中间代码生成的结果通常不是最优的,因为生成中间代码时考虑的主要是功能的正确性,并没有考虑性能的问题。

在中间代码生成之后,编译器会对中间代码进行各种优化,以产生更高效的代码。

例如常量折叠、循环优化、死代码删除等等。

5.中间代码转换:在完成了中间代码的优化之后,编译器还可以对中间代码进行进一步的转换。

这个转换的目的是将中间代码转换成更具体、更低级的形式,例如目标机器的汇编代码。

编译原理(第2版)课后习题答案详解

编译原理(第2版)课后习题答案详解

第1 章引论第1 题解释下列术语:(1)编译程序(2)源程序(3)目标程序(4)编译程序的前端(5)后端(6)遍答案:(1)编译程序:如果源语言为高级语言,目标语言为某台计算机上的汇编语言或机器语言,则此翻译程序称为编译程序。

(2)源程序:源语言编写的程序称为源程序。

(3)目标程序:目标语言书写的程序称为目标程序。

(4)编译程序的前端:它由这样一些阶段组成:这些阶段的工作主要依赖于源语言而与目标机无关。

通常前端包括词法分析、语法分析、语义分析和中间代码生成这些阶段,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理工作和符号表管理等工作。

(5)后端:指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。

(6)遍:是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。

第2 题一个典型的编译程序通常由哪些部分组成?各部分的主要功能是什么?并画出编译程序的总体结构图。

答案:一个典型的编译程序通常包含8 个组成部分,它们是词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、中间代码优化程序、目标代码生成程序、表格管理程序和错误处理程序。

其各部分的主要功能简述如下。

词法分析程序:输人源程序,拼单词、检查单词和分析单词,输出单词的机内表达形式。

语法分析程序:检查源程序中存在的形式语法错误,输出错误处理信息。

语义分析程序:进行语义检查和分析语义信息,并把分析的结果保存到各类语义信息表中。

中间代码生成程序:按照语义规则,将语法分析程序分析出的语法单位转换成一定形式的中间语言代码,如三元式或四元式。

中间代码优化程序:为了产生高质量的目标代码,对中间代码进行等价变换处理。

目标代码生成程序:将优化后的中间代码程序转换成目标代码程序。

表格管理程序:负责建立、填写和查找等一系列表格工作。

表格的作用是记录源程序的各类信息和编译各阶段的进展情况,编译的每个阶段所需信息多数都从表格中读取,产生的中间结果都记录在相应的表格中。

编译原理中的中间代码生成

编译原理中的中间代码生成

编译原理中的中间代码生成编译原理是计算机科学的一门重要课程。

在编译器的构造过程中,中间代码生成是其核心部分之一。

它是将源代码翻译为目标代码的重要中间阶段。

中间代码生成的过程涉及到链表、树,生成三元式、四元式等多种中间形式。

本文将介绍中间代码生成的过程和其在编译中的作用。

一、中间代码的概念中间代码是指在源程序和目标程序之间所生成的一系列指令的集合。

目标代码是指机器可执行的二进制代码,而中间代码则是一种可传递、可处理和可修改的编译代码形式。

中间代码属于一种中间状态,它不是源代码也不是目标代码,但可以被转换成目标代码。

中间代码可以基于语法树、语法分析栈、语法分析表进行生成,生成的中间代码需要满足语言语法结构和语义规则。

二、中间代码生成的流程在编译过程中,中间代码生成是指将源代码转换成中间代码的过程。

它是在词法分析、语法分析和语义分析阶段之后完成的。

下面介绍一下中间代码生成的流程。

1.源代码转换为语法树编译器通过词法分析和语法分析将源代码转换成语法树。

语法树是一种树形结构,它记录了源代码中各个语句的组成情况。

2.语法树进行语义分析在语法分析之后,编译器进行语义分析,检查语法树的合法性,然后根据语言的语义规则对语法树进行标注。

标注的内容包括符号表信息、数据类型等。

3.中间代码的生成在语义分析后,编译器进入中间代码的生成阶段,生成语句的中间代码。

中间代码通常采用三元式或四元式等形式。

三元式包含操作符、操作数以及结果的地址,四元式中还包括了类型信息。

4.中间代码优化在中间代码生成的过程中,编译器会尽可能地优化中间代码。

可以对中间代码进行多种优化,如常量合并、变量替换、公共子表达式消除等。

5.中间代码转换为目标代码在中间代码生成后,编译器将中间代码转换为目标代码。

目标代码可以是汇编代码或机器代码等不同形式的二进制代码。

三、中间代码生成优化的意义编译器中间代码优化的目标是提高程序的执行效率和降低其资源消耗。

执行效率的提高可以通过以下方式实现:1.减少内存使用编译器可以通过删除冗余代码、去除死代码和不必要的变量等方式来减少中间代码的内存使用。

编译原理作业集-第七章(精选.)

编译原理作业集-第七章(精选.)

编译原理作业集-第七章(精选.)第七章语义分析和中间代码产⽣本章要点1. 中间语⾔,各种常见中间语⾔形式;2. 说明语句、赋值语句、布尔表达式、控制语句等的翻译;3. 过程调⽤的处理;4. 类型检查;本章⽬标掌握和理解中间语⾔,各种常见中间语⾔形式;各种语句到中间语⾔的翻译;以及类型检查等内容。

本章重点1.中间代码的⼏种形式,它们之间的相互转换:四元式、三元式、逆波兰表⽰;3.赋值语句、算术表达式、布尔表达式的翻译及其中间代码格式;4.各种控制流语句的翻译及其中间代码格式;5.过程调⽤的中间代码格式;6.类型检查;本章难点1. 各种语句的翻译;2. 类型系统和类型检查;作业题⼀、单项选择题:1. 布尔表达式计算时可以采⽤某种优化措施,⽐如A and B⽤if-then-else可解释为_______。

a. if A then true else B;b. if A then B else false;c. if A then false else true;d. if A then true else false;2. 为了便于优化处理,三地址代码可以表⽰成________。

a. 三元式b. 四元式c. 后缀式d. 间接三元式3. 使⽤三元式是为了________:a. 便于代码优化处理b. 避免把临时变量填⼊符号表c. 节省存储代码的空间d. 提⾼访问代码的速度4. 表达式-a+b*(-c+d)的逆波兰式是________。

a. ab+-cd+-*;b. a-b+c-d+*;c. a-b+c-d+*;d. a-bc-d+*+;5. 赋值语句x:=-(a+b)/(c-d)-(a+b*c)的逆波兰式表⽰是_______。

a. xab+cd-/-bc*a+-:=;a. xab+/cd-bc*a+--:=;a. xab+-cd-/abc*+-:=;a. xab+cd-/abc*+--:=;6. 在⼀棵语法树中结点的继承属性和综合属性之间的相互依赖关系可以由________来描述。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
assign a + a assign + * uminus c b uminus
*
b
*
b
uminus
c
a= b*-c + b*-c
c abc uminus * bc numinus *+ assign
抽象语法树
• 构造赋值语句语法树的语法制导定义: 产生式
S→id = E E→E1 + E2 E→E1 * E2 E→- E1 E→(E1)
• param x1 • param x2 • …… • param x2 • call p, n n表示实参个数。return y中y为过程返回的一个值
– 形如x = y[i]及x[i] = y的索引赋值。
– 形如x = &y, x = *y和*x = y的地址和指针赋值。象形式。 • 这些语句可以以带有操作符和操作数域的记录 来实现。四元式、三元式及间接三元式是三种 这样的表示。
x = y op z
其中,x、y和z是名字,常量或编译器生成的临时变量 op代表任何操作符(定点运算符、浮点运算符、逻辑运算 符等)
• 像x+y*z这样的表达式要翻译为:
T1 = y * z
T2 = x + T1 其中T1 ,T2为编译时产生的临时变量。
三地址语句的类型
• 三地址语句类似于汇编语言代码。语句可以有 符号标号,而且存在各种控制流语句。
– 临时变量也要填入符号表中。
三元式
• 为了避免把临时变量填入符号表,可以通过计 算临时值语句的位置来引用该临时变量。 • 这样三地址代码的记录只需要三个域op, arg1 和arg。
• 对于单目运算符op, arg1和arg2只需用其一。
四元式/三元式举例
a = b * -c + b * -c
b c 1
a= b*-c + b*-c
1 2
3
+ * id uminus id • b • c • • • * id uminus id • b • c •
*
id id uminus * + id
0
b c 5 4 3 a
2
4 5 6 7 8 9
6 7
10
11
assign

9
8
三地址代码
• 三地址代码是下列形式的语句序列
四元式
• 一个四元式是带有四个域的记录结构,这四个 域分别称为op, arg1, arg2及result。
– 域op包含一个代表运算符的内部码
– 三地址语句x=y op z通过将y放入arg1,z放入arg2 ,并且将x放入result,=为算符。
– 像x=y或x=-y这样的一元操作符语句不使用arg2 – 像param这样的运算符仅使用arg1域。 – 条件和无条件语句将目标标号存入result域。
– 形如if x relop y goto L或 if a goto L的条件跳转语句。
• 第一种形式使用关系运算符号relop(<,>等) • 第二种a为布尔变量或常量
– 用于过程调用的语句param x和call p, n,以及返回语句 return y。源程序中的过程调用p(x1,x2,…,xn):
• 其中E.code表示E的后缀式,op表示任何二元操作符 ,“||”表示后缀形式的连接
图表示法
• 图表示法主要包括DAG( Directed Acyclic Graph )与抽象语法 树 • 语法树描述了源程序的自然层次结构。DAG以更紧凑的形式 给出了相同的信息。两者不同的是:
– 在一个DAG中代表公共子表达式的结点具有多个父结点 – 在一颗抽象语法树中公共子表达式被表示为重复的子树。
• 只要知道每个算符的目数,对于后缀式,无论从那一端进行 扫描,都能对它正确的进行唯一分解
后缀式
• 表达式翻译为后缀式的语义规则描述:
产生式 E→E1 op E2 语义规则 E.code = E1.code || E2.code || op
E→(E1)
E→id
E.code = E1.code
E.code = id
语义规则
S.nptr = mknode(‘assign’, mkleaf(id, id.place), E.nptr) E.nptr = mknode(‘+’ , E1.nptr, E2.nptr) E.nptr = mknode(‘*’ , E1.nptr, E2.nptr) E.nptr = mknode(‘uminus’, E1.nptr) E.nptr = E1.nptr
第七章
本章内容
中间代码生成
–介绍几种常用的中间表示:后缀表示、图 形表示和三地址代码
–用语法制导定义和翻译方案的方法来说明 程序设计语言的结构怎样被翻译成中间形式
记号 分析 器 流
静态 检查 器
中间 代码 中间 代码 生成 代码 生成 器 器
7.1 中 间 语 言
• 抽象语法树
• 后缀式
• DAG图表示
• 本书中使用的三地址语句:
– 形如x= y op z的赋值语句,其中op为二元算术算符 或逻辑算符 – 形如x= op y的赋值语句,其中op为一元算符。 – 形如x= y的赋值语句,将y的值赋给x
– 形如goto L的无条件跳转语句,即下一条将被执行 的语句是带有标号L的三地址语句
三地址语句的类型
• 三地址代码(包括三元式、四元式、间接 三元式)
后缀式
• 后缀式表示又称逆波兰表示法。 • 这种表示法是:把运算量(操作数)写在前面,把算符写在 后面(后缀)。 • 一个表达式的后缀形式可以如下定义:
– 如果E是一个变量或常量,则E的后缀式是E自身
– 如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后 缀式为E1’E2’op。这里E1’和E2’分别是E1和E2的后缀式。 – 如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式
op (0) (1) (2) (3) (4) uminus * uminus * + arg1 c b c b T2 T3 T4 T1 arg2 result T1 T2 T3 T4 T5 (0) (1) op uminus * arg1 c b (0) (2) (3) arg2
E→id
E.nptr = mkleaf(id , id.place)
• 如果函数mknode(op, child)和mknode(op, left, right) 尽可能返回一个指向已经存在结点的指针以代替建立 新的结点,那么就会生成DAG图。
抽象语法树的表示形式
assign id • a •
0
id id uminus
相关文档
最新文档