Show / Hide Table of Contents

NeoVM指令集

内置数据类型

NeoVM内置的数据类型一共有7种:

类型描述
Boolean布尔类型,实现为一个bool值和两个字节数组 TRUEFALSE
Integer整型,实现为一个 BigInteger 值。
ByteArray字节数组,实现为一个 byte[]
Array数组,实现为一个 List<StackItem>StackItem 是一个抽象类,NeoVM内置的数据类型均继承自 StackItem
Struct结构体,继承自 Array 。结构与 Array 相同,只是添加了 Clone 方法和重写了 Equals 方法。
Map实现为一个键值对为 StackItem 的字典类型 Dictionary<StackItem, StackItem>
InteropInterface互操作接口
// boolean 类型
private static readonly byte[] TRUE = { 1 };
private static readonly byte[] FALSE = { 0 };

private bool value;

指令集

Neo.VM虚拟机一共实现了113个指令(另外有4个被注释未实现指令),类别如下:

常数流程控制栈操作字符串操作逻辑运算算术运算密码学高级数据结构栈隔离异常处理
25916552571452

下面将分别介绍各个指令的详细内容。

常数

常数部分指令主要完成向计算栈中压入常数或者数组的功能。

PUSH0

指令PUSH0
字节码0x00
别名: PUSHF
功能:向计算栈中压入一个长度为0的字节数组。

PUSHBYTES

指令:PUSHBYTES1~PUSHBYTES75
字节码:0x01~0x4B
功能:向计算栈中压入一个字节数组,其长度等于本指令字节码的数值。

PUSHDATA

指令:PUSHDATA1, PUSHDATA2, PUSHDATA4
字节码:0x4C, 0x4D, 0x4E
功能:向计算栈中压入一个字节数组,其长度由本指令后的 1|2|4 字节指定。

PUSHM1

指令:PUSHM1
字节码:0x4F
功能:向计算栈中压入一个大整数,其数值等于-1。

PUSHN

指令:PUSH1~PUSH16
字节码:0x51~0x60
别名: PUSHT
功能:向计算栈中压入一个大整数,其数值等于1~16。

流程控制

用于控制的虚拟机运行流程,包括跳转、调用等指令。

NOP

指令:NOP
字节码:0x61
功能:空操作,但是会使指令计步器加1。

JMP

指令:JMP
字节码:0x62
功能:无条件跳转到指定偏移位置,偏移量由本指令后的2字节指定。

JMPIF

指令:JMPIF
字节码:0x63
功能:当计算栈栈顶元素不等于0时,跳转到指定偏移位置,
偏移量由本指令后的2字节指定。不论条件判断成功与否,栈顶元素将被移除。

JMPIFNOT

指令:JMPIFNOT
字节码:0x64
功能:当计算栈栈顶元素等于0时,跳转到指定偏移位置,偏移量由本指令后的2字节指定

CALL

指令:CALL
字节码:0x65
功能:调用指定偏移位置的函数,偏移量由本指令后的2字节指定。

RET

指令:RET
字节码:0x66
功能:移除调用栈的顶部元素,并使程序在调用栈的下一帧中继续执行。
如果调用栈为空,则虚拟机进入停机状态。

APPCALL

指令:APPCALL
字节码:0x67
功能:调用指定地址的函数,函数地址由本指令后的20字节指定。

SYSCALL

指令:SYSCALL
字节码:0x68
功能:调用指定的互操作函数,函数名称由本指令后的字符串指定。

TAILCALL

指令:TAILCALL
字节码:0x69
功能:以尾调用的方式(调用完后不再返回当前执行环境),
调用指定的互操作函数,函数名称由本指令后的字符串指定。

栈操作

实现对栈的元素做复制、移除、交换等功能。

DUPFROMALTSTACK

指令DUPFROMALTSTACK
字节码0x6A
功能复制备用栈栈顶的元素,并将其压入计算栈。

TOALTSTACK

指令:TOALTSTACK
字节码:0x6B
功能:移除计算栈栈顶的元素,并将其压入备用栈。

FROMALTSTACK

指令:FROMALTSTACK
字节码:0x6C
功能:移除备用栈栈顶的元素,并将其压入计算栈。

XDROP

指令:XDROP
字节码:0x6D
功能:移除计算栈栈顶的元素n,并移除剩余的索引为n的元素。
输入:Xn Xn-1 ... X2 X1 X0 n
输出:Xn-1 ... X2 X1 X0

XSWAP

