概要
ilasmでstack machineやってみた。
練習問題やってみた。
練習問題
日本語をilasmに変換するコンパイラを書け。
数9を4個つかって1から15までの数を表す式をコンパイルせよ。
写真
投入したソース
d1:
数値 9 を積み
数値 9 を積み
引く
数値 9 を積み
数値 9 を積み
割る
足す
数値印字し
d2:
数値 9 を積み
数値 9 を積み
割る
数値 9 を積み
数値 9 を積み
割る
足す
数値印字し
d3:
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
足す
数値 9 を積み
割る
数値印字し
d4:
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
数値 9 を積み
捨てる
コピペし
足す
数値印字し
d5:
数値 9 を積み
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
コピペし
足す
引く
数値印字し
d6:
数値 9 を積み
コピペし
数値 9 を積み
足す
数値 9 を積み
足す
数値 9 を積み
割る
引く
数値印字し
d7:
数値 9 を積み
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
引く
数値印字し
d8:
数値 9 を積み
数値 9 を積み
数値 9 を積み
割る
引く
数値 9 を積み
捨てる
数値印字し
d9:
数値 9 を積み
数値 9 を積み
引く
数値 9 を積み
掛ける
数値 9 を積み
足す
数値印字し
d10:
数値 9 を積み
数値 9 を積み
割る
数値 9 を積み
足す
数値 9 を積み
捨てる
数値印字し
d11:
数値 9 を積み
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
足す
数値印字し
d12:
数値 9 を積み
コピペし
数値 9 を積み
数値 9 を積み
足す
足す
数値 9 を積み
割る
足す
数値印字し
d13:
数値 9 を積み
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
コピペし
足す
足す
数値印字し
d14:
数値 9 を積み
コピペし
数値 9 を積み
数値 9 を積み
足す
数値 9 を積み
割る
コピペし
足す
引く
足す
数値印字し
d15:
数値 9 を積み
コピペし
コピペし
数値 9 を積み
足す
数値 9 を積み
足す
数値 9 を積み
割る
引く
足す
数値印字し
終わり。
実行結果
.assembly extern mscorlib {}
.assembly d94 {}
.method static void main() {
.maxstack 8
.entrypoint
d1:
ldc.i4 9
ldc.i4 9
sub
ldc.i4 9
ldc.i4 9
div
add
call void [mscorlib]System.Console::WriteLine(int32)
d2:
ldc.i4 9
ldc.i4 9
div
ldc.i4 9
ldc.i4 9
div
add
call void [mscorlib]System.Console::WriteLine(int32)
d3:
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
add
ldc.i4 9
div
call void [mscorlib]System.Console::WriteLine(int32)
d4:
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
ldc.i4 9
pop
dup
add
call void [mscorlib]System.Console::WriteLine(int32)
d5:
ldc.i4 9
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
dup
add
sub
call void [mscorlib]System.Console::WriteLine(int32)
d6:
ldc.i4 9
dup
ldc.i4 9
add
ldc.i4 9
add
ldc.i4 9
div
sub
call void [mscorlib]System.Console::WriteLine(int32)
d7:
ldc.i4 9
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
sub
call void [mscorlib]System.Console::WriteLine(int32)
d8:
ldc.i4 9
ldc.i4 9
ldc.i4 9
div
sub
ldc.i4 9
pop
call void [mscorlib]System.Console::WriteLine(int32)
d9:
ldc.i4 9
ldc.i4 9
sub
ldc.i4 9
mul
ldc.i4 9
add
call void [mscorlib]System.Console::WriteLine(int32)
d10:
ldc.i4 9
ldc.i4 9
div
ldc.i4 9
add
ldc.i4 9
pop
call void [mscorlib]System.Console::WriteLine(int32)
d11:
ldc.i4 9
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
add
call void [mscorlib]System.Console::WriteLine(int32)
d12:
ldc.i4 9
dup
ldc.i4 9
ldc.i4 9
add
add
ldc.i4 9
div
add
call void [mscorlib]System.Console::WriteLine(int32)
d13:
ldc.i4 9
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
dup
add
add
call void [mscorlib]System.Console::WriteLine(int32)
d14:
ldc.i4 9
dup
ldc.i4 9
ldc.i4 9
add
ldc.i4 9
div
dup
add
sub
add
call void [mscorlib]System.Console::WriteLine(int32)
d15:
ldc.i4 9
dup
dup
ldc.i4 9
add
ldc.i4 9
add
ldc.i4 9
div
sub
add
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
検証
>ilasm d9.il
Microsoft (R) .NET Framework IL Assembler. Version 4.8.9105.0
Copyright (c) Microsoft Corporation. All rights reserved.
Assembling 'd9.il' to EXE --> 'd9.exe'
Source file is UTF-8
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
>d9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
成果物
サンプルコード
コンパイラ
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 d94 {}\n.method static void main() {\n.maxstack 8\n.entrypoint\n";
while (i > 0)
{
var code = codes[pc].split(" ");
switch (code[1])
{
case "入力し":
res += " call string [mscorlib]System.Console::ReadLine()\n";
pc++;
break;
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::Write(string)\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 += " pop\n";
pc++;
break;
case "コピペし":
res += " dup\n";
pc++;
break;
case "足す":
res += " add\n";
pc++;
break;
case "掛ける":
res += " mul\n";
pc++;
break;
case "引く":
res += " sub\n";
pc++;
break;
case "割る":
res += " div\n";
pc++;
break;
case "剰余し":
res += " rem\n";
pc++;
break;
case "乱数し":
res += " callvirt instance int32 [mscorlib]System.Random::Next(int32)\n";
pc++;
break;
case "長さし":
res += " callvirt instance int32 [mscorlib]System.String::get_Length()\n";
pc++;
break;
case "切り出し":
res += " callvirt instance string [mscorlib]System.String::Substring(int32, 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;
}
以上