Project 6: Assembly
简介
在本项目中我使用JAVA编程语言进行代码的编写。课程已经给我们提供了贴心的API设计,我们只需要根据API进行补充就可以了。
Assembler由以下四个类组成:
- Parser: read an instruction from the .asm file,ignore the white space and comments,interpret the type of instruction,parse it when it is a C-instruction
- Code: translate hack assembly languable into binary codes by using the code map
- SymbolTable:use a map to store all the symbols and its corresponding address
- Main: initialize a SymbolTable->create a parser->first pass->recreate a parser->second pass
这是典型的面向对象编程,不涉及算法内容,基本上就是进行简单的字符串读写,但是需要支持各个类之间较为复杂的依赖关系。用JAVA和IntelliJ IDEA进行开发是一个很不错的选择。
其实这个作业在总体统筹上的规划难度几乎是0,因为在课本里面已经给了所有的API,只需要完成每个类的API以及在Main函数中实现整个pipeline即可。所以我在这里就不放具体代码了,而是把我在完成的过程中遇到的一些问题记录一下。
一些insights
关于Java的Map
在本次作业中,为了实现一些指令到binary code的转化,我们需要使用java标准库的Map容器。
|
|
Parser的读入操作
这里还是比较复杂的,尤其是涉及一些基本的字符串处理操作。
- 使用
BufferedReader进行整行的读入。
|
|
- 关键的
advance函数实现
|
|
- 注意在一个
parser对象结束工作之后及时关闭内部的reader,读者可自行设置函数完成。
关于ROM和RAM
在完成代码的时候,我曾经出现了一个混淆,就是label和variable的存储位置。我原本意味他们是存储在一起的,所以可能出现覆盖的问题。
但是事实上,label指向的是ROM里面的指令内存,而variable指向的是RAM里面的数据内存,二者可能地址的int值是一样的,但是实际上并不是存在一块内存中的,也就不涉及互相覆盖的问题。而在硬件端运行的时候,会自动根据指令是A还是C指令访问对应的内存的。
写在最后
在这里我说几句闲话,算是表达一下自己的一些关于学习方法的思考。 在我看来,如果进行一项学习活动只追求一方面的增益,那么相应的效率就是比较低下的。而如果同时追求三方面以上的增益,那么就容易陷入多线程工作造成的注意力涣散问题中去。比方说在学习data100相关课程的时候,使用pandas库进行数据处理。在这个过程中,我获得了三个方向的收益:
- 掌握数据处理的基本流水线
- Pandas的基本语法
- 阅读官方教程和API文档的能力
而本次Project中,由于需要使用一种高级编程语言来完成一个基础的汇编器,而对我来说python编程总有一种很随意的感觉、缺少工程的味道;而C++编程则缺少合适的IDE(Visual Studio太丑了,而用CMake则需要把大量的时间放在编译和debug上面)且代码略显复杂,因此我决定使用一种我并不熟悉的(但是很简单)的编程语言——Java.
这时候我突然想起我曾经关注的一门课——MIT:Software Construction。我想,何不就这个机会,切入软件工程这个领域,进行一些中等规模编程实训,培养自己的代码习惯和编程系统思维(古法手搓代码爱好者的选择,氛围编程用户看个乐呵即可)?因此,我从这个Project中获得的增益如下:
- 汇编器的运行原理
- java编程语法
- 系统编程思维 那么,这个项目对于我来说,就是有意义的、且多方面收益的学习过程。
絮絮叨叨说了这些,其实我想表达的,是心理学家斯金纳多年前就已经说过的。 Education is what remains after one has forgotten everything he learned in school. 具体的知识是无穷无尽的。我们终其一生只能居在一隅内。唯有通过在知识中实践,掌握普适的学习方法,我们才能尽自己的努力,发挥人类在泛化能力上的优势,才能不断接近“无涯”的境界。 不多说了,准备开启Nand2Tetris的第二部分。奥利给!