指令:XSWAP
字节码:0x72
功能:移除计算栈栈顶的元素n,并将剩余的索引为0的元素和索引为n的元素交换位置。
输入:Xn Xn-1 ... X2 X1 X0 n
输出:X0 Xn-1 ... X2 X1 Xn

XTUCK

指令:XTUCK
字节码:0x73
功能:移除计算栈栈顶的元素n,并将剩余的索引为0的元素复制并插入到索引为n的位置。
输入:Xn Xn-1 ... X2 X1 X0 n
输出:Xn X0 Xn-1 ... X2 X1 X0

DEPTH

指令:DEPTH
字节码:0x74
功能:将当前计算栈中的元素数量压入计算栈顶。

DROP

指令:DROP
字节码:0x75
功能:移除计算栈栈顶的元素。

DUP

指令:DUP
字节码:0x76
功能:复制计算栈栈顶的元素。
输入:X
输出:X X

NIP

指令:NIP
字节码:0x77
功能:移除计算栈栈顶的第2个元素。
输入:X1 X0
输出:X0

OVER

指令:OVER
字节码:0x78
功能:复制计算栈栈顶的第二个元素,并压入栈顶。
输入:X1 X0
输出:X1 X0 X1

PICK

指令:PICK
字节码:0x79
功能:移除计算栈栈顶的元素n,并将剩余的索引为n的元素复制到栈顶。
输入:Xn Xn-1 ... X2 X1 X0 n
输出:Xn Xn-1 ... X2 X1 X0 Xn

ROLL

指令:ROLL
字节码:0x7A
功能:移除计算栈栈顶的元素n,并将剩余的索引为n的元素移动到栈顶。
输入:Xn Xn-1 ... X2 X1 X0 n
输出:Xn-1 ... X2 X1 X0 Xn

ROT

指令:ROT
字节码:0x7B
功能:移除计算栈栈顶的第3个元素,并将其压入栈顶。
输入:X2 X1 X0
输出:X1 X0 X2

SWAP

指令:SWAP
字节码:0x7C
功能:交换计算栈栈顶两个元素的位置。
输入:X1 X0
输出:X0 X1

TUCK

指令:TUCK
字节码:0x7D
功能:复制计算栈栈顶的元素到索引为2的位置。
输入:X1 X0
输出:X0 X1 X0

字符串操作

CAT

指令:CAT
字节码:0x7E
功能:移除计算栈栈顶的两个元素,并将其拼接后压入栈顶。
输入:X1 X0
输出:Concat(X1,X0)

SUBSTR

指令:SUBSTR
字节码:0x7F
功能:移除计算栈栈顶的三个元素,取子串后压入栈顶。
输入:X index len
输出:SubString(X,index,len)

LEFT

指令:LEFT
字节码:0x80
功能:移除计算栈栈顶的两个元素,取子串后压入栈顶。
输入:X len
输出:Left(X,len)

RIGHT

指令:RIGHT
字节码:0x81
功能:移除计算栈栈顶的两个元素,取子串后压入栈顶。
输入:X len
输出:Right(X,len)

SIZE

指令:SIZE
字节码:0x82
功能:将计算栈栈顶元素的长度压入栈顶。
输入:X
输出:X len(X)

逻辑运算

INVERT

指令:INVERT
字节码:0x83
功能:对计算栈栈顶的元素按位取反。
输入:X
输出:~X

AND

指令:AND
字节码:0x84
功能:对计算栈栈顶的两个元素执行按位与运算。
输入:AB
输出:A&B

OR

指令:OR
字节码:0x85
功能:对计算栈栈顶的两个元素执行按位或运算。
输入:AB
输出:A|B

XOR

指令:XOR
字节码:0x86
功能:对计算栈栈顶的两个元素执行按位异或运算。
输入:AB
输出:A^B

EQUAL

指令:EQUAL
字节码:0x87
功能:对计算栈栈顶的两个元素执行逐字节的相等判断。
输入:AB
输出:Equals(A,B)

算术运算

INC

指令:INC
字节码:0x8B
功能:对计算栈栈顶的大整数执行递增运算。
输入:X
输出:X+1

DEC

指令:DEC
字节码:0x8C
功能:对计算栈栈顶的大整数执行递减运算。
输入:X
输出:X-1

SIGN

指令:SIGN
字节码:0x8D
功能:获取计算栈栈顶的大整数的符号(负、正或零)。
输入:X
输出:X.Sign()

NEGATE

指令:NEGATE
字节码:0x8F
功能:求计算栈栈顶的大整数的相反数。
输入:X
输出:-X

ABS

指令:ABS
字节码:0x90
功能:求计算栈栈顶的大整数的绝对值。
输入:X
输出:Abs(X)

