概要
ilasmでstack machineやってみた。
練習問題やってみた。
構想編
練習問題
elixirでilasmをアセンブルしてROM化せよ。
CPUの仕様設計
スタックマシン
-
命令長 12ビット
-
命令メモリー 12ビット256バイト
-
レジスタ 8ビット
文字列用 4バイト
プログラムカウンタ 1バイト
スタック用 6バイト
出力用 1バイト
変数用 2バイト
乱数用 1バイト -
フラグ
ジャンプ用1ビット -
命令セット
命令コード | ニーモニック | 意味 | stackの状態 |
---|---|---|---|
000 | nop | 何もしない。 | 変化無し |
001 | ret | 戻る | 変化無し |
1nn | ldc.i4 nn | stackに整数 nnを積む。 | 1個増える |
2nn | ldstr "fizzbuzz" | バッファに「fizzbuzz」を積む。 | 変化無し |
400 | call void [mscorlib] System.Console::WriteLine(int32) | トップを数値印刷。 | 1個減る |
500 | call void [mscorlib] System.Console::WriteLine(string) | バッファを文字印刷。 | 変化無し |
6nn | beq nn | セカンドとトップを比べて等しいならnnに飛ぶ。 | 2個減る |
7nn | bgt nn | セカンドとトップを比べて小さいならnnに飛ぶ。 | 2個減る |
8nn | blt nn | セカンドとトップを比べて大きいならnnに飛ぶ。 | 2個減る |
9nn | br nn | nnへ飛ぶ。 | 変化無し |
ann | brfalse nn | トップがゼロで無いならnnに飛ぶ。 | 1個減る |
bnn | brtrue nn | トップがゼロならnnに飛ぶ。 | 1個減る |
f00 | dup | stackにコピーを積む。 | 1個増える |
f01 | pop | stackを一個減らす。 | 1個減る |
f02 | add | セカンドとトップの加算を求める。 | 1個減る |
f03 | sub | セカンドとトップの減算を求める。 | 1個減る |
f04 | mul | セカンドとトップの乗算を求める。 | 1個減る |
f05 | div | セカンドとトップの除算を求める。 | 1個減る |
f06 | rem | セカンドとトップの剰余を求める。 | 1個減る |
f07 | callvirt instance int32 [mscorlib]System.Random::Next(int32) | stackに乱数を積む | 1個増える |
f09 | stloc a | 変数aにトップを移動。 | 1個減る |
f0a | ldloc a | stackに変数aの値を積む。 | 1個増える |
f0b | stloc b | 変数bにトップを移動。 | 1個減る |
f0c | ldloc b | stackに変数bの値を積む。 | 1個増える |
- 例外
ldstrは、命令長6バイト (なので アドレス計算 めんどくさくなっちゃた。)
rom[22] = 12'h201;
rom[23] = 12'h266;
rom[24] = 12'h269;
rom[25] = 12'h262;
rom[26] = 12'h275;
rom[27] = 12'h200;
投入するソース
fizzbuzz
ldc.i4 100
stloc b
ldc.i4 1
stloc a
loop:
ldloc a
ldloc b
bgt bye
ldloc a
ldc.i4 15
rem
brfalse fb
ldloc a
ldc.i4 5
rem
brfalse b
ldloc a
ldc.i4 3
rem
brfalse f
ldloc a
call void [mscorlib] System.Console::WriteLine(int32)
br tugi
fb:
ldstr "fibu"
br print
b:
ldstr "buzz"
br print
f:
ldstr "fizz"
print:
call void [mscorlib] System.Console::WriteLine(string)
tugi:
ldloc a
ldc.i4 1
add
stloc a
br loop
bye:
ret
以上