计算机基础系列 —— 虚拟机代码翻译器(1)

“Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.” ―Linus Torvalds

文中提到的所有实现都可以参考:nand2tetris_sol,但是最好还是自己学习课程实现一遍,理解更深刻。

课程的 Part I:

被抽象成一块 Hack 器件,Part II 的重点在软件部分,包括高级语言(Jack)、操作系统、编译器(Jack Compiler)和 虚拟机翻译器(VM translator)。

One tier VS Two tier

我们这篇文章来看 VM Code 和 VM Translator 的实现,后面的文章会看 Two tier 的高级语言 Jack 和 Jack 编译器。

VM Code

编译器把高级语言编译成 vmcode,而 vmcode 被设计成在堆栈结构机器(abstract stack machine)运行。

对于上面的数学计算,Stack 都可以通过 pop x y 然后 command x y (实现上不同的 command 用不同汇编语言实现,然后硬编码在 VM translator 里) 最后 push x y 的计算结果回到 stack,如下图:

Segments

我们现在知道了 vmcode 是如何计算的,但是高级语言里的计算结果是存储在不同的变量里的,所以我们还需要让 vmcode 也知道这些变量的种类。

所以 vmcode 有了 segment 的概念,不同的变量放在不同的 segment 里面,比如函数的参数放在 argument 段里,static 变量放在 static 段里,所以汇编器里的一些与定义符号其实对应的就是 vmcode 里不同的段,这些段都是虚拟的,实际上都在一块 RAM 里。

constant

比如程序里有一段 const int x = 17 17 就放在 constant segment 里,我们来看看 vmcode 如何把 17 放进 constant segment 里,以及对应的汇编代码,因为我们这节课实现的是 VM translator,生成 VM code 是后面我们要实现的 compiler 要做的事情。

上面的图展示了,push constant 17 (把 17 放到 stack machine 的 constant segment 里)的过程。但是注意,这里实际上没有一个 constant segment,因为 constant 的语义就是把一个常数放进 stack 里。

local | argument | this | that

这几个段虽然功能不同,但都可以用同样的方式操作,只是段的位置不一样,所以语义不同,但都可以用相同的伪代码表示(下面是 local 的图,其他不同之处把 LCL 替换成 ARG THIS THAT 即可,这些预定义符号代表段在 RAM 里的开始地址),pop segment i 的语义是:把最新 push 到 stack 里的值 pop 到对应 segment 里的 segment start address + i 位置供程序使用。push segment i 的语义是:把 segment 里的 segment start address + i 位置的值 push 到 stack 的 SP 位置供程序使用。

static

RAM[16] - RAM[255] 用来存放 static 变量

每个 filename.vm 文件的静态变量,存放在 RAM 里,相当于每个 vm 文件有一个虚拟的 segment,每个 segment 的名字是汇编语言里的标签 filename.i。

temp

temp 变量放在 RAM[5] - RAM[12],这里编译器生成 VM code 会用来存一些临时信息,后面的文章会介绍。

pointer

push/pop pointer 0 等于 push/pop THIS

push/pop pointer 1 等于 push/pop THAT

有了上面的这些信息,我们就可以编写代码,把这些 VM Code 翻译成汇编语言。

VM code 里还有分支和函数调用的概念,下篇文章,我们看如何把这些概念翻译成汇编语言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/578108.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud GateWay——网关的基本使用

1. 为什么所有的请求先到网关呢? 有了网关就可以对请求进行路由,路由到具体的微服务,减少外界对接微服务的成本,比如:400电话,路由的试可以根据请求路径进行路由、根据host地址进行路由等, 当微…

ios应用内支付

用uniapp开发iOS应用内支付 准备前端代码服务器端处理如果iOS支付遇到问题实在解决不了,可以联系我帮忙解决,前端后端都可以解决(添加的时候一定要备注咨询iOS支付问题) 准备前端代码 获取支付通道 (uni.getProvider) uni.getPr…

上岸美团了!

Hello,大家好,最近春招正在如火如荼,给大家分享一份美团的面经,作者是一份某双非的硕(只如初见668),刚刚通过了美团的3轮面试,已经拿到offer,以下是他的一些分享。 一面&…

module ‘numpy‘ has no attribute ‘int‘

在 NumPy 中,如果遇到了错误提示 "module numpy has no attribute int",这通常意味着正在尝试以错误的方式使用 NumPy 的整数类型。从 NumPy 1.20 版本开始,numpy.int 已经不再是一个有效的属性,因为 NumPy 不再推荐使用…

mongodb sharding分片模式的集群数据库,日志治理缺失导致写入数据库报错MongoWriteConcernException的问题总结(上)

一、背景 常见的mongodb集群模式有以下三种: 主从复制(Master-Slave)模式副本集(Replica Set)模式分片(Sharding)模式 公司测试环境搭建的集群采用分片模式,有同事反馈说&#xf…

数据结构——链表(双向链表)

大家好,我是小峰,今天给大家讲解的是双向链表,我们先来看看链表的结构。 链表分类 这里带头是哨兵位的头节点 3. 循环与非循环 我们排列一些就可以看出链表的结构种类 这些链表的操作大都差不多 我们今天讲解的是双向带头循环链表 带头双向…

BGP实训

BGP基础配置实训 实验拓扑 注:如无特别说明,描述中的 R1 或 SW1 对应拓扑中设备名称末尾数字为 1 的设备,R2 或 SW2 对应拓扑中设备名称末尾数字为2的设备,以此类推;另外,同一网段中,IP 地址的主…

【数据挖掘】实验5:数据预处理(2)

验5:数据预处理(2) 一:实验目的与要求 1:熟悉和掌握数据预处理,学习数据清洗、数据集成、数据变换、数据规约、R语言中主要数据预处理函数。 二:实验知识点总结 1:数据集成是将多个…

boost::asio::ip::tcp/udp::socket::release 函数为什么限制 Windows 8.1 才可以调用?

如本文题目所示,这是因为只有在 Windows 8.1(Windows Server 2012 RC)及以上 Windows 操作版本才提供了运行时,修改/删除完成端口关联的ABI接口。 boost::asio 在 release 函数底层实现之中是调用了 FileReplaceCompletionInform…

git仓库太大只下载单个文件或文件夹

有没有这样的苦恼:仓库太大,只想下载其中某些文件(夹)? 一招解决:bash down_folder_from_git.sh 运行前,先修改开头三个变量 原理: 稀疏检出 让工作树仅包含自定义的文件 #!/usr/bin/bash addrhttps://github.com/fac…

【edge浏览器无法登录某些网站,以及迅雷插件无法生效的解决办法】

edge浏览器无法登录某些网站,以及迅雷插件无法生效的解决办法 edge浏览器无法登录某些网站,但chrome浏览器可以登录浏览器插件无法使用,比如迅雷如果重装插件重装浏览器重装迅雷后仍然出现问题 edge浏览器无法登录某些网站,但chro…

niushop单商户V5多店版源码分享三端uniapp打包方法包括PC端_小程序或h5端打包_收银端打包_APP端打包_商户端

目前多店版有四端uniapp,包括PC端uniapp,商家端uniapp,收银端uniapp,门店手机端uniapp,下面我总结下这些端的打包流程希望能帮助到大家,需要交流的可以看我昵称或者点我头像关注我分享代码和教程 一.niush…