Virtual Machine
之前说到可以使用Assembly language来实现程序编写,把程序通过一个Assembler就可以得到计算机可以操作的二进制文件。
但是Assembly language依旧不适于编程,但怎么将高级编程语言转变为Assembly language呢,该课程的思路是类似JAVA,先将其转换为VM language,再将VM language转化为Assembly language。
所以首先需了解VM language。其共有4种指令:

下面将分别介绍。
1)Memory segment commands
在VM里很重要的一个概念就是Stack。其实就是把寄存器当作一个stack,第0个寄存器的值RAM[0]就是栈顶的位置。比如说RAM[0]=257,就表示当前的栈顶是第257个寄存器,通过修改RAM[0]的值,就可以修改栈顶的位置。然后就可以使用push/pop了。
该课程很鸡肋的地方,就是提了个指针的概念:定义SP = RAM[0],*SP表示当前栈顶的值。要push一个值a,就令*SP = a;SP++; 要pop一个值,就令SP--;
好吧,问题来了,指针实际上既不是VM language,也不是Assembly language,只是该课程为了描述栈提出的一个概念,那具体怎么和这两者联系起来呢?举例如下,这里很容易模糊的地方是,在指针里,SP就表示栈顶地址,但在Assembly里SP表示第1个寄存器的地址!真是讨厌。
VM code:
push constant 17;
指针:
*SP = 17;SP++;
Assembly code:
@17
D = M
@SP
A = M
M = D
@SP
M = M+1
上面提到了 push constant i,对于constant,直接push就可以了,但对于别的类型数据local/static/this/that/temp/pointer,就要分类型存储了。
分类存储的思路就用到了类似汇编里段地址的概念,就是把内存分成一段段的。在数据里没有变量名的概念,但有变量名对应的地址表,这里就不考虑变量名。
在该课程中,具体设置如下:
默认SP的范围为256~2047;
对于constant类型数据,刚刚也说了,直接push到SP的范围内;
对于local类型数据,其base address存入第1个寄存器,即为RAM[1],那么local对应的stack里的第i个值的地址就是RAM[1] + i,其值就是RAM[ RAM[1]+i ]。类似于SP指向栈顶地址,定义LCL指向local类型数据的base address。类似地,ARG-RAM[2]、THIS-RAM[3]、THAT-RAM[4]。对于这些数据,其base address的具体值暂无设置规则,只要知道其值就可以了;
对于static类型数据,在Assembly中会直接将其作为一个变量,变量的申明和使用同Hack programming,其范围为16~255;
temp的范围为5~12,13~15用于general purpose registers;另外还有pointer,只能取值0/1,指向this/that,还没弄明白有啥用。
2)Arithmetic/Logical commands
假设是add,就会pop出两个数a、b,然后执行a+b,再push回去。其他类似。
3)Branching commands
goto label:无条件jump
if-goto label:先判断再jump
4)Function commands
在高级编程语言里,经常会用到各种函数。为描述其实现细节,课程里举了个很好的例子。假设有个机器人正在扫地,你突然给它下个指令让它端杯水来,机器人会怎么做?正常的流程应该是把扫地的指令记住,再执行端水,再返回继续扫地。其实和执行函数是一个道理,为了记住当前状态,就会使用到栈。
先分别解释几个commands的意思:
function foo nVars:声明函数foo,local variables数目为nVars;
call foo nArgs:请求执行函数foo,实参数目为nArgs;因此执行这一command之前,要先push nArgs个参数
return:执行call操作后,原先的nArgs个参数被清空,且栈顶为返回值
看起来很神奇,怎么利用栈来实现执行函数foo呢?更具体的说,怎么把这个VM code 转化为 Assembly code呢?可以先看下面这个例子

首先,function foo nVars这一语句会被定义为LABEL,使用goto/if-goto就可以实现函数的调用。
但怎么保存当前的状态呢?保存LCL/ARG/THIS/THAT就好了;
怎么将foo需要的参数传过去呢?重新定义ARG就好了。注意之前已经保存了ARG,所以重新定义也不要紧;
然后为local variables push nVars个0。做完这些就可以使用使用goto进入foo函数内部啦。

进入函数内部执行操作后,到了该返回值的时候了。首先可以将要返回的值赋给ARG指向的寄存器,然后程序该走向何方呢?
说明应该要记住foo被调用的地方,这样才能回去。这里就又用到了LABEL,定义一个returnAddress的LABEL,并在调用函数前就push进去。关于这里为什么要使用临时变量retAdd,课程给出的答案是,“if the function has no arguments, the next command, which is *arg = pop(), will override the return address” 不太理解...

