This article is written by Li Jianying(Light Li) in Chinese and translated into English by Robbie.

NEOVM is NEO’s VM.

It is clear that NEOVM is the virtual machine used in the Neo blockchain system.

A simple explanation of the virtual machine

Virtual machines are virtual computers, and virtual machines we usually mention has two typical types.

1.1 One is a complete simulation of a computer

For example hyper-V，VMWare

There is also an arcade machine simulator

1.2 The other type only acts as an execution environment.

For example, JVM, dotnet framework and V8\lua

For developers, the implementation environment is divided into two major categories.

1.2.1 Public execution environment

For example, java c# python

1.2.2 One is the embedded execution environment

For example, lua is a typically embedded script.

Of course, there are cases where c# and js are used as embedded scripts through mono and v8.

2 What is NeoVM

NeoVM is in the form of 1.2.2 above. It’s similar to Lua and is an embedded execution environment.

NeoVM is a virtual machine based on the Turing machine mode, which realizes logical operations by changing the state of the head on the tape.

NeoVM is a separate system that does not rely on the Neo project. NeoVM only provides pure logic computing capabilities, uses scalable interoperability, and then inserts functions that virtual machines can call.

NeoVM is designed to be closer to a machine. The code segment that is executed is a block of memory that parses the data into instructions on the fly.

3 How is NeoVM executed

To explain this, we must review the Turing machine.

Please ignore my ugly handwriting.

I assume that you understand how tape music players work. Otherwise, head and tape would become concepts that are hard to understand.

1. Write instructions on tape.

2. The head is responsible for reading the current instruction.

3. The instruction set is known. Four instructions are shown in the figure.

Nop does nothing. Push [n] pushes a number into calcstack, from which add takes two values, adds them, and puts them back in calcstack. ret ends the current execution.

4. Register space manages state. For NeoVM, registers are two Stacks: CalcStack and AltStack

There is a tape, head, instruction set, and state space. This is a Turing machine.

4 talk is cheap

Let’s take a look at the code.

Code is in samples/turing01

Less than 100 lines of code simulate the execution of the Turing machine in that ugly picture

First, get the tape with code ready.

NOP

PUSH 1

PUSH 2

ADD

RET

Then scroll the tape and let the code roll down under the head

while(!vm.stop)

{

…

}

This involves the shutdown of the Turing machine; the ret command is to inform the shutdown. Otherwise, we will continue to scroll. Of course, you can also rely on the length of the paper tape to stop. In fact, NEOVM is designed to stop automatically when the paper tape runs out. I believe that no one will suspect that the retvalue obtained by this program is 3.

Let’s analyze what happened.

This is just a simulation program. Explain one problem at a time. We use the class head to represent the tape head and the List to represent the tape.

The rolling tape is accumulated by head.pos

The state space is the stop variable and the calcstack stack

The steps to execute the instruction are written in the function StepOne

The process of StepOne is 1. Read the code on the tape head 2. Execute code 3. Roll tape head.pos++;

Executing code is operating state space

NOP doesn’t do anything, but NOP is still one of the most important instructions, so just treat him as a blank.

RET directly causes downtime, and the head does not roll anymore, the head position is also part of the state space, and the command can cause the head position to change. This is important because the essence of flow control is the head position change. All logics including if, for, and while are finally changing the head position to VM

PUSH pushes a value onto calcstack

ADD takes two values ​​from calcstack and adds them together and puts them back

If you run this program, breakpoints, StepOne step by step, observe calcstack, you will find:

1. After nop, nothing happens after

2. After push 1, calcstack is [1]

3. After push 2, calcstack is [2,1]

4. After add, calcstack is [3]

5. After ret, stop becomes true, so the loop ends.

That is how NEOVM works.

For NEOVM, .avm is the tape, the difference is that avm is byte[], not structured like the List we use here.

The purpose of this article is to explain what NEOVM is and how it works. I just used this simple procedure first for the explanation.

I will continue to explain more in the next article.

Please refer to the source code at https://github.com/lightszero/neovmbook/tree/master/samples/turing01