NEOVM 就是 NEO& 39;s VM拆開(kāi)就很清楚了,Neo區(qū)塊鏈系統(tǒng)中使用的虛擬機(jī)。虛擬機(jī)就是虛擬的電腦,現(xiàn)在我們通常提到的虛擬機(jī)有兩種典型的形式
NEOVM 就是 NEO's VM
拆開(kāi)就很清楚了,Neo區(qū)塊鏈系統(tǒng)中使用的虛擬機(jī)。
虛擬機(jī)就是虛擬的電腦,現(xiàn)在我們通常提到的虛擬機(jī)有兩種典型的形式。
1.1一種是對(duì)一臺(tái)電腦完整的模擬
比如hyper-V,VMWare
還有街機(jī)模擬器
1.2另一種是僅僅作為執(zhí)行環(huán)境
比如JVM 比如dotnet framework 比如V8\lua
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),面對(duì)的執(zhí)行環(huán)境又分為兩大類情況。
1.2.1 公用執(zhí)行環(huán)境
公用執(zhí)行環(huán)境,比如java c# python
1.2.2 一種是嵌入式執(zhí)行環(huán)境
舉個(gè)例子,比如lua 就是一種典型的嵌入式腳本。
當(dāng)然也有通過(guò)mono 和 v8,把c# 和 js 作為嵌入式腳本使用的情況。
2 NeoVM是什么
NeoVM的形式就是上文 1.2.2 這種,和Lua相似,是一種嵌入式的執(zhí)行環(huán)境。
NeoVM是一種基于圖靈機(jī)模式的虛擬機(jī),通過(guò)磁頭在磁帶上的移動(dòng)改變狀態(tài),以此來(lái)實(shí)現(xiàn)邏輯運(yùn)算。
NeoVM 是 不依賴于Neo項(xiàng)目的一個(gè)單獨(dú)系統(tǒng),NeoVM只提供純粹的邏輯計(jì)算能力,采用可擴(kuò)展的互操作方式,后插入虛擬機(jī)可以調(diào)用的功能。
NeoVM的設(shè)計(jì)更貼近機(jī)器,執(zhí)行的代碼段是一個(gè)內(nèi)存塊,執(zhí)行時(shí)即時(shí)將數(shù)據(jù)解析為指令。
3 NeoVM的執(zhí)行方式
要說(shuō)明這件事情我們必須得復(fù)習(xí)一下圖靈機(jī)了
忽略我丑陋的字跡
這里就假設(shè)你了解磁帶式音樂(lè)播放器的工作原理,要不然head 和 tape 就變成一個(gè)晦澀的概念了。
1.在一條磁帶tape上寫上指令。
2.磁頭head負(fù)責(zé)讀取當(dāng)前指令
3.指令集是已知的 圖中展示了四條指令
nop 啥也不做 push [n] 將一個(gè)數(shù)字推到calcstack 中 add 從calcstack中取兩個(gè)值,將他們相加,再放回calcstack中 ret 結(jié)束當(dāng)前執(zhí)行。
4.寄存器空間來(lái)管理狀態(tài),對(duì)NeoVM來(lái)說(shuō)寄存器是兩個(gè)Stack,CalcStack 和 AltStack。
有磁帶,有磁頭,指令集,狀態(tài)空間,這就是一個(gè)圖靈機(jī)了。
4 Talk is cheap
讓我們來(lái)研究一下代碼吧
代碼在 samples/turing01
不到100行代碼,模擬了那副丑陋的畫里的圖靈機(jī)執(zhí)行過(guò)程。
首先是準(zhǔn)備好寫著代碼的磁帶
NOP
PUSH 1
PUSH 2
ADD
RET
然后滾動(dòng)磁帶,讓代碼一條條滾到磁頭下面
while(!vm.stop)
{
...
}
這里涉及到圖靈機(jī)的停機(jī)問(wèn)題,ret指令就是來(lái)通知停機(jī)的,要不然我們就會(huì)一直滾動(dòng)下去。當(dāng)然也可以依賴紙帶的長(zhǎng)度來(lái)停機(jī),實(shí)際上NEOVM是設(shè)計(jì)為紙帶用完自動(dòng)停機(jī)的 相信不會(huì)有人懷疑這個(gè)程序得到的retvalue是3。
讓我們來(lái)分析一下發(fā)生了什么。
這只是模擬程序,一次說(shuō)明一個(gè)問(wèn)題,我們用class Head表示磁頭,用List表示磁帶
滾動(dòng)磁帶是通過(guò)head.pos的累加
狀態(tài)空間 是 stop變量 和 calcstack 棧
執(zhí)行指令的步驟寫在函數(shù)StepOne中
StepOne 的過(guò)程是 1.讀取磁帶上位于磁頭處的代碼 2.執(zhí)行代碼 3.滾動(dòng)磁頭 head.pos++;
執(zhí)行代碼時(shí)就是操作狀態(tài)空間
NOP 什么也不干,但NOP依然是最重要的指令之一,你就把他當(dāng)作空格就好了。
RET 直接導(dǎo)致停機(jī),磁頭也不再滾動(dòng), 磁頭位置也是狀態(tài)空間的一部分,指令可以導(dǎo)致磁頭位置變化,這一點(diǎn)很重要,因?yàn)榱鞒炭刂频谋举|(zhì)就是磁頭位置變化,所有 的 if for while 邏輯,最后落實(shí)到vm上都是在改變磁頭位置。
PUSH 往calcstack上推一個(gè)值
ADD 從calcstack取兩個(gè)值,相加后再放回去
如果你跑起這個(gè)程序,斷點(diǎn),一步步StepOne,觀察calcstack,你會(huì)發(fā)現(xiàn):
1.nop 之后,什么也沒(méi)有發(fā)生 2.push 1 之后,calcstack里面是 [1] 3.push 2 之后,calcstack里面是 [2,1] 4.add 之后,calcstack 里面是 [3] 5.ret 之后,stop 變成true了,于是循環(huán)就結(jié)束了。
這就是NEOVM的工作原理了。
對(duì)NEOVM來(lái)說(shuō) .avm 就是這條tape了,不同之處在于avm是byte[],不是像我們這里使用的List 這么結(jié)構(gòu)化。
這篇的目的是解釋NEOVM是什么,是怎么工作的,先用這個(gè)簡(jiǎn)單的程序進(jìn)行說(shuō)明。(李劍英)