上級 getting-started

Wasmバイナリフォーマット

.wasmバイナリ

すべての .wasm ファイルは8バイトから始まります:

00 61 73 6D    ← マジックナンバー: "\0asm"
01 00 00 00    ← バージョン: 1

ヘッダーの後、ファイルにはセクションが含まれます — 各セクションにはタイプID、サイズ、内容があります。

セクション

ID 名前 内容
0 Custom デバッグ情報、名前、メタデータ
1 Type 関数型シグネチャ (i32, i32) -> i32
2 Import JSからインポートされた関数/メモリ/グローバル
3 Function 関数インデックス → 型シグネチャのマッピング
4 Table 間接関数呼び出しテーブル
5 Memory リニアメモリ宣言(初期 + 最大ページ数)
6 Global グローバル変数宣言
7 Export JavaScriptに公開される関数/メモリ
8 Start インスタンス化時に呼ばれる関数
9 Element テーブル初期化データ
10 Code 実際の関数バイトコード
11 Data 静的データ(文字列、定数)

WAT: テキストフォーマット

WAT(WebAssembly Text)はWasmの人間が読める形式です。相互に変換できます:

# バイナリ → テキスト
wasm2wat my_module.wasm -o my_module.wat

# テキスト → バイナリ
wat2wasm my_module.wat -o my_module.wasm

WATでのシンプルな関数

(module
  ;; Typeセクション: 関数シグネチャ
  (type $add_type (func (param i32 i32) (result i32)))

  ;; Functionセクション + Codeセクション
  (func $add (type $add_type) (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add
  )

  ;; Exportセクション
  (export "add" (func $add))
)

これは以下のRustコードと同じものにコンパイルされます:

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

Wasm命令セット

Wasmはスタックマシンを使います — 命令がスタック上の値をプッシュ/ポップします:

;; (a + b) * 2 を計算
local.get $a     ;; スタック: [a]
local.get $b     ;; スタック: [a, b]
i32.add          ;; スタック: [a+b]
i32.const 2      ;; スタック: [a+b, 2]
i32.mul          ;; スタック: [(a+b)*2]

よく使う命令

命令 動作
local.get $x ローカル変数をプッシュ
local.set $x ポップしてローカルに格納
i32.const N 定数をプッシュ
i32.add 2つポップして合計をプッシュ
i32.mul 2つポップして積をプッシュ
i32.lt_s 2つポップして小さければ1をプッシュ
if...else...end 条件分岐
loop...br_if...end 条件付きブレークのループ
call $fn 関数呼び出し
return 関数からの復帰

ブラウザがWasmをロードする方法

// ステップ1: バイナリを取得
const response = await fetch('module.wasm');

// ステップ2: コンパイル(ストリーミング = ダウンロード中にコンパイル)
const module = await WebAssembly.compileStreaming(response);

// ステップ3: インスタンス化(インポートのリンク、メモリの確保)
const instance = await WebAssembly.instantiate(module, {
    env: {
        log: (ptr, len) => { /* WasmがインポートしたJS関数 */ }
    }
});

// ステップ4: エクスポートされた関数を呼び出す
const result = instance.exports.add(2, 3);

ストリーミングコンパイル

Download:  ████████████████████░░░░░
Compile:   ░░░████████████████████░░
Execute:   ░░░░░░░░░░░░░░░░░░░░░░██

ブラウザはダウンロード中にWasmをコンパイルします — そのため100KBのWasmファイルはダウンロード完了直後に実行可能な状態になることがあります。

.wasmファイルの検査

# エクスポートされたものを確認
wasm-objdump -x module.wasm

# 逆アセンブリを確認
wasm-objdump -d module.wasm

# セクションサイズを確認
wasm-objdump -h module.wasm

# 読みやすいテキストに変換
wasm2wat module.wasm

試してみよう

Run をクリックして、バイナリフォーマットの構造を確認しましょう — マジックバイト、バージョン、そして.wasmファイルを構成するすべてのセクションタイプを確認できます。

試してみる

チャプタークイズ

すべての問題に正解してレッスンを完了しましょう