概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
日本語をilasmに変換するコンパイラを書け。
zundokoをコンパイルせよ。
方針
- Plunker使う。
写真
投入したソース
乱数召喚し
変数 r に移動し
数値 0 を積み
変数 a に移動し
loop:
変数 r を積み
数値 3 を積み
乱数し
数値 1 を積み
比べて大なら zun へ飛ぶ
数値 0 を積み
変数 a に移動し
文字列 "ドコ" を積み
文字印字し
無条件で loop へ飛ぶ
zun:
文字列 "ズン" を積み
文字印字し
変数 a を積み
数値 1 を積み
足す
変数 a に移動し
変数 a を積み
数値 3 を積み
比べて大なら end へ飛ぶ
無条件で loop へ飛ぶ
end:
文字列 "ドコ,キヨシ!!" を積み
文字印字し
終わり。
実行結果
.assembly extern mscorlib {}
.assembly zundoko {}
.method static void main() {
.entrypoint
.locals init (class [mscorlib]System.Random r, int32 a)
newobj instance void [mscorlib]System.Random::.ctor()
stloc r
ldc.i4 0
stloc a
loop:
ldloc r
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::WriteLine(string)
br loop
zun:
ldstr "ズン"
call void [mscorlib] System.Console::WriteLine(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
}
サンプルコード
コンパイラ
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 i = 1;
var res = ".assembly extern mscorlib {}\n.assembly zundoko {}\n.method static void main() {\n.entrypoint\n.locals init (class [mscorlib]System.Random r, int32 a)\n";
while (i > 0)
{
var code = codes[pc].split(" ");
switch (code[1])
{
case "乱数召喚し":
res += " newobj instance void [mscorlib]System.Random::.ctor()\n";
pc++;
break;
case "文字列":
res += " ldstr " + code[2] + "\n";
pc++;
break;
case "数値":
res += " ldc.i4 " + code[2] + "\n";
pc++;
break;
case "変数":
if (code[3] == "を積み")
res += " ldloc " + code[2] + "\n";
if (code[3] == "に移動し")
res += " stloc " + code[2] + "\n";
pc++;
break;
case "数値印字し":
res += " call void [mscorlib] System.Console::WriteLine(int32)\n";
pc++;
break;
case "文字印字し":
res += " call void [mscorlib] System.Console::WriteLine(string)\n";
pc++;
break;
case "真なら":
res += " brtrue "+ code[2] + "\n";
pc++;
break;
case "偽なら":
res += " brfalse "+ code[2] + "\n";
pc++;
break;
case "比べて大なら":
res += " bgt "+ code[2] + "\n";
pc++;
break;
case "足す":
res += " add\n";
pc++;
break;
case "mul":
res += " 掛ける\n";
pc++;
break;
case "sub":
res += " 引く\n";
pc++;
break;
case "div":
res += " 割る\n";
pc++;
break;
case "剰余し":
res += " rem\n";
pc++;
break;
case "乱数し":
res += " callvirt instance int32 [mscorlib]System.Random::Next(int32)\n";
pc++;
break;
case "無条件で":
res += " br "+ code[2] + "\n";
pc++;
break;
case "終わり。":
res += " ret\n}\n";
i = 0;
break;
case undefined:
res += code[0] + "\n";
pc++;
break;
default:
alert(code[1]);
pc++;
break;
}
}
out.value = res;
}
検証
>ilasm zundoko5.il
Microsoft (R) .NET Framework IL Assembler. Version 4.8.9105.0
Copyright (c) Microsoft Corporation. All rights reserved.
Assembling 'zundoko5.il' to EXE --> 'zundoko5.exe'
Source file is ANSI
Assembled global method main
Creating PE file
Emitting classes:
Emitting fields and methods:
Global Methods: 1;
Emitting events and properties:
Global
Writing PE file
Operation completed successfully
>zundoko5
ドコ
ドコ
ドコ
ドコ
ドコ
ドコ
ドコ
ドコ
ドコ
ズン
ドコ
ドコ
ズン
ドコ
ドコ
ドコ
ズン
ドコ
ズン
ドコ
ドコ
ドコ
ドコ
ズン
ズン
ズン
ズン
ドコ,キヨシ!!
成果物
以上