计算机要素--第七章 虚拟机I:堆栈运算

计算机系统要素,从零开始构建现代计算机(nand2tetris)
如果完成了本书所有的项目 你将会获得以下成就

  • 构建出一台计算机(在模拟器上运行)
  • 实现一门语言和相应的语言标准库
  • 实现一个简单的编译器

而且,这本书的门槛非常低,只要你能熟练运用一门编程语言即可。本课程综合了数字电路,计算机组成原理,计算机体系架构,操作系统,编译原理,数据结构等的主要内容,搭建了计算机平台的构建的框架,并未深入细节,如果需要了解细节,可由本书作为主线,逐步完善的知识体系。

QQ交流群(含资料):289682057
课程连接
项目地址Github


本章要实现的内容

  • 算术逻辑命令
  • 内存访问命令

详细内容

下面是一些主要内容

  • 编译器采用两层转换模型进行构建,首先高级语言将被翻译成中间代码,然后中间代码被转换成机器语言。这种划分方式有利于减少高级语言和机器语言之间的依赖性。
  • 将高级语言翻译成中间代码的程序可以称为编译器前端程序,而将中间代码翻译成机器语言的程序可以称为编译器后端程序。比如JAVA,JAVA的源码经翻译后形成字节码文件,字节码文件是运行在java虚拟机上的,而字节码文件经翻译后得到机器语言,机器语言运行在硬件平台上。中间代码运行在虚拟机上,机器语言运行在硬件上。
  • 在这个项目中,虚拟机语言共包含4种类型的命令:算术命令,内存访问命令,程序流程控制命令和子程序调用命令。
  • 编译器的后端程序负责的是将中间代码翻译成机器语言,所以它与硬件平台的关系性非常大,如果我们需要运行在不同的硬件平台上,那么机器语言就会发生变化,因此后算程序就需要改变,而前端程序不需要改变,因此虚拟机可以使语言很方便的进行跨平台使用。
  • 另外,很多语言的编译器能够共享VM后端程序,允许diamante共享和语言互用性。比如,某种语言善于科学计算,主要是因为它的中间代码被翻译成的机器语言在底层上是很高效的,如果我们能够把另一种语言编译到同样的VM层,那么另一种语言就能够获得这种高效的科学计算。

实现介绍

在本章中实现的命令有算术逻辑命令和内存访问命令。
算术逻辑运算主要利用堆栈来进行实现。内存访问命令,通俗来讲就是将数据从内存中拿到堆栈中和将数据从堆栈中拿到内存中。所以,这两种命令综合起来,主要实现的过程就是:将数据从内存中拿到堆栈中,然后再堆栈中进行运算,然后再将运算结果从堆栈中存到内存中。
数据结构的实现:堆栈和虚拟内存段
实际上再本章的project中,并不需要一个实际的数组或者列表来实现堆栈和内存段,但是要有逻辑上的概念。
在Hack计算机平台中,内存为32K。其中前16K作为通用RAM使用,后16K用于I/O设备的内存映像。对于前16K的通用RAM,VM将其划分为8个独立的虚拟内存段,下面是具有的划分介绍:
在这里插入图片描述
argument,local,static,this,that,temp这些段在下面由具体的介绍。这里要注意两个段,constant和pointer。constant并不需要占用RAM段,它是通过直接在高级语言中使用int变量来实现。pointer段实际上就是由RAM[3]和RAM[4]组成,下面具体介绍RAM[3],RAM[4]。
在这里插入图片描述
在这里插入图片描述
SP:初值为256,此时表示栈空
LCL:local段的基址并不是固定的,这并不是重要的,重要的是,我们只要记住local段的基址就可以了,至于基址是什么,等待程序进行分配
ARG:argument段的基址也不是固定的,我们只要记住argument段的基址就可以了
THIS:this段的基址也不是固定的,我们只要记住this段的基址就可以了
THAT:that段的基址也不是固定的,我们只要记住that段的基址就可以了
RAM[5-12]:这8个内存单元是直接保存的内容,而不是基址,它与之前几个单元的差别在于,对temp进行操作的时候要比对this,that,local和argument段进行操作的时候少基址的获取。对temp访问的时候直接在R5上加上偏移量就是本次存取的内存单元
RAM[13-15]:这3个内存单元作为通用寄存器,在本章中,主要的作用就是暂时存储从栈中弹出的数据,或者暂时存储通过基址计算出来的地址。
RAM[16-255]:这个段中的内存单元主要是分配为VM中的静态变量,即使用static标识的变量,在本章中使用顺序分配的方式来进行的,而在本课程提供的VMEmulator中使用的是基址和偏移量的方式来进行分配的,但这对于程序测试并没有影响,所以不必要担心这个地方
RAM[256-2047]:这个段是栈区,当做栈来进行使用,注意对栈进行操作的时候,要进行栈顶地址的改变
在本章中就使用了这些内存段。
综合内存映射分析堆栈运算
做好本章的项目,理解好内存映射是关键,只有理解了内存映射才能知道去哪里取数据,将数据存储到哪里。综合来看,本章的大致思路就是:从RAM[1-4]中找到基址,然后再根据偏移量计算出地址,然后去获取数据,再将数据放入堆栈中,在堆栈中完成一定操作后,再将结果从堆栈中弹出,然后放到指定的内存单元(这里实际上还需要计算基址和偏移量)。不同的是temp段,它可以直接在RAM[5]上加上偏移量得到存储单元的地址。在整个操作过程中,如果需要使用除D寄存器和A寄存器之外的寄存器暂时存储结果的时候,就会使用到RAM[13-15]的通用寄存器。

实现步骤

1、按照书中7.5所推荐的实现顺序依次实现5个vm文件的转化。
2、对于每一个文件,先在VMEmulator中运行.vm文件和xxxxVME.tst,通过观察其每一步是如何实现的,深入理解VM语言中push,pop和各个参数的实际意义。
3、自己手写相关的Hack汇编语言代码,对每个内存段,都要至少写上一个例子
4、将转换过程用高级语言实现,测试并修改,抽象出方法,实现代码复用


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章