SVX日記
2023-10-15(Sun) WebAssembly $00
;; https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/Control_flow
(module
(func $log (import "console" "log") (param i32))
(func (export "ifTest") (param $val i32)
local.get $val
if (result i32)
i32.const 456 ;; not 0: True
else
i32.const 123 ;; 0: False
end
call $log
)
(func (export "loopTest") (param $times i32) (result i32)
(local $i i32)
(local $sum i32)
i32.const 0 ;; 初期値
local.tee $i
local.set $sum
loop $loop1
local.get $i ;; 処理1
call $log
local.get $sum ;; 処理2 $sum += $i
local.get $i
i32.add
local.set $sum
local.get $i ;; $i += 1
i32.const 1
i32.add
local.tee $i
local.get $times
i32.lt_s ;; $i < $times
br_if $loop1
end
local.get $sum
)
(func (export "whileTest") (param $times i32)
(local $i i32)
local.get $times ;; 初期値
local.set $i
block $loop1
loop $loop2
local.get $i ;; $i == 0
i32.const 0
i32.eq
br_if $loop1 ;; break
local.get $i ;; 処理1
call $log
local.get $i ;; $i -= 1
i32.const 1
i32.sub
local.set $i
br $loop2 ;; continue
end
end
)
)
<!-- https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/Control_flow -->
<HTML>
<HEAD>
<TITLE>WebAssembly Control Flow Test</TITLE>
</HEAD>
<BODY>
<SCRIPT>
async function main() {
const importObjects = {
console: { log: (arg) => console.log(arg) },
};
const obj = await WebAssembly.instantiateStreaming(fetch('controlflow.wasm'), importObjects);
obj.instance.exports.ifTest(0);
obj.instance.exports.ifTest(1);
obj.instance.exports.ifTest(2);
let sum = obj.instance.exports.loopTest(11);
console.log('total:', sum);
obj.instance.exports.whileTest(5);
}
main();
</SCRIPT>
</BODY>
</HTML>
123
456
456
0
1
2
3
4
5
6
7
8
9
10
total: 55
5
4
3
2
1
まずは条件分岐(if)。WebAssemblyのifはスタックの先頭の値がゼロか非ゼロかで処理を分岐するものだ。JavaScriptから0を渡すとelseの123が返り、非ゼロを渡すと456が返っている。ちょっとクセがあるのは、アセンブラにはスタックのズレを検出する機能があり、if構造を抜けた際にスタックが高くなって(ズレて)いると、それが検出されてエラーになってしまうところだ。そういう場合「スタックに返り値を積んだんのですよ」と明示する必要がある。ifの後の「(result i32)」がそれだ。思い返せば、Z80の頃にプログラムを暴走させてしまう一番の原因はPUSHとPOPのズレだったよなぁ。
次は繰り返し(loop)。カウンタは0から加算され、指定した回数だけ実行される。中身に処理がないのもアレなんでカウンタの累計を計算して返すようにしてみた。11回のループで0〜10が加算され結果の55が返っている。