【编译原理】TINY编译器学习(一)
来源:互联网 发布:iis中将端口改为81 编辑:程序博客网 时间:2024/04/30 07:51
《编译原理及实践》中附带的TINY编译器,代码仅有几千行,
这点代码就实现了一个完整的编译器,及对应的目标代码运行程序,接下来会用一段时间研究下这个代码。
1. 源代码来源
Google “loucomp” 下载即可。
2. 源码结构
globals.h main.c
util.h util.c
scan.h scan.c
parse.h parse.c
symtab.h symtab.c
analyze.h analyze.c
code.h code.c
cgen.h cgen.c
其中scan、parse、analyze和cgen文件分别对应于代码扫描程序、分析程序、语义分析程序和代码生成器各阶段。
3. 关键函数
syntaxTree = parse( );
对应于词法分析及语法树生成。
buildSymtab(syntaxTree);
建立符号表
typeCheck(syntaxTree);
类型检测
codeGen(syntaxTree, codefile);
目标代码生成
同时工程采用了三个编译宏,可以分阶段进行控制编译器输出
NOPARSE 创建只扫描的编译器
NOANALYZE 创建只分析和扫描的编译器
NOCODE 创建执行语义分析但不生成代码的编译器
4. 使用方法
编译此工程生成tiny.exe程序,可以通过 tiny.ext sample.tny可以对源代码sample.tny进行编译,生成sample.tm可执行文件。
tm文件只有在特定的虚拟机上才能运行,对应的虚拟机是tm.exe。
编译tm.c可以生成tm.exe程序,运行tm.exe sample.tm就可以执行最终的程序。
5. 目标代码直观印象
5.1 待翻译的源代码:
a[index] = 6
5.2 普通的汇编代码:
MOV R0, index ;; value of index -> R0
MUL R0, 2 ;; double value in R0,乘以2是因为数组类型占两个字节
MOV R1, &a ;; address of a -> R1
ADD R1, R0 ;; add R0 to R1
MOV *R1, 6 ;; constant 6 -> address in R1
5.3 TINY目标代码:
LDC 1, 0 ( 0 ) ;; load 0 into reg 1
LD 0, 68 ( 1 ) ;; load val at (68+R1) into R0; 假设index 在存储器地址68中,注意这里load的是地址里的值,不是地址,注意和LDA的区别。
LDC 1, 2 ( 0 ) ;; load 2 into reg 1
MUL 0, 1, 0 ;; put R1 * R0 into R0
LDC 1, 0 ( 0 ) ;; load 0 into reg 1
LDA 1, 20 ( 1 ) ;; load 20 + R1 into R0; 假设a在存储器地址20,注意这里load的是地址,不是地址里存的值,注意和LD的区别。
ADD 0, 1, 0 ;; put R1 + R0 into R0
LDC 1, 6 ( 0 ) ;; load 6 into reg 1
ST 1, 0 ( 0 ) ;; 将R1中存的6放到最终数组的地址中。
注意:LDC是“装入常量”,LD是“由存储器装入”,而LDA是“装入地址”
6. sample.tny
{ Sample program
in TINY language -
computes factorial
}
read x; { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact { output factorial of x }
end
这段程序使用TINY语言实现了一个阶乘计算程序,其中{}用于注释,repeat-until类似于pascal语言。
7. 关于tm程序
大致浏览了下tm.c的源代码,其实现就是将TINY目标语言翻译成对应的c语言实现,相当于使用c语言实现了tm虚拟机。
这点代码就实现了一个完整的编译器,及对应的目标代码运行程序,接下来会用一段时间研究下这个代码。
1. 源代码来源
Google “loucomp” 下载即可。
2. 源码结构
globals.h main.c
util.h util.c
scan.h scan.c
parse.h parse.c
symtab.h symtab.c
analyze.h analyze.c
code.h code.c
cgen.h cgen.c
其中scan、parse、analyze和cgen文件分别对应于代码扫描程序、分析程序、语义分析程序和代码生成器各阶段。
3. 关键函数
syntaxTree = parse( );
对应于词法分析及语法树生成。
buildSymtab(syntaxTree);
建立符号表
typeCheck(syntaxTree);
类型检测
codeGen(syntaxTree, codefile);
目标代码生成
同时工程采用了三个编译宏,可以分阶段进行控制编译器输出
NOPARSE 创建只扫描的编译器
NOANALYZE 创建只分析和扫描的编译器
NOCODE 创建执行语义分析但不生成代码的编译器
4. 使用方法
编译此工程生成tiny.exe程序,可以通过 tiny.ext sample.tny可以对源代码sample.tny进行编译,生成sample.tm可执行文件。
tm文件只有在特定的虚拟机上才能运行,对应的虚拟机是tm.exe。
编译tm.c可以生成tm.exe程序,运行tm.exe sample.tm就可以执行最终的程序。
5. 目标代码直观印象
5.1 待翻译的源代码:
a[index] = 6
5.2 普通的汇编代码:
MOV R0, index ;; value of index -> R0
MUL R0, 2 ;; double value in R0,乘以2是因为数组类型占两个字节
MOV R1, &a ;; address of a -> R1
ADD R1, R0 ;; add R0 to R1
MOV *R1, 6 ;; constant 6 -> address in R1
5.3 TINY目标代码:
LDC 1, 0 ( 0 ) ;; load 0 into reg 1
LD 0, 68 ( 1 ) ;; load val at (68+R1) into R0; 假设index 在存储器地址68中,注意这里load的是地址里的值,不是地址,注意和LDA的区别。
LDC 1, 2 ( 0 ) ;; load 2 into reg 1
MUL 0, 1, 0 ;; put R1 * R0 into R0
LDC 1, 0 ( 0 ) ;; load 0 into reg 1
LDA 1, 20 ( 1 ) ;; load 20 + R1 into R0; 假设a在存储器地址20,注意这里load的是地址,不是地址里存的值,注意和LD的区别。
ADD 0, 1, 0 ;; put R1 + R0 into R0
LDC 1, 6 ( 0 ) ;; load 6 into reg 1
ST 1, 0 ( 0 ) ;; 将R1中存的6放到最终数组的地址中。
注意:LDC是“装入常量”,LD是“由存储器装入”,而LDA是“装入地址”
6. sample.tny
{ Sample program
in TINY language -
computes factorial
}
read x; { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact { output factorial of x }
end
这段程序使用TINY语言实现了一个阶乘计算程序,其中{}用于注释,repeat-until类似于pascal语言。
7. 关于tm程序
大致浏览了下tm.c的源代码,其实现就是将TINY目标语言翻译成对应的c语言实现,相当于使用c语言实现了tm虚拟机。
0 0
- 【编译原理】TINY编译器学习(一)
- TINY编译器《编译原理》
- 【编译原理】TINY编译器之词法分析(二)
- 编译原理及实践教材TINY编译器代码解析
- 编译原理及实践教材TINY编译器代码解析
- Lex/Yacc的学习——《编译原理及实践》附录B tiny编译器源码在linux下编译实现
- 编译原理课设——《TINY编译器》,用lex生成词法扫描实现编译器
- 编译原理课设——《TINY编译器》,用yacc生成语法扫描实现编译器
- 编译原理:tiny语言
- 编译器原理学习笔记 一
- 编译原理学习:TINY语言词法扫描程序实现
- 编译原理学习(一)
- 编译原理的大作业——关于TINY+的编译器
- 编译原理课设——《TINY编译器》,用lex和yacc生成词法语法分析源码,实现编译器
- tiny-spring代码学习(一)
- (编译原理)TINY扩充语言的语法分析
- 编译原理学习(一)--编译以及编译过程
- 编译原理学习笔记(一)体系结构
- 简单实用 利用反射机制写的JAVA数据库访问控制框架
- 多线程的对比与案例(计算目录下文件的大小)
- 为开发用途mac电脑瘦身
- 黑马程序员--Java面向对象——JDK 1.5新特性
- Stuts2的"struts.devMode"设置成true后,不起作用的解决办法
- 【编译原理】TINY编译器学习(一)
- 使用DBMS_STATS.restore 恢复统计信息
- ExtJS教程(1)---初窥ExtJs
- MFC的消息映射机制的理解
- android List按时间排序
- 所谓幸福,从来没有答案
- 黑马程序员--Java面向对象——反射
- 虚拟机设置中的各种网络连接方式详解
- side effect