Neo編譯器

上一篇區塊鏈研究方案
先整理一下Neo編譯器的知識吧。git

項目連接

  1. Neo自己是開源的,在github搜索就能夠拿到源碼,我爲了方便調試,把全部代碼都放在一塊兒。https://github.com/benhaben/n...
  2. Neo是C#開發的,大部分代碼能夠跨平臺,可是也有不能再mac上運行的代碼,好比改裝後的leveldb的代碼,因此最好仍是用VisualStudio在windows上調試研究較好。
  3. 本文檔主要是總結本身所研究的東西,如今不太規範,主要考慮好理解,並不完善,後面也能夠進一步規範化提交到neo項目中。

主框架

clipboard.png
框架程序員

你們能夠看到Compiler所處的位置github

Compiler做用

  1. 在Neo區塊鏈系統中,智能合約是一段代碼,能夠完成必定的邏輯,最後算出合約的結果。如今已經有不少具體的應用了,感興趣的能夠看一下基於Neo作的項目。
  2. 若是對比特幣或者智能合約不瞭解,不知道爲何須要有這些代碼,能夠看一下比特幣的白皮書。這裏簡單說一下,在比特幣系統中,當一個「人」(能夠當作一個公鑰)須要和另外一個「人」產生交易的時候,這段代碼用來檢查身份,分配比特幣。具體的瞭解能夠看一下普林斯頓的公開課
  3. 下面進入到Neo compiler的介紹了,前面所需的基礎知識本文不在關注。

Compiler的框架

下面的圖主要顯示代碼的主要流程:算法

clipboard.png
基本的流程windows

  1. Neo能夠用各類語言寫,不過如今主要是C#。
  2. Neo的編譯器主要是一個翻譯器
  3. C#代碼被C#編譯器編譯成MSIL,對MSIL的理解能夠查看Standard ECMA-335 Common Language
    Infrastructure (CLI)
  4. Neo compiler使用Mono.Cecil讀取IL
  5. Neo編譯器只關注C#中的static function,因此只是C#語言的一個超級閹割版
  6. Neo的編譯器遍歷IL,根據語義轉成Neo虛擬機的opcode
  7. 至於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的虛擬機也是堆棧虛擬機。
關於基於棧的虛擬機和基於寄存器的虛擬機能夠看一下這些文章:
棧式虛擬機和寄存器式虛擬機
另外還有一篇概念講解的很詳細的文章虛擬機隨談(一):解釋器,樹遍歷解釋器,基於棧與基於寄存器,大雜燴spa

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
PUSH1
PUSH2
ROLL
SETITEM
NOP
FROMALSTACK
DUP
TOTALSTACK
PUSH0
PICKITEM
FROMALSTACK
DUP
TOTALSTACK
PUSH1
PICKITEM
ADD
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PUSH2
ROLL
SETITEM
JMP
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PICKITEM
NOP
FROMALSTACK
DROP
ret

neo彙編的說明,能夠查看這個文檔

咱們能夠發現以下狀況:

  1. MSIL的代碼很短,Neo.VM的代碼很長,這是因爲虛擬機的指令和能力不一樣形成的。咱們只須要關注,彙編代碼處理了局部變量的存貯獲取,參數的傳遞,程序的退出,還有add指令。
  2. 彙編代碼和compiler的生成算法相關,須要咱們去同時研究neo的編譯器和虛擬機,才能明白具體的細節。
  3. 具體每一行的含義,怎麼執行的,能夠查看這個文檔
  4. 後面還會有一個講解虛擬機的文章,到那個時候在仔細說明

neo.compiler代碼閱讀指南

代碼閱讀仍是很頭痛的,因此作了兩個腦圖:

  1. compiler執行腦圖
  2. compiler對象關係

clipboard.png
對象關係

  1. ILModule是對MSIL的一個映射,包含模塊,類型,函數,字段,函數中又包含返回值,參數,函數體,能夠點開腦圖一層一層查看。
  2. Mono.Cecil是使用來讀取MSIL的,他也是對MSIL的一個映射,因爲沒有文檔,只能看代碼知道他的類結構了,這一部分在腦圖中沒有顯示,不過不要緊,compiler會把感興趣的代碼轉成ILModule
  3. ModuleConverter用來遍歷ILModule,把裏面的MSIL轉成Neo.VM的代碼,存貯在NeoModule
  4. 具體兩邊的指令如何對應,真是須要一個一個理解的,很是繁瑣,兩邊都有不少的指令。能夠看看這個代碼

總結

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

做者:沈寅
原文連接:https://www.jianshu.com/p/646...

相關文章
相關標籤/搜索