上一篇《Neo 編譯器》中說明了Neo編譯器是怎麼把CIL轉成neo虛擬機的opcode,那麼vm虛擬機又是怎麼處理這些代碼的,這篇文章咱們看一下虛擬機的代碼。git
虛擬機所處的位置github
在框架圖中,咱們能夠看出Virtual Machine有如下做用框架
下面咱們先看一下虛擬機如何讀取Opcode。函數
下面展現的圖不是UML, UML太麻煩,仍是腦圖比較符合思惟邏輯的發展。區塊鏈
關鍵的幾個對象測試
執行引擎ui
執行上下文加密
每一個變量都蠻好理解的,重點是下面看看怎麼用的。lua
vm代碼執行流程spa
public void Execute() { State &= ~VMState.BREAK; while (!State.HasFlag(VMState.HALT) && !State.HasFlag(VMState.FAULT) && !State.HasFlag(VMState.BREAK)) StepInto(); }
public void StepInto() { if (InvocationStack.Count == 0) State |= VMState.HALT; if (State.HasFlag(VMState.HALT) || State.HasFlag(VMState.FAULT)) return; OpCode opcode = CurrentContext.InstructionPointer >= CurrentContext.Script.Length ? OpCode.RET : (OpCode)CurrentContext.OpReader.ReadByte(); try { ExecuteOp(opcode, CurrentContext); } catch { State |= VMState.FAULT; } }
看一下這行代碼,OpCode opcode = CurrentContext.InstructionPointer >= CurrentContext.Script.Length ? OpCode.RET : (OpCode)CurrentContext.OpReader.ReadByte();
ExecuteOp函數就是具體的執行OpCode的語義,咱們經過一個例子來講明
仍是上次的那個代碼
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; } }
測試虛擬機的代碼
using System; using System.IO; using System.Linq; using Neo; using Neo.VM; using Neo.Cryptography; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var engine = new ExecutionEngine(null, Crypto.Default); engine.LoadScript(File.ReadAllBytes(@"C:\……\Test1.avm")); using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitPush(4); // 對應形參 b sb.EmitPush(3); // 對應形參 a engine.LoadScript(sb.ToArray()); } engine.Execute(); // 開始執行 var result = engine.EvaluationStack.Peek().GetBigInteger(); // 在這裏設置返回值 Console.WriteLine($"執行結果 {result}"); Console.ReadLine(); } } }
生成的代碼太長了,須要有點耐心才能看完,若是圖片不清晰,能夠去代碼倉庫下載pdf
具體的執行過程
文章只是過了一下一個簡單的代碼,後面咱們須要研究一下系統調用和訪問外部存貯,智能合約之間互相調用的狀況。
進技術羣交流:795681763