没有去编程实现,看后面需要吧。
Virtual Machine的更多相关文章
- Azure PowerShell (6) 设置单个Virtual Machine Endpoint
<Windows Azure Platform 系列文章目录> 请注意: - Azure不支持增加Endpoint Range - 最多可以增加Endpoint数量为150 http:// ...
- Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
<Windows Azure Platform 系列文章目录> 请注意: - Azure不支持增加Endpoint Range - 最多可以增加Endpoint数量为150 http:// ...
- (学)解决VMware Taking ownership of this virtual machine failed
原文:http://blog.csdn.net/fisher_jiang/article/details/6992588背景: 一次crash可能会造成虚拟机锁死的情况发生现象:点击take owne ...
- Azure Virtual Machine 之 如何利用Management Class Libraries 创建VM
之前发的blog简单的介绍了如何使用Management Class Libraries 来控制Azure platform. 但由于官方并没有提供文档,所以我们只能够通过自己研究来摸索使用该类库的方 ...
- fail to create java virtual machine..
今天打开zend stdio 的时候 出现的错误 fail to create java virtual machine... 然后找度娘了,,都说改xxxxx, 我打开360 ,把内存清理了一遍 ...
- VMware Workstation cannot connect to the virtual machine 解决方案
今天 打开虚拟机 忽然遇到这个问题: VMware Workstation cannot connect to the virtual machine. Make sure you have righ ...
- [New Portal]Windows Azure Virtual Machine (11) 在本地使用Hyper-V制作虚拟机模板,并上传至Azure (1)
<Windows Azure Platform 系列文章目录> 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,作为自定义的虚拟机模板. 注意:因为在制作VHD的最 ...
- [New Portal]Windows Azure Virtual Machine (12) 在本地使用Hyper-V制作虚拟机模板,并上传至Azure (2)
<Windows Azure Platform 系列文章目录> 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,作为自定义的虚拟机模板. 注意:因为在制作VHD的最 ...
- [New Portal]Windows Azure Virtual Machine (13) 在本地使用Hyper-V制作虚拟机模板,并上传至Azure (3)
<Windows Azure Platform 系列文章目录> 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,作为自定义的虚拟机模板. 注意:因为在制作VHD的最 ...
- [New Portal]Windows Azure Virtual Machine (14) 在本地制作数据文件VHD并上传至Azure(1)
<Windows Azure Platform 系列文章目录> 之前的内容里,我介绍了如何将本地的Server 2012中文版 VHD上传至Windows Azure,并创建基于该Serv ...
随机推荐
- SSZipArchive的使用详解和遇到的问题
https://blog.csdn.net/zhengang007/article/details/51019479 2016年03月30日 版权声明:本文为博主原创文章,转载请注明作者和原文链接. ...
- WEB工具类
import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; ...
- gRPC 如何使用python表示多维数组
在使用gRPC作为远程调用框架时,如何使用python来表示多维数组呢?gRPC中定义proto文件时,有一个参数是repeated,用来表示重复的数据类型,使用这个参数可以表示list类型.如下,我 ...
- Mysql七种 JOIN 连接
内连接 SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.Key = B.Key 左外连接 SELECT <se ...
- Xshell报错“The remote SSH server rejected X11 forwarding request.”
Xshell报错“The remote SSH server rejected X11 forwarding request.” 2012年12月17日 ⁄ Linux⁄ 共 218字 ⁄ 字号 小 ...
- 常见的cmd命令
1.查看所有端口的使用情况:netstat -ano
- C# 中使用面向切面编程(AOP)中实践代码整洁
1. 前言 最近在看<架构整洁之道>一书,书中反复提到了面向对象编程的 SOLID 原则(在作者的前一本书<代码整洁之道>也是被大力阐释),而面向切面编程(Aop)作为面向对象 ...
- [debian]use ISO as debian apt source / 使用ISO文件作为apt源
准备文件: debian-9.8.0-amd64-DVD-1.iso debian-9.8.0-amd64-DVD-2.iso debian-9.8.0-amd64-DVD-3.iso 挂载: roo ...
- practice01
1. 组合数公式: C(n, k) =C(n-1, k) +C(n-1, k-1) 要求利用该公式写递归函数求组合数. #include <stdio.h> int C(int a,int ...
- react 16 ssr的重构踩坑
ssr 服务端不能识别前端的window.特别是首屏渲染的数据需要用到window对象(比如href += location.search); 服务端不能加载图片,css文件. require.ext ...