概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
ilasmを日本語に変換するコンパイラを書け。
湯婆婆をコンパイルせよ。
写真
投入したソース
ldstr "契約書\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "甲は油屋当主として、乙を油屋に雇用することを契約し、\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "労働に伴う対価の支払いを右の通り、約定する。\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "なお、一日の労働の対価は金百円とする。\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "甲 油屋当主 湯婆婆\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "乙\r\n"
call void [mscorlib]System.Console::WriteLine(string)
ldstr "契約書だよ。そこに名前を書きな。"
call void [mscorlib]System.Console::WriteLine(string)
call string [mscorlib]System.Console::ReadLine()
dup
dup
stloc str
ldstr "フン。"
call void [mscorlib]System.Console::Write(string)
call void [mscorlib]System.Console::Write(string)
ldstr "というのかい。贅沢な名だねぇ。"
call void [mscorlib]System.Console::WriteLine(string)
newobj instance void [mscorlib]System.Random::.ctor()
ldc.i4 2
callvirt instance int32 [mscorlib]System.Random::Next(int32)
ldloc str
callvirt instance int32 [mscorlib]System.String::get_Length()
rem
ldc.i4 1
callvirt instance string [mscorlib]System.String::Substring(int32, int32)
dup
dup
ldstr "今からお前の名前は"
call void [mscorlib]System.Console::Write(string)
call void [mscorlib]System.Console::Write(string)
ldstr "だ。いいかい、"
call void [mscorlib]System.Console::Write(string)
call void [mscorlib]System.Console::Write(string)
ldstr "だよ。分かったら返事をするんだ、"
call void [mscorlib]System.Console::Write(string)
call void [mscorlib]System.Console::Write(string)
ldstr "!!"
call void [mscorlib]System.Console::WriteLine(string)
ret
実行結果
文字列 "契約書\r\n" を積み
文字印字し
文字列 "甲は油屋当主として、乙を油屋に雇用することを契約し、\r\n" を積み
文字印字し
文字列 "労働に伴う対価の支払いを右の通り、約定する。\r\n" を積み
文字印字し
文字列 "なお、一日の労働の対価は金百円とする。\r\n" を積み
文字印字し
文字列 "甲 油屋当主 湯婆婆\r\n" を積み
文字印字し
文字列 "乙\r\n" を積み
文字印字し
文字列 "契約書だよ。そこに名前を書きな。" を積み
文字印字し
コピペし
コピペし
変数 str に移動し
文字列 "フン。" を積み
文字列 "というのかい。贅沢な名だねぇ。" を積み
文字印字し
乱数召喚し
数値 2 を積み
乱数し
変数 str を積み
乱数し
剰余し
数値 1 を積み
乱数し
コピペし
コピペし
文字列 "今からお前の名前は" を積み
文字列 "だ。いいかい、" を積み
文字列 "だよ。分かったら返事をするんだ、" を積み
文字列 "!!" を積み
文字印字し
終わり。
サンプルコード
コンパイラ
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 "dup":
res += " コピペし\n";
pc++;
break;
case "newobj":
res += " 乱数召喚し\n";
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[3] == "[mscorlib]System.Console::WriteLine(int32)")
res += " 数値印字し\n";
if (code[3] == "[mscorlib]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;
}
成果物
以上