Golang中基于堆栈的虚拟机

214 阅读2分钟

GO中基于堆栈的虚拟机

VASM--虚拟机的Assmebly语言

目前在VASM中支持的指令

(仅支持64位架构)

  • 推(PUSH
  • ADDI
  • SUBI
  • MULI
  • DIVI
  • ADDF
  • 苏菲
  • MULF
  • DIVF
  • JMP
  • 停顿
  • NOP
  • RET
  • DUP
  • 交换
  • 调用
  • 撤消
  • JMP_IF
  • 不是
  • EQI
  • 呼叫DROP

(见指令帮助)

快速启动

> go build main.go
> .\main.exe

在Powershell上交替进行(用优化方法构建)。

> .\go_build.ps1 .\main.go
> .\main.exe

使用步骤调试运行,同时编译成字节代码.vm

> .\go_build.ps1 .\main.go
> .\main.exe -input .\examples\fib.vasm -debug -compile
see generated .\examples\fib.vm 

从.vasm文件在虚拟机中执行

更多的.vasm例子请参见examples文件夹

> .\go_build.ps1 .\main.go
> .\main.exe -input .\examples\powers_of_two.vasm -limit 71
see .\main.exe -h for help on input paramenters

产生2的幂的'**vasm'**指令集:power_of_two.vasm

# Pushing initial
PUSH 0
PUSH 1
# Starting Loop
loop1:
    ADDI		# Adding Last two of the stack
    DUP 0		# Duplicating 
    DUP 1		# Duplicating 
    JMP loop1

输出

---- PROGRAM TRACE BEG ----
JMP : {int64holder:2 float64holder:5e-324 pointer:}
DUP : {int64holder:1 float64holder:0 pointer:}
DUP : {int64holder:0 float64holder:0 pointer:}
ADDI
PUSH : {int64holder:1 float64holder:5e-324 pointer:}
PUSH : {int64holder:0 float64holder:5e-324 pointer:}
---- PROGRAM TRACE END ----

---- STACK BEG ----
{1 5e-324 }
{2 5e-324 }
{4 5e-324 }
{8 5e-324 }
{16 5e-324 }
{32 5e-324 }
{64 5e-324 }
{128 5e-324 }
{256 5e-324 }
{512 5e-324 }
{1024 5e-324 }
{2048 5e-324 }
{4096 5e-324 }
{8192 5e-324 }
{16384 5e-324 }
{32768 5e-324 }
{65536 5e-324 }
{131072 5e-324 }
---- STACK END ----

e.vasm计算'e'。

> .\main.exe -input .\examples\e.vasm -limit 120

输出

---- PROGRAM TRACE BEG ----
JMP : {int64holder:3 float64holder:5e-324 pointer:}
SWAP : {int64holder:2 float64holder:0 pointer:}
SWAP : {int64holder:1 float64holder:0 pointer:}
MULF
SWAP : {int64holder:2 float64holder:0 pointer:}
DUP : {int64holder:0 float64holder:0 pointer:}
ADDF
PUSH : {int64holder:-9223372036854775808 float64holder:1 pointer:}
SWAP : {int64holder:2 float64holder:0 pointer:}
ADDF
DIVF
DUP : {int64holder:2 float64holder:0 pointer:}
PUSH : {int64holder:-9223372036854775808 float64holder:1 pointer:}
PUSH : {int64holder:-9223372036854775808 float64holder:1 pointer:}
PUSH : {int64holder:-9223372036854775808 float64holder:1 pointer:}
PUSH : {int64holder:-9223372036854775808 float64holder:1 pointer:}
---- PROGRAM TRACE END ----

---- STACK BEG ----
{-9223372036854775808 10 }
{-9223372036854775808 3.6288e+06 }
{-9223372036854775808 2.7182815255731922 }  <- Approximation of 'e' using Taylor series around 0 and value of x=1
---- STACK END ----

指令帮助

  • PUSH(Any Operand) : 将操作数推至堆栈
  • ADDI:将前两个操作数作为整数相加,并将其推回堆栈顶部。
  • SUBI:将前两个操作数作为整数减去,并将其推回堆栈顶部。
  • MULI:将前两个操作数作为整数进行乘法运算,并将其推回堆栈顶部。
  • DIVI:将前两个操作数除以整数,并将其推回到堆栈顶部。
  • ADDF:将前两个操作数作为浮点数相加,并将其推回到堆栈顶部。
  • SUBF:将前两个操作数作为浮点数减去,并将其推回到堆栈顶部。
  • MULF:将前两个操作数作为浮点数进行乘法运算,并将其推回到堆栈顶部。
  • DIVF:将前两个操作数作为浮点数进行除法,并将其推回到堆栈顶部。
  • JMP(Operand Int / Label) : 跳到标签或堆栈中的位置。
  • HALT:停止虚拟机的运行
  • NOP:在堆栈中不执行任何操作
  • RET:将指令指针指向堆栈的顶部
  • DUP(Operand Int) : 从堆栈的操作数位置复制操作数并将其推回堆栈顶部
  • SWAP(Operand Int) : 交换操作数位置和堆栈顶部的值_(可以作为一个累加器使用_
  • CALL(Operand Int / Label) : 跳到标签或堆栈内的函数调用。
  • DROP:从堆栈顶部移除数值
  • JMP_IF(Operand Int) : 如果int64不是0就跳转。
  • NOT: !0->0和0->1在堆栈的顶部
  • EQI: 对堆栈顶部的两个值进行整数等价,消耗它们,如果相等则推1,否则推0到堆栈顶部
  • EQF: 在堆栈的前两个值上执行浮点运算,消耗它们,如果相等则推1,否则推0到堆栈顶部

GitHub

github.com/mannasoumya…