如果需要重複執行某個流程,可以使用 loop
,它也是一種區塊,因此看不到區塊前對堆疊的置入的數值,可以定義結果型態,若沒有定義,那離開區塊前必須清空堆疊。
loop
與 block
、if
不同的是,使用 br
指定分支流程至 loop
時,是指分支至 loop
開頭,而不是 end
!
例如,從 1 顯示到 10:
(module
(import "env" "log" (func $log (param i32)))
(func $main
(local $i i32)
(set_local $i (i32.const 1)) ;; i = 1
loop $LOOP
(i32.le_s (get_local $i) (i32.const 10)) ;; i <= 10
if
get_local $i
call $log
(set_local $i ;; i = i + 1
(i32.add (get_local $i) (i32.const 1)))
br $LOOP
end
end
)
(start $main)
)
loop
不會自動形成迴圈,如果不使用 br
指定流程分支至 $LOOP
,就不會重複進行運算,因此,想要製作無窮迴圈,基本上就是:
loop
br 0
end
來點真正的應用好了,例如,來計算 30 與 12 的最大公因數:
(module
(import "env" "log" (func $log (param i32)))
(func $main
(local $m i32) (local $n i32) (local $r i32)
(set_local $m (i32.const 30)) ;; m = 30
(set_local $n (i32.const 12)) ;; n = 12
loop $LOOP
(i32.ne (get_local $n) (i32.const 0)) ;; n != 0
if
(set_local $r ;; r = m % n
(i32.rem_s (get_local $m) (get_local $n)))
(set_local $m (get_local $n)) ;; m = n
(set_local $n (get_local $r)) ;; n = r
br $LOOP
end
end
get_local $m
call $log
)
(start $main)
)
來看個費式數的例子,求第 10 個費式數:
(module
(import "env" "log" (func $log (param i32)))
(func $main
(local $n i32) ;; 求第 n 個費式數
(local $a i32) (local $b i32)
(local $i i32) (local $tmp i32)
(set_local $n (i32.const 10)) ;; n = 10
(i32.or ;; n == 0 || n == 1
(i32.eqz (get_local $n))
(i32.eq (get_local $n) (i32.const 1))
)
if
get_local $n
call $log
else
(set_local $b (i32.const 1)) ;; b = 1
(set_local $i (i32.const 2)) ;; i = 2
loop
(i32.le_s (get_local $i) (get_local $n)) ;; i <= n
if
(set_local $tmp (get_local $b)) ;; tmp = b
(set_local $b ;; b = a + b
(i32.add (get_local $a) (get_local $b)))
(set_local $a (get_local $tmp)) ;; a = tmp
(set_local $i ;; i = i + 1
(i32.add (get_local $i) (i32.const 1)))
br 1
end
get_local $b
call $log
end
end
)
(start $main)
)