在寫程式之前,需要先準備好編譯工具。Web Assembly官方就有提供編譯工具,就是之前提到過的:wabt (Web Assembly Binary Toolkit)
git clone --recursive https://github.com/WebAssembly/wabt
下來之後,還需要先安裝Cmake以及作業系統可以使用的編譯器,例如Visual C++、clang、gcc、MinGW等等,依照他的說明,應該就可以編譯出執行檔。編譯出來的執行檔會放在clone目錄的bin之下。
編譯好之後,可以看到幾個執行檔:
使用方法,可以用[執行檔] --help
的方式查詢。之後這些也不會全用到,大概主要就是使用wat2wasm把文字格式的wat程式編譯成wasm,或是反過來把wasm轉成wat。另外一個我有使用的工具,是為了理解實際上編譯出來的wasm與wat有什麼差異,就是wat-desugar,後面會稍微提到。
如果只是想用wat來寫wasm,其實用wabt就可以。但是如果是想把asm.js跟wasm互轉、把llvm的Web Assembly Backend編譯出來的.s檔轉成wasm等等工作,就可以使用binaryen
。他也一樣可以拿來把wat/wast編譯成wasm或者反過來產出wat/wast。
安裝的方式跟wabt大同小異:
git clone https://github.com/WebAssembly/binaryen.git
cd binaryen
cmake . && make
執行檔也會放在bin目錄,可以看到:
使用wasm-as可以把wat/wast編譯成wasm,wasm-dis可以把wasm反組議程wat/wast。wasm-merge可以把幾個wasm檔合併成一個,wasm-opt可以最佳化產出的wasm檔,wasm-shell可以執行wat/wast檔並協助除錯等。
跟binaryen比較起來,wabt是比較簡潔的工具,所以我會先使用wabt,有需要再來看一看binaryen。
文字格式,顧名思義就是用人可閱讀的方式來寫程式,然後再編譯成wasm。
Web Assembly官網有解說文字格式的文件:Text Format。除了提到可以使用的編譯工具外,這個簡短的說明其實就是兩個重點
所以再回頭看一下之前寫的myadd.wat:
(module
(func (export "add") (param $a i32) (param $b i32) (result i32)
get_local $a
get_local $b
i32.add))
這裡面,程式部份就是三行:
get_local $a
get_local $b
i32.add
但是這三行其實並不符合S-Expression的語法。之前自己試寫的時候,以為全部都會用S-Expression,但是寫出來的東西完全過不了編譯...原來文件裡面寫很清楚,但是我沒仔細看XD
把格式的問題搞清楚以後,就可以開始研究怎麼寫程式。所以明天先稍微看看關於Web Assembly這個語言的一些基礎知識。
如果有看上一篇,會發現一件事情,就是跟文字格式比較起來,wasm檔有更多Section...所以在可能在編譯過程中,編譯器多做了一些事情。wabt裡面有一個工具叫做wat-desugar,可以去掉語法糖把程式最佳化。可以來看看用他處理myadd.wat的結果:
(module
(func (;0;) (param $a i32) (param $b i32) (result i32)
get_local $a
get_local $b
i32.add)
(export "add" (func 0))
(type (;0;) (func (param i32 i32) (result i32))))
這樣對照起來,func、code、export、type區段就都有了。程式中只寫了一個function,他的index就是0,然後在export以及type中,都是用這個index來參考到這個function。
原本的export是寫在func中,編譯的時候他會被拉出成一個export區段,使用add這個名字來對應到index是0的func。而type區段,其實也就是把func中宣告參數及回傳類型的資訊拉出來,同樣用index來對應。