HOME/Articles/

WASM入門

Article Outline

WebAssemblyとは

ブラウザ上で動く仮想マシンを動かすための仕様のこと。

WebAssemblyアセンブリ言語の例

命令語 16進数
get_local $n 20
i32.const n 41
i32.add 6a

WebAssemblyアセンブリ言語→WebAssemblyマシン語

アセンブリ言語からマシン語に変換することをアセンブル、その機械をアセンブラという。

例えばWebAssemblyアセンブリ言語で足し算をする関数を書いてみます。

get_local 0
i32.const 1
i32.add
end

これをアセンブルすると、WebAssemblyマシン語(wasm)の完成。

0x00, 0x61, 0x73, 0x6d,
0x01, 0x00, 0x00, 0x00,
0x01, 0x06, 0x01, 0x60, 0x01, 0x7f, 0x01, 0x7f,
0x03, 0x02, 0x01, 0x00,
0x07, 0x05, 0x01, 0x01, 0x66, 0x00, 0x00,
0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x0b

0x20, 0x00, 0x41, 0x01, 0x6a

福野さん作の手書きWebAssembly。

https://fukuno.jig.jp/app/wasm/testenv/

アセンブリを書くのは辛い

マシン語を手書きするのは勿論、アセンブリ言語の手書きもつらいので高級言語を使います。

高級言語を用いることで、高級言語→コンパイル→アセンブリ言語→アセンブル→マシン語と変換できます。

zig言語を使う

zig言語を使ってWebAssemblyを吐かせてみます。

zig言語はC++やRustなどの他の言語に比べて仕様がシンプルだそう。

プロジェクトの作成

brew install zig

mkdir zig-playground
cd zig-playground

zig init-exe

ハローワールド

src/main.zigを編集します。

const std = @import("std");

pub fn main() anyerror!void {
    std.debug.print("Hello, {s}!\n", .{"World"});
}

実行。

zig run src/main.zig

">Image from Gyazo

wasmを吐かせる

src/main.zigを編集します。

export fn add(a: i32, b: i32) i32 {
  return a + b;
}

コンパイル。

zig build-lib src/main.zig -target wasm32-freestanding-musl -dynamic -O ReleaseSmall

中身を見てみる。

">Image from Gyazo

ブラウザからwasmを読み取る

index.htmlを作成。

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>WebAssembly</title>
</head>
<body>
  <script>
    WebAssembly.instantiateStreaming(fetch('main.wasm'))
      .then(obj => {
        const res = obj.instance.exports.add(1, 2);
        console.log(res)
      });
  </script>
</body>
</html>

Webサーバーを立ち上げる。なんでもいいですがかんたんなのでpython使ってます。

python3 -m http.server 8000

localhost:8000にアクセスしコンソールで確認。

">Image from Gyazo

WebAssemblyの仕様を知れば自作プログラミング言語をつくることも可能

参考文献

https://fukuno.jig.jp/1933

https://webassembly.github.io/spec/core/binary/index.html