Neo編譯器

買賣虛擬貨幣

上一篇
先整理一下Neo編譯器的知識吧。

專案連結

  • Neo本身是開源的,在github搜尋就可以拿到原始碼,我為了方便除錯,把所有程式碼都放在一起。https://github.com/benhaben/neo-compiler.git
  • Neo是C#開發的,大部分程式碼可以跨平臺,但是也有不能再mac上執行的程式碼,比如改裝後的leveldb的程式碼,所以最好還是用Visual Studio在windows上除錯研究較好。
  • 本文件主要是總結自己所研究的東西,現在不太規範,主要考慮好理解,並不完善,後面也可以進一步規範化提交到neo專案中。


主框架

框架

大家可以看到Compiler所處的位置

Compiler作用

  • 在Neo區塊鏈系統中,智慧合約是一段程式碼,可以完成一定的邏輯,最後算出合約的結果。現在已經有很多具體的應用了,感興趣的可以看一下基於Neo做的專案。
  • 如果對比特幣或者智慧合約不瞭解,不知道為什麼需要有這些程式碼,可以看一下比特幣的白皮書。這裡簡單說一下,在比特幣系統中,當一個“人”(可以看成一個公鑰)需要和另一個“人”產生交易的時候,這段程式碼用來檢查身份,分配比特幣。具體的瞭解可以看一下普林斯頓的公開課
  • 下面進入到Neo compiler的介紹了,前面所需的基礎知識本文不在關注。


Compiler的框架

下面的圖主要顯示程式碼的主要流程:

基本的流程

  • Neo可以用各種語言寫,不過現在主要是C#。
  • Neo的編譯器主要是一個翻譯器
  • C#程式碼被C#編譯器編譯成MSIL,對MSIL的理解可以檢視Standard ECMA-335 Common Language Infrastructure (CLI)
  • Neo compiler使用Mono.Cecil讀取IL
  • Neo編譯器只關注C#中的static function,所以只是C#語言的一個超級閹割版
  • Neo的編譯器遍歷IL,根據語義轉成Neo虛擬機器的opcode
  • 至於MSIL向neo.vm的opcode怎麼轉,需要仔細研究neo.vm的opcode的設計


Compiler工作一個具體事例

先看一段智慧合約程式碼

這段程式碼沒有什麼實際的作用,就是返回a+b,但是main可以接受引數。

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;

public class Sum : SmartContract
{
    public static int Main(int a, int b)
    {
        return a + b;
    }
}

MSIL

main function IL code

IL_0000 Nop
IL_0001 Ldarg_0
IL_0002 Ldarg_1
IL_0003 Add
IL_0004 Stloc_0
IL_0005 Br_S
IL_0007 Ldloc_0
IL_0008 Ret

這段程式碼很簡單,就是讀取引數Ldarg_0,Add,返回。可以看到CLR的虛擬機器也是堆疊虛擬機器。
關於基於棧的虛擬機器和基於暫存器的虛擬機器可以看一下這些文章:

另外還有一篇概念講解的很詳細的文章

neo.compiler

為了感性的認識neo編譯器做了什麼,我們可以看一下上面的只能合約被翻譯成了什麼

hex:53-C5-6B-6C-76-6B-00-52-7A-C4-6C-76-6B-51-52-7A-C4-61-6C-76-6B-00-C3-6C-76-6B-51-C3-93-6C-76-6B-52-52-7A-C4-62-03-00-6C-76-6B-52-C3-61-6C-75-66

實際上是一串數字了,每個數字對應一個vm的操作碼或者是數值,為了更好理解,把彙編程式碼放出來

PUSH4
PUSH3
RET
PUSH3
NEWARRAY
TOTALSTACK
FROMALSTACK
DUP
TOALTSTACK
PUSH0
PUSH2
ROLL
SETITEM
FROMALSTACK
DUP
TOTALSTACK
PUSh2
PUSH2
ROLL
SETITEM
NOP
FROMALSTACK
DUP
TOTALSTACK
PUSH0
PICKITEM
FROMALSTACK
DUP
TOTALSTACK
PUSh2
PICKITEM
ADD
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PUSH2
ROLL
SETITEM
JMP
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PICKITEM
NOP
FROMALSTACK
DROP
ret

neo彙編的說明,可以檢視這個文件

我們可以發現如下情況:

  • MSIL的程式碼很短,Neo.VM的程式碼很長,這是由於虛擬機器的指令和能力不同造成的。我們只需要關注,彙編程式碼處理了區域性變數的存貯獲取,引數的傳遞,程式的退出,還有add指令。
  • 彙編程式碼和compiler的生成演算法相關,需要我們去同時研究neo的編譯器和虛擬機器,才能明白具體的細節。
  • 具體每一行的含義,怎麼執行的,可以檢視這個文件
  • 後面還會有一個講解虛擬機器的文章,到那個時候在仔細說明


neo.compiler程式碼閱讀指南

程式碼閱讀還是很頭痛的,所以做了兩個腦圖:

  • compiler執行腦圖
  • compiler物件關係

物件關係

  • ILModule是對MSIL的一個對映,包含模組,型別,函式,欄位,函式中又包含返回值,引數,函式體,可以點開腦圖一層一層檢視。
  • Mono.Cecil是使用來讀取MSIL的,他也是對MSIL的一個對映,由於沒有文件,只能看程式碼知道他的類結構了,這一部分在腦圖中沒有顯示,不過沒關係,compiler會把感興趣的程式碼轉成ILModule
  • ModuleConverter用來遍歷ILModule,把裡面的MSIL轉成Neo.VM的程式碼,存貯在NeoModule
  • 具體兩邊的指令如何對應,真是需要一個一個理解的,非常繁瑣,兩邊都有很多的指令。可以看看這個程式碼


總結

看完這個文章,並不能瞭解到具體的細節,具體的細節已經在程式碼中,這篇文章的主要目的是提供很多資料,提供大的框架,幫助對Neo.Compiler感興趣的程式設計師加速閱讀程式碼的速度。

作者:沈寅
原文連結:https://www.jianshu.com/p/6461b4e18089

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;