基于寄存器和栈式的虚拟机实现

一、总述
参考资料https://blog.csdn.net/dashuniuniu/article/details/50347149
虚拟机总共有两种,基于栈的和基于寄存器的。栈式的生成字节码会更多,但是单个指令比较简单,虚拟机更好设计。基于寄存器方式实现的虚拟机以后更好优化,执行效率会更高。

程序的机器级表示:
模拟CPU的行为其实很简单,因为再复杂的程序,本质上都是由
1.mov指令(实现LOAD,STORE)
2.算数(加减乘除等)和逻辑(布尔运算):仅有算数和逻辑操作只能顺序执行(一条指令接着一条指令)
3.控制(比较,跳转)操作:加上控制就有了条件、循环、分支语句。在CPU内存在一组单个位的条件码寄存器,每做完一个操作都会设置条件码。除此之外还有cmp指令,其实相当于减法,只是不保留结果。cmp执行后,影响条件码寄存器的值。
4.call和ret:函数调用。
5.输入输出也对应自己的指令。

所以如果自己造一个虚拟机,就是设计好自己的指令集然后实现。
在指令集的设计上,基于栈和基于寄存器其实不会有太大的区别,主要是基于栈的操作数少,但是指令条数会比较多。

基于栈的虚拟机有一个操作数栈,操作数的位置已经默认,每次操作都是默认从栈上取数据。
例子:执行a=b+c

push b
push c
add
pop a

Tiny语言自带的虚拟机是基于寄存器的。

二、简单的基于寄存器(内存)的虚拟机:
https://www.zhihu.com/question/33084689/answer/58994758
管理两段空间,分别是指令空间、数据空间(数据空间是一个数组data)。

0006 IADD 0, 1    // sum += i

指令格式是这样的(一般跟的是寄存器),0代表data[0]处的值,1代表data[1]处的值。
这个简单的虚拟机也可以利用ISTIP、ILDIP实现函数调用。
这是个最简单的基于内存的虚拟机,它不需要寄存器。

硬件层面的寄存器和内存完全是不同的概念。而软件层面的虚拟寄存器就是数据段的内存。比如基于寄存器的虚拟机都是用一个变量(内存)来模拟寄存器。

用编译器将编程语言写成的程序转换成与之等价的用指令集中的指令组成的序列表示的程序。
然后由物理机器读入这些指令序列并依次运行处理器相应的功能部件。

TM由只读指令存储区、数据区和8个通用寄存器构成。都是用非负整数地址且以0开始。
指令存储区

#define   IADDR_SIZE  1024 /* increase for large programs */
typedef struct {
      int iop  ;
      int iarg1  ;
      int iarg2  ;
      int iarg3  ;
   } INSTRUCTION;
INSTRUCTION iMem [IADDR_SIZE];

数据存储区(内存)

#define   DADDR_SIZE  1024 /* increase for large programs */
int dMem [DADDR_SIZE];

在Tiny的目标代码中,大量出现了reg5、6、7,其中5是memory pointer,6是全局指针global pointer,7是PC
A memory pointer (or just pointer) is a primitive, the value of which is intended to be used as a memory address; it is said that a pointer points to a memory address. It is also said that a pointer points to a datum [in memory] when the pointer’s value is the datum’s memory address.

mp和gp一个是栈顶一个是栈底

/* mp = "memory pointer" points
 * to top of memory (for temp storage)
 */
#define  mp 6

/* gp = "global pointer" points
 * to bottom of memory for (global)
 * variable storage
 */
#define gp 5

从中间代码到目标代码:
如果不做任何优化,直接翻译出来的汇编代码应该是类似这样的东西:
int z = 0
mov 0 -> R1 (R1寄存器的值赋0)
store R1 -> z (把R1寄存器的值写到z变量所在的内存位置)

z = z+2
load z -> R1 (从内存将z载入R1寄存器)
add R1, 2 -> R1 (R1寄存器加2)
store R1 -> z (把加完2的值写回内存变量z)

对每一个形如x=y+z的三地址语句,都可以翻译成如下的代码序列(简单的宏拓展)

LD  R0,y
ADD R0,R0,z
ST  x,R0

可以只使用一个寄存器R0就实现翻译

参考书籍:game scripting mastery 游戏脚本高级编程
https://www.zhihu.com/question/33084689/answer/58994758
https://www.zhihu.com/question/20897500/answer/16536470

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值