位元格式
大家也許會很好奇,用 wat2wasm 把文字轉成 wasm 檔的時候,跑出一大堆數字的部份是代表什麼意思?其實那就是轉換之後檔案裡實際的內容,也就是我們接下來要介紹的位元格式
LEB128 (Little-Endian Base 128)
雖然整數通常會有固定長度,像是 8, 16, 32, 64 bits,但是以 32 bits 來說,實際上常常不需要用到 32 bits 來表示。為了精減大小,WebAssembly 在位元格式上常常會使用 LEB128 格式來表示整數。
解碼
每個 byte 只用 7 bits 表示數值,剩下的 1 bit 表示是否結束
如果長度不夠,照有號/無號整數的方式補足長度,得到有號/無號整數的數值
編碼
負數
正數
以 32 位元整數來說,最多用到 5 個 byte,如果全都是 1 開頭的話表示錯誤;64 位元整數最多 10 個,16 位元最多 3 個,也是用這種方法檢查錯誤
雖然在數值接近最大值的時候,是用更多位元表示相同的數,不過大部分的狀況數值不會那麼大,所以用 LEB128 可以有效的降低檔案大小
數值型別的位元格式
模組的位元格式
接下來講解模組中各部份的位元格式,大家可以對照 wat2wasm 的輸出結果做印證
前文 (Preamble)
這部份固定佔 8 bytes,大部分的位元格式中幾乎都會有前文,用來區別不同的位元格式
魔術數字 (Magic number) 4 bytes
0x00 0x61 0x73 0x6d,用字碼轉換成文字之後就是 "\0asm",表示這是 wasm 格式
版本 (Version) 4 bytes
0x01 0x00 0x00 0x00,表示這是 0x01 版的 WebAssembly,在之前也有 0x0a, 0x0b, 0x0c, 0x0d的先行版本,之後如果推出新版的 WebAssembly,這邊就會變動
各部份標頭 (Section header)
接下來會分成許多部份 (Section),對照到在 模組 章節一般格式的各個部份。每個部份都不是必須的,沒有用到的話就不會產生
每個部份在依開始都會有個標頭 (header),標示各個部份的代碼還有長度
代碼 (Section code)
用來區分是哪個部份
長度 (Section size)
用一個 LEB128 32 位元無號整數,表示整個部份的長度 (不包括標頭)
在 wat2wasm 的輸出裡會看到這邊是 section size (guess),既然是guess,表示這的值是亂猜的,不用理會,也不會被編進檔案裡
真正的值在下面 FIXUP section size 的地方,在編進檔案的時候也是這個真正值會被寫到section size (guess)的位置上
函式型別 (Type section)
數量 (num types)
用一個 LEB128 32 位元無號整數,表示總共有多少函式型別
函式型別
引入 (Import section)
數量 (num imports)
用一個 LEB128 32 位元無號整數,表示總共有多少引入物件
引入物件:
在引入物件中,接下來的部份會依據不同的引入種類,而有不同的格式:
函式
一個 LEB128 32 位元無號整數,表示函式型別的編號
函式表
記憶體
全域變數
函式 (Function section)
數量 (num functions)
用一個 LEB128 32 位元無號整數,表示總共有多少函式
編號
一個或多個 LEB128 32 位元無號整數,表示該函式使用的函式型別編號
函式表 (Table section)
數量 (num tables)
用一個 LEB128 32 位元無號整數,表示總共有多少函式表 (目前只會是 1)
函式表
記憶體 (Memory section)
數量 (num memories)
用一個 LEB128 32 位元無號整數,表示總共有多少記憶體 (目前只會是 1)
記憶體
全域變數 (Global section)
數量 (num globals)
用一個 LEB128 32 位元無號整數,表示總共有多少全域變數
全域變數
輸出 (Export section)
數量 (num exports)
用一個 LEB128 32 位元無號整數,表示總共有多少全域變數
輸出物件
起始函式 (Start section)
索引值 (index)
一個 LEB128 32 位元無號整數,表示起始函式在模組中的編號
函式表元素 (Element section)
數量 (num elements)
用一個 LEB128 32 位元無號整數,表示總共有多少函式表元素
函式表元素
會根據這邊的資料,指定函式表的值
程式碼 (Code section)
程式碼部份表示函式的內容
數量 (num functions)
用一個 LEB128 32 位元無號整數,表示總共有多少函式內容
函式內容
區域變數 (在函式內容裏面)
相同種類且接連在一起宣告的區域變數,會合併成一個區域變數格式,所以才會有"數量"欄位
資料 (Data section)
資料部份表示記憶體的初始資料
數量 (num data)
用一個 LEB128 32 位元無號整數,表示總共有多少資料指定物件
資料指定物件
指令
指令的部份大部份是一個 byte 編碼,有些指令會加上額外的參數
控制指令
br_table 額外參數
跳回層數數量 : 一個 LEB128 32 位元無號整數
跳回層數 : 個 LEB128 32 位元無號整數
參數指令
記憶體指令
記憶體額外參數
對齊 (alignment) : 一個 LEB128 32 位元無號整數
(WasmVM 不會用到這個值)
位移 (offset) : 一個 LEB128 32 位元無號整數
常數指令
算術指令
Last updated