2010-01-09 69 views
41

我想要自我教育的目的是为动态语言实现一个简单的虚拟机,比较喜欢C.像Lua VM,Parrot或Python VM,但更简单。除了查看现有虚拟机的代码和设计文档外,是否还有任何关于实现此目的的好资源/教程?实现虚拟机的教程/资源

编辑:为什么近距离投票?我不明白 - 这不是编程。如果我的问题存在特定问题,请发表评论。

+2

如果你还有兴趣,我写了一个非常简单的虚拟机C.看看:http://github.com/tekknolagi/carp – tekknolagi 2014-08-22 16:47:20

回答

29

我假设你想要一个虚拟机而不是单纯的解释器。我认为他们是连续统一体的两点。口译员在接近程序原始表达的情况下工作。虚拟机工作在更原始的(和独立的)指令上。这意味着您需要编译阶段才能将其转换为另一个阶段。我不知道你是否想首先处理这个问题,或者如果你还记得输入语法。

对于动态语言,您需要某处存储数据(作为键/值对)以及对其执行操作的某些操作。 VM维护商店。运行的程序是一系列指令(包括控制流程)。您需要定义一组说明。我建议一组简单的有开始,如:

  • 基本的算术运算,包括算术比较,访问商店
  • 基本控制流程
  • 内置的打印

你可能希望使用基于堆栈的计算方法进行算术运算,正如许多VM所做的那样。在上面还没有太多动态。为了达到这个目的,我们需要两件事:在运行时计算变量名称的能力(这只是表示字符串操作),以及将代码作为数据处理。这可能与允许函数引用一样简单。

对VM的输入最好是字节码。如果你还没有编译器,那么可以从一个基本的汇编器(它可能是VM的一部分)中生成。

虚拟机本身由循环:

1. Look at the bytecode instruction pointed to by the instruction pointer. 
2. Execute the instruction: 
    * If it's an arithmetic instruction, update the store accordingly. 
    * If it's control flow, perform the test (if there is one) and set the instruction pointer. 
    * If it's print, print a value from the store. 
3. Advance the instruction pointer to the next instruction. 
4. Repeat from 1. 

与计算的变量名交易可能会非常棘手:一个指令需要指定哪些变量计算的名称是可以这样做,允许指令参考。到输入中提供的字符串常量池。

一个例子程序(在装配和字节码):

offset bytecode (hex) source 
0  01 05 0E   //  LOAD 5, .x 
3  01 03 10   // .l1: LOAD 3, .y 
6  02 0E 10 0E  //  ADD .x, .y, .x 
10  03 0E   //  PRINT .x 
12  04 03   //  GOTO .l1 
14  78 00   //  .x: "x" 
16  79 00   //  .y: "y" 

隐含的指令代码为:

"LOAD x, k" (01 x k) Load single byte x as an integer into variable named by string constant at offset k. 
"ADD k1, k2, k3" (02 v1 v2 v3) Add two variables named by string constants k1 and k2 and put the sum in variable named by string constant k3. 
"PRINT k" (03 k) Print variable named by string constant k. 
"GOTO a" (04 a) Go to offset given by byte a. 

需要当变量被其它变量等命名为变体(和间接的级别变得难以理解)。汇编程序查看像“ADD .x,.y,.x”这样的参数,并生成正确的字节码以从字符串常量(而不是计算变量)中进行添加。

+0

不错。任何想法资源从这里去? – zaharpopov 2010-01-13 03:41:03

+1

@zaharpopv:我不太确定如何实现你的语言的动态功能,但是像上面这样简单的虚拟机设计很容易,一旦你完成了它,你将会学习到它是多么合适,并且可以改变它以支持更有趣的功能。另外,查看Python解释器的一组指令可能会给你一些关于如何支持动态的想法。 – Edmund 2010-01-13 09:16:11

9

嗯,这不是关于在C中实现VM,而是因为它是我在看到这个问题之前打开的最后一个标签,所以我觉得我需要在JavaScript中使用<canvas>标记指出article about implementing a QBASIC bytecode compiler and virtual machine。它包含所有的源代码,以获得足够的QBASIC来运行“半字节”游戏,并且是编译器和字节码解释器系列文章中的第一篇。这篇文章描述了虚拟机,他也承诺将来的文章也会描述编译器。

顺便说一句,我没有投票结束您的问题,但您得到的近距离投票是关于如何了解实施虚拟机的question from last year的副本。我认为这个问题(关于教程或相对简单的东西)与那个应该保持开放的问题是不相同的,但是您可能想要参考这个问题寻求更多的建议。

4

另一个需要关注的资源是Lua language的实现。它是一个基于注册的虚拟机,在性能方面享有良好声誉。 source code在ANSI C89中,通常非常易读。与大多数高性能脚本语言一样,最终用户可以看到可读的高级动态语言(具有闭包,尾调用,不可变字符串,数字和散列表等作为主要数据类型的功能,作为第一类值, 和更多)。源文本被编译为虚拟机的字节码,供虚拟机实现执行,虚拟机的实现大致如Edmund's answer所述。

为了保持虚拟机本身的可移植性和高效性,我们付出了巨大的努力。如果需要更高的性能,则对于32位x86存在从VM字节代码到本机指令的just in time compiler,并且在64位版本的beta版本中。

2

为了启动(即使不Ç,但C++),你可以给看看到muParser

这是一个数学表达式解析器,它使用简单的虚拟机来执行操作。我认为即使你需要时间来理解一切,无论如何,这个代码比完整的虚拟机能够运行一个完整的程序更简单。 (顺便说一下,我在C#中设计了一个similar lib--这是它的早期阶段,但是下一个版本将允许编译到.NET/VM IL 或者可能是一个像muParser这样的新的简单VM。

另一个有趣的事情是NekoVM(它执行.n字节码文件)。这是一个开源项目written in C,它的主要语言(.neko)被认为是由source-to-source compiler技术生成的。本着最后一个主题,请参阅同一作者的Haxe(开源)。

1

像你我一直在研究虚拟机和编译器,我可以推荐的一本好书是Compiler Design: Virtual Machines。它通过为每个虚拟机提供指令集以及如何将更高级别的语言编译到该虚拟机的教程来描述用于命令式,功能性,逻辑和面向对象语言的虚拟机。我只为命令式语言实现了虚拟机,并且它已经是一个非常有用的练习。

如果你刚刚开始,那么我可以推荐的另一个资源是PL101。它是JavaScript中的一组交互式教程,可指导您完成各种语言的解析器和解释器的实现过程。