標籤:ar 資料 問題 代碼 c line ad ef 程式
如何列印出位元組碼:
代碼裡做如下修改,把列印位元組碼的宏開關開啟。
y.tab.c
18 行
#define LISTING 0
改為
#define LISTING 1
因為 PrintCode 的定義在調用之後,所以加個前置聲明:
做出下修改:
y.tab.c
329 行
添加
static void PrintCode (Byte *code, Byte *end);
保證在 lua_parse 調用它的時候,是已經聲明了的。
把列印位元組碼開啟之後,執行指令碼的時候就會先打位元組碼列印出來。
看看位元組碼列印出來是什麼樣,還來個 hello, world 吧
--------------------------------
print("Lua1.1 show bytecode")
print("hello, world")
--------------------------------
列印位元組碼如下:
CODE
0 PUSHGLOBAL 4
3 PUSHMARK
4 PUSHSTRING 8
7 CALLFUNC
9 ADJUST 0
10 PUSHGLOBAL 4
13 PUSHMARK
14 PUSHSTRING 9
17 CALLFUNC
19 ADJUST 0
20 HALT
Lua1.1 show bytecode
hello, world
簡單解釋下,最後的兩行是程式的執行結果,就是輸出了兩個字串。
前的從 "CODE" 開始直到 “HALT”結束的都是位元組碼。
每行的最左邊的標號位元組碼相對位移量,右面的就是位元組碼了。
--------------------------------
現在,就可以解決在 Lua1.0 裡說的那個 $debug 的問題了。
代碼和上面的一樣,除了在第一行加上 “$debug"。
--------------------------------
$debug
print("Lua1.1 show bytecode")
print("hello, world")
--------------------------------
列印位元組碼如下:
CODE
0 SETLINE 2
3 PUSHGLOBAL 4
6 PUSHMARK
7 PUSHSTRING 8
10 CALLFUNC
12 ADJUST 0
13 SETLINE 3
16 PUSHGLOBAL 4
19 PUSHMARK
20 PUSHSTRING 9
23 CALLFUNC
25 ADJUST 0
26 HALT
Lua1.1 show bytecode
hello, world
對比上面列印出來的位元組碼,可以看出區別了吧。 下面的位元組碼比上面多了 6 個位元組。我們看到下面的位元組碼多了下面 2 句,
0 SETLINE 2
13 SETLINE 3
這個 SETLINE 後面的標號對應的就是原始碼中的行號。這樣,比較方便對比位元組碼和原始碼。以後不特別說明的情況下,我們把每個指令碼的頭部都加上 "$debug" 來產生帶原始碼行號的位元組碼。
看了位元組碼,可以看出來一些問題,我們的 "hello, world" 這樣的字串跑哪兒去了?從位元組碼中體現不出來。
這個版本上,不可以直接執行編譯好的位元組碼,每次執行指令碼的時候,都得老老實實的從 Lua 指令碼原始碼編譯執行,原因就在這裡,看位元組碼裡,這種字串這樣的資料資訊丟失了。就是原始碼轉化為位元組碼後,位元組碼自己攜帶的資訊要少於原始碼。我們知道在寫組譯工具時,一般會把程式分為資料區段,程式碼片段。在位元組碼這裡,則相當於資料區段沒有了。那資料去哪兒了?資料在原始碼編譯為位元組碼中,儲存到了環境裡。而這樣的情況直到 Lua2.4 的時候,位元組碼才可以儲存下來,由解譯器直接執行。這樣的位元組碼是什麼樣的呢?我會不會分析一下呢?目前還沒有這樣的計劃。不過也說不定。計劃內的是 Lua5.x 之前,再分析一個 Lua4.0,因為那是 Lua 棧式虛擬機器的最後一個版本。到 Lua5.0 就變成了寄存器式的虛擬機器了。
我也嘗試過在 Lua1.0 裡開啟列印位元組碼的功能,不過,效果很差,內建的幾個例子中有不少看起來都像是死迴圈了,都大量的空指令(NOP,這是 Lua1.0 裡的一個指令,空指令引入的本意是在對位元組對齊有需求的體系架構上做為填充之用。不過實際上看來是沒有用上, Lua1.1 裡已經沒有這個指令了。)和輸出。
Lua1.1 列印位元組碼