上一篇《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