NOT

指令:NOT
字节码:0x91
功能:对计算栈栈顶的元素执行逻辑非运算。
输入:X
输出:!X

NZ

指令:NZ
字节码:0x92
功能:判断计算栈栈顶的大整数是否为非0值。
输入:X
输出:X!=0

ADD

指令:ADD
字节码:0x93
功能:对计算栈栈顶的两个大整数执行加法运算。
输入:AB
输出:A+B

SUB

指令:SUB
字节码:0x94
功能:对计算栈栈顶的两个大整数执行减法运算。
输入:AB
输出:A-B

MUL

指令:MUL
字节码:0x95
功能:对计算栈栈顶的两个大整数执行乘法运算。
输入:AB
输出:A*B

DIV

指令:DIV
字节码:0x96
功能:对计算栈栈顶的两个大整数执行除法运算。
输入:AB
输出:A/B

MOD

指令:MOD
字节码:0x97
功能:对计算栈栈顶的两个大整数执行求余运算。
输入:AB
输出:A%B

SHL

指令:SHL
字节码:0x98
功能:对计算栈中的大整数执行左移运算。
指令:Xn
字节码:X<<n

SHR

指令:SHR
字节码:0x99
功能:对计算栈中的大整数执行右移运算。
输入:Xn
输出:X>>n

BOOLAND

指令:BOOLAND
字节码:0x9A
功能:对计算栈栈顶的两个元素执行逻辑与运算。
输入:AB
输出:A&&B

BOOLOR

指令:BOOLOR
字节码:0x9D
功能:对计算栈栈顶的两个元素执行逻辑或运算。
输入:AB
输出:A||B

NUMEQUAL

指令:NUMEQUAL
字节码:0x9C
功能:对计算栈栈顶的两个大整数执行相等判断。
输入:AB
输出:A==B

NUMNOTEQUAL

指令:NUMNOTEQUAL
字节码:0x9E
功能:对计算栈栈顶的两个大整数执行不相等判断。
输入:AB
输出:A!=B

LT

指令:LT
字节码:0x9F
功能:对计算栈栈顶的两个大整数执行小于判断。
输入:AB
输出:A<B

GT

指令:GT
字节码:0xA0
功能:对计算栈栈顶的两个大整数执行大于判断。
输入:AB
输出:A>B

LTE

指令:LTE
字节码:0xA1
功能:对计算栈栈顶的两个大整数执行小于等于判断。
输入:AB
输出:A<=B

GTE

指令:GTE
字节码:0xA2
功能:对计算栈栈顶的两个大整数执行大于等于判断。
输入:AB
输出:A>=B

MIN

指令:MIN
字节码:0xA3
功能:取出计算栈栈顶的两个大整数中的最小值。
输入:AB
输出:Min(A,B)

MAX

指令:MAX
字节码:0xA4
功能:取出计算栈栈顶的两个大整数中的最大值。
输入:AB
输出:Max(A,B)

WITHIN

指令:WITHIN
字节码:0xA5
功能:判断计算栈中的大整数是否在指定的数值范围内。
输入:XAB
输出:A<=X&&X<B

密码学

实现了常用的哈希运算以及签名验证等。

SHA1

指令:SHA1
字节码:0xA7
功能:对计算栈栈顶的元素执行SHA1运算。
输入:X
输出:SHA1(X)

SHA256

指令:SHA256
字节码:0xA8
功能:对计算栈栈顶的元素执行SHA256运算。
输入:X
输出:SHA256(X)

HASH160

指令:HASH160
字节码:0xA9
功能:对计算栈栈顶的元素执行内置的160位散列运算。
输入:X
输出:HASH160(X)

HASH256

指令:HASH256
字节码:0xAA
功能:对计算栈栈顶的元素执行内置的256位散列运算。
输入:X
输出:HASH256(X)

CHECKSIG

指令:CHECKSIG
字节码:0xAC
功能:利用计算栈栈顶元素中的签名和公钥,对当前验证对象执行内置的非对称签名验证操作。
输入:SK
输出:Verify(S,K)

VERIFY

指令:VERIFY
字节码:0xAD
功能:利用计算栈栈顶元素中的签名、公钥和验证对象,执行内置的非对称签名验证操作。
输入:MSK
输出:Verify(M,S,K)

CHECKMULTISIG

指令:CHECKMULTISIG
字节码:0xAE
功能:利用计算栈栈顶元素中的多个签名和公钥,对当前验证对象执行内置的非对称多重签名验证操作。
输入:Sm-1 ... S2 S1 S0 m Kn-1 ... K2 K1 K0 n
输出:V
备注:对于任意的𝑆𝑆∈{𝑆0,…, 𝑆𝑆−1},存在一个𝑆𝑆∈{𝑆0, … , 𝑆𝑆−1}</br>使得Verify(𝑆𝑆, 𝑆𝑆) ==1,则V=1;否则,V=0。

高级数据结构

实现对Array、Map、Struct等的常用操作。

ARRAYSIZE

指令:ARRAYSIZE
字节码:0xC0
功能:获取计算栈栈顶的数组的元素数量。
输入:[X0 X1 X2 ... Xn-1]
输出:n

PACK

指令:PACK
字节码:0xC1
功能:将计算栈栈顶的n个元素打包成数组。
输入:Xn-1 ... X2 X1 X0 n
输出:[X0 X1 X2 ... Xn-1]

UNPACK

指令:UNPACK
字节码:0xC2
功能:将计算栈栈顶的数组拆包成元素序列。
输入:[X0 X1 X2 ... Xn-1]
输出:Xn-1 ... X2 X1 X0 n

PICKITEM

指令:PICKITEM
字节码:0xC3
功能:获取计算栈栈顶的数组中的指定元素。
输入:[X0 X1 X2 ... Xn-1] i
输出:Xi

SETITEM*

指令:SETITEM
字节码:0xC4
功能:对计算栈栈顶的数组中的指定位置元素赋值。
输入:[X0 X1 X2 ... Xn-1] I V
输出:[X0 X1 X2 Xi-1 V X i+1 ... Xn-1]

NEWARRAY

指令:NEWARRAY
字节码:0xC5
功能:在计算栈栈顶新建一个大小为n的Array
输入:n
输出:Array(n)值全为false的Array

NEWSTRUCT

指令:NEWSTRUCT
字节码:0xC6
功能:在计算栈栈顶新建一个大小为n的Struct
输入:n
输出:Struct(n)值全为false的Struct

NEWMAP

指令:NEWMAP
字节码:0xC7
功能:在计算栈栈顶新建一个Map
输入:
输出:Map()

APPEND*

指令:APPEND
字节码:0xC8
功能:向Array中添加一个新项
输入:Array item
输出:Array.add(item)

REVERSE*

指令:REVERSE
字节码:0xC9
功能:将Array元素倒序排列
输入:[X0 X1 X2 ... Xn-1]
输出:[Xn-1 ... X2 X1 X0]

REMOVE*

指令:REMOVE
字节码:0xCA
功能:从Array或Map中移除指定元素
输入:[X0 X1 X2 ... Xn-1] m
输出:[X0 X1 X2 ... Xm-1 Xm+1 ... Xn-1]

HASKEY

指令:HASKEY
字节码:0xCB
功能:判断Array或Map中是否包含Key指定元素
输入:[X0 X1 X2 ... Xn-1] key
输出:true 或 false

KEYS

指令:KEYS
字节码:0xCC
功能:获取Map的所有Key,并放入新的Array中
输入:Map
输出:[key1 key2 ... key n]

VALUES

指令:VALUES
字节码:0xCD
功能:获取Array或Map所有值,并放入新的Array中
输入:Map或Array
输出:[Value1 Value2... Value n]

栈隔离

CALL_I

指令:CALL_I
字节码:0xE0
功能:调用一个新的运行上下文,其脚本为当前上下文的脚本,
pcount指定参数个数,rvcount指定结果个数。执行指令跳转至新的运行上下文。

CALL_E

指令:CALL_E
字节码:0xE1
功能:调用一个新的运行上下文,其脚本由指令后20位Hash指定。
pcount指定参数个数,rvcount指定结果个数。执行指令跳转至新的运行上下文。

CALL_ED

指令:CALL_ED
字节码:0xE2
功能:调用一个新的运行上下文,其脚本由计算栈栈顶的Hash指定。
pcount指定参数个数,rvcount指定结果个数。执行指令跳转至新的运行上下文。

CALL_ET

指令:CALL_ET
字节码:0xE3
功能:CALL_E的尾调用形式。

CALL_EDT

指令:CALL_EDT
字节码:0xE4
功能:CALL_ED的尾调用形式。

异常处理

THROW

指令:THROW
字节码:0xF0
功能:将虚拟机状态置为FAULT

THROWIFNOT

指令:THROWIFNOT
字节码:0xF1
功能:从计算栈栈顶读取一个布尔值,如果为False,则将虚拟机状态置为FAULT

带*操作码表示该操作码的操作结果并未使用 PUSH() 放回计算栈。