概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
ilasmを日本語に変換するコンパイラを書け。
zundokoをコンパイルせよ。
写真
投入したソース
ldc.i4 0
stloc a
loop:
ldc.i4 3
callvirt instance int32 [mscorlib]System.Random::Next(int32)
ldc.i4 1
bgt zun
ldc.i4 0
stloc a
ldstr "ドコ"
call void [mscorlib]System.Console::Write(string)
br loop
zun:
ldstr "ズン"
call void [mscorlib]System.Console::Write(string)
ldloc a
ldc.i4 1
add
stloc a
ldloc a
ldc.i4 3
bgt end
br loop
end:
ldstr "ドコ,キヨシ!!"
call void [mscorlib]System.Console::WriteLine(string)
ret
実行結果
数値 0 を積み
変数 a に移動し
loop:
数値 3 を積み
乱数し
数値 1 を積み
比べて大なら zun へ飛ぶ
数値 0 を積み
変数 a に移動し
文字列 "ドコ" を積み
無条件で loop へ飛ぶ
zun:
文字列 "ズン" を積み
変数 a を積み
数値 1 を積み
足す
変数 a に移動し
変数 a を積み
数値 3 を積み
比べて大なら end へ飛ぶ
無条件で loop へ飛ぶ
end:
文字列 "ドコ,キヨシ!!" を積み
終わり。
サンプルコード
コンパイラ
var out = document.getElementById("out");
var src = document.getElementById("src");
function run() {
var str = src.value;
str = str.replace(/\t/g, " ");
str = str.replace(/ /g, " ");
str = str.replace(/ /g, " ");
str = str.replace(/ /g, " ");
var codes = str.split("\n");
var pc = 0;
var sp = 0;
var len = codes.length;
var i;
var label = {};
var val = {};
var ram = [];
var res = "";
for (i = 0; i < len; i++)
{
if (codes[i].indexOf(":") > -1)
{
label[codes[i]] = i;
}
}
while (i > 0)
{
var code = codes[pc].split(" ");
switch (code[1])
{
case "drop":
pc++;
break;
case "dup":
pc++;
break;
case "ldstr":
res += " 文字列 " + code[2] + " を積み\n";
pc++;
break;
case "ldc.i4":
res += " 数値 " + code[2] + " を積み\n";
pc++;
break;
case "stloc":
res += " 変数 "+ code[2] + " に移動し\n";
pc++;
break;
case "ldloc":
res += " 変数 "+ code[2] + " を積み\n";
pc++;
break;
case "call":
if (code[4] == "System.Console::WriteLine(int32)")
res += " 数値印字し\n";
if (code[4] == "System.Console::WriteLine(string)")
res += " 文字印字し\n";
pc++;
break;
case "brtrue":
res += " 真なら "+ code[2] + " へ飛ぶ\n";
pc++;
break;
case "brfalse":
res += " 偽なら "+ code[2] + " へ飛ぶ\n";
pc++;
break;
case "bgt":
res += " 比べて大なら "+ code[2] + " へ飛ぶ\n";
pc++;
break;
case "add":
res += " 足す\n";
pc++;
break;
case "mul":
res += " 掛ける\n";
pc++;
break;
case "sub":
res += " 引く\n";
pc++;
break;
case "div":
res += " 割る\n";
pc++;
break;
case "rem":
res += " 剰余し\n";
pc++;
break;
case "callvirt":
res += " 乱数し\n";
pc++;
break;
case "br":
res += " 無条件で "+ code[2] + " へ飛ぶ\n";
pc++;
break;
case "ret":
res += " 終わり。\n";
i = 0;
break;
case undefined:
res += code[0] + "\n";
pc++;
break;
default:
alert(code[1]);
pc++;
break;
}
}
out.value = res;
}
成果物
以上