2010-01-09 126 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中的一組交互式教程,可指導您完成各種語言的解析器和解釋器的實現過程。