用于自编编程语言Polygon的虚拟机(详细指南)

212 阅读3分钟

Polygon虚拟机

Polygon虚拟机(PVM)是用于自编编程语言Polygon的虚拟机。 PVM是一个基于寄存器的虚拟机,所以这意味着它使用寄存器执行各种操作。很疯狂,我知道!这是我的个人项目之一,我计划继续开发它。

简介

PVM可以与文件一起工作,并通过它的专用REPL(读-评-打印循环)。PVM对扩展名为.plasm 的文件进行操作,其语法如下:

// examples/for_loop.plasm
load $0 1
load $1 5
load $2 16
load $3 36

gtq $0 $1
jeq $3
out $0
inc $0
jneq $2

out $0
hlt

乍一看,有许多事情正在发生。但我会在下一节中解释。 首先,Plasm编译器接受这些指令,并检查每一条指令是否有错误。 如果没有,它将这些指令转换为字节码,例如:

// This is a load instruction representation in bytecode
load $0 100
^^^^ ^^ ^^^
02   00 00 64

PVM总共可以处理23条指令(目前)。PVM仍然处于开发阶段,所以还有更多的指令会出现。让我们来看看每条指令,看看它们的参数是什么,以及它们做什么。

指令

正如我之前所说,PVM可以处理23条指令。 下面是所有可用指令的列表:

hlt load move add sub mul div jmp jmpf 
jmpb out eq neq gt lt gtq ltq jeq jneq
free alloc inc dec

PVM在寄存器的帮助下进行操作。总共有32个寄存器,可以称为$<register_number> 。寄存器的枚举从0开始,因此,例如,如果我们想访问第15个寄存器,我们将把它称为$14 。按照这个逻辑,我们最后的第32个寄存器将是$31 。现在,让我们来看看每个指令。

hlt 代表停顿:它告诉PVM停止程序的执行。

load <register> <integer_literal> 将一个指定的整数字放在指定的寄存器中。

move <from_register> <to_register> 将一个值从一个指定的寄存器移到另一个寄存器,同时将原寄存器的值设为0。

add <target> <register_1> <register_2> 将两个寄存器的值相加,并将结果放入目标寄存器。

sub <target> <register_1> <register_2> 从2个寄存器中减去数值,并将结果放在目标寄存器中。

mul <target> <register_1> <register_2> 2个寄存器的值相乘,将结果放在目标寄存器中。

div <target> <register_1> <register_2> 2个寄存器的值相除,将结果放在目标寄存器中,并将余数存储在内存中。

jmp <target> 从另一个点继续执行。

jmpf <target> 与jmp相同,但不能向后跳转。

jmpb <target> 与jmp相同,但不能进一步jmp。

out <target> 打印寄存器中的值。

eq <register_1> <register_2> 检查两个值是否相等。

neq <register_1> <register_2> 检查两个值是否相等,如果两个值不相等。

gt <register_1> <register_2> 检查value_1是否大于value_2。

lt <register_1> <register_2> 检查value_1是否小于value_2。

gtq <register_1> <register_2> 检查value_1是否大于或等于value_2。

ltq <register_1> <register_2> 检查value_1是否小于或等于value_2。

jeq <target> 检查之前的平等指令是否为真(1)并执行jmp指令。

jneq <target> 检查之前的平等指令是否为假(0),并执行一条jmp指令。

free <target> 将目标寄存器的值设为0。

alloc <register> 从堆上的寄存器中分配字节数。

inc <register> 将存储在寄存器中的值增加1。

dec <register> 将寄存器中的值减去1。

警告!

这是一个个人项目,由一个人维护。请不要在生产环境中使用这个项目,直到它达到稳定版本。