WASI がなんだとか WASM がなんだとかは詳しく説明しません。各位やって。
まず Lucet を入れる。
はい
Hello, world! するには fd_write があればよさそう。
wasmtime/WASI-api.md at master · CraneStation/wasmtime · GitHub
引数はだいたい見りゃわかる。が、__wasi_ciovec_t
っつーのが引っかかる。
とはいえこれも見りゃわかる。
wasmtime/WASI-api.md at master · CraneStation/wasmtime · GitHub
バッファへのポインタとバッファの長さを持ってる構造体。
で、fd_write にはそいつのポインタを渡してやればいいということがわかる。
というところまでわかったら WAT を書く。S 式。
(module (import "wasi_unstable" "fd_write" (func $__wasi_fd_write (param i32 i32 i32 i32) (result i32))) (func $_start i32.const 1 i32.const 16 i32.const 13 i32.const 24 call $__wasi_fd_write drop) (memory 1) (data (i32.const 0) "Hello, world!\00\00\00\00\00\00\00\0d\00\00\00") (export "_start" (func $_start)))
import ってやつでリンクをやってて、data でメモリの初期値を埋めてる。export はエントリポイントの公開。
で、data に埋まってる初期値が大切で、ここに
"Hello, world!"(13bytes) + padding[0x00 0x00 0x00](3bytes) + buf address[0x00 0x00 0x00 0x00] (4bytes = i32) + buf length[0x0d 0x00 0x00 0x00](4bytes = i32)
が埋まっている。
buf address と buf length ってのが __wasi_ciovec_t
の中身。
ので、スタックに
1 ;; stdout の fd 16 ;; buf address へのアドレス 13 ;; "Hello, world!" のバイト数。buf length とは別にこれも必要らしい 24 ;; `nwritten` へのアドレスっぽい。戻り値はスタックに返ってくるんじゃねーのかよ(スタックにも返ってくるんだよな)
というかんじで積んでやって、call $__wasi_fd_write
してやる。
最後、スタックに nwritten
と思しき値が残ってしまうのでそいつを drop
で消し飛ばせば完了。
hello.wat
みたいな名前で保存してやって、以下のように実行できる。
lucetc-wasi -o hello.so hello.wat lucet-wasi hello.so
楽しいね