0%

《动手写虚拟机》准备阶段

虚拟机是什么

作为一个程序员,肯定知道Java是运行在大名鼎鼎的JVM中的。还有区块链领域的智能合约,也是运行在相应的虚拟机当中的。

这些虚拟机,其实就是模拟了真实CPU,来执行各种指令,这些指令被称为中间代码,也被称为字节码(对应真实CPU直接执行的二进制码)

这里扩展区分一下主流的三类编程语言

  1. 原生。由源代码经过编译器前端翻译成中间代码,然后又由编译器后端编译成目标机器架构的汇编语言,最后由汇编器编译成目标机器码交给真实CPU执行。比如C、C++、Golang、Rust等等
  2. 虚拟机。由源代码经过编译器前端翻译成中间代码,中间代码交给虚拟机执行。比如Java、Solidity等等
  3. 解释器。直接将源代码交给解释器,解释器边编译边执行。比如Javascript、Python等等

需要知道的编译原理知识

在写虚拟机之前需要先大致了解一个可执行文件到底是怎么来的,其中的编译原理是什么

请参考文章 《操作系统原理》编译原理

思路

因为咱们是在写虚拟机,所以我们先不管编译器前端怎么手写出来(以后有机会我们撸一个)。

我们的目标是输入一段字节码bytecodes,输出执行结果。

中间代码一般是下面的形式(这是以太坊合约中的一段字节码,我们自己的当然不是这样,是后面设计的,这里只是形如):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PUSH1 0x60
PUSH1 0x40
MSTORE
PUSH1 0x04
CALLDATASIZE
LT
PUSH2 0x0196
JUMPI
PUSH1 0x00
CALLDATALOAD
PUSH29 0x0100000000000000000000000000000000000000000000000000000000
SWAP1
DIV
PUSH4 0xffffffff

上面的字节码没有词法、没有语法、更没有语义,虚拟机完全是一行一行执行,但有跳转

虚拟机总的来讲,其实就是一个while循环,一行一行读取指令,然后翻译执行。使用栈结构模拟函数栈帧。

文件组织结构

首先我们的虚拟机应当即是一个三方包又是一个命令行工具

三方包的话就要一个包名,我们这里是github.com/pefish/go-vm,也是repo网址

命令行工具的话就需要一个bin目录(借鉴Rust),还需要一个名字,我们起名叫govm(gvm已经被用了),所以有个入口文件bin/govm/main.go

剩下的咱们边开发边整理

设计指令

下篇预告

HelloWorld




微信关注我,及时接收最新技术文章