概要
wasmが、スタックマシンらしいので、やってみた。
wasmのwatで、hello worldやってみた。
サンプルコード
document.getElementById('runBtn').addEventListener('click', async () => {
const watCode = document.getElementById('watCode').value;
const resultOutput = document.getElementById('resultOutput');
const logOutput = document.getElementById('logOutput');
// 表示のリセットとエラークラスの除去
resultOutput.innerText = "実行中...";
resultOutput.parentElement.classList.remove('error');
logOutput.innerText = "";
try {
// WABTの初期化待ち
const wabt = await WabtModule();
// 1. WATコードのパース
let wasmModule = wabt.parseWat("main.wat", watCode);
// 2. バイナリ化
let buffer = wasmModule.toBinary({
log: true,
canonicalize_lebs: true,
relocatable: false,
write_debug_names: false
});
// 3. メモリ解放
wasmModule.destroy();
// ログの表示
logOutput.innerText = buffer.log || `bytesize: ${buffer.buffer.byteLength}`;
// 4. WebAssemblyのインスタンス化
const results = await WebAssembly.instantiate(buffer.buffer);
const exports = results.instance.exports;
// エクスポートされたメモリと関数があるか確認
if (exports.mem && exports.get_ptr && exports.get_len) {
// Wasm側のメモリ位置と長さを取得
const ptr = exports.get_ptr();
const len = exports.get_len();
// JavaScriptの Uint8Array を使ってWasmのメモリ空間を覗き見る
const memView = new Uint8Array(exports.mem.buffer, ptr, len);
// バイト配列を文字列(UTF-8)にデコードして表示
const decoder = new TextDecoder('utf-8');
resultOutput.innerText = decoder.decode(memView);
} else {
resultOutput.innerText = "エラー: 必要なメモリや関数 (mem, get_ptr, get_len) がエクスポートされていません。";
}
} catch (error) {
// 構文エラーなどを画面に赤く出す
resultOutput.innerText = `エラーが発生しました:\n${error.message}`;
resultOutput.parentElement.classList.add('error');
}
});
WATコード
(module
(memory (export "mem") 1)
(data (i32.const 0) "Hello, World!")
(func $get_ptr (result i32) i32.const 0)
(func $get_len (result i32) i32.const 13)
(export "get_ptr" (func $get_ptr))
(export "get_len" (func $get_len))
)
写真
成果物
以上。
