概要
ilasmでstack machineやってみた。
ilasmをcopilotに解説してもらった。
投入したプロンプト
次のilasmを解説してくれ
.assembly extern mscorlib {}
.assembly fizzbuzz {}
.method static void main() {
.entrypoint
.locals init (int32 n, int32 i)
ldc.i4 100
stloc n
ldc.i4 1
stloc i
loop:
ldloc i
ldloc n
bgt bye
ldloc i
ldc.i4 15
rem
brfalse fb
ldloc i
ldc.i4 5
rem
brfalse b
ldloc i
ldc.i4 3
rem
brfalse f
ldloc i
call void [mscorlib] System.Console::WriteLine(int32)
br tugi
fb:
ldstr "fizzbuzz"
br print
b:
ldstr "buzz"
br print
f:
ldstr "fizz"
print:
call void [mscorlib] System.Console::WriteLine(string)
tugi:
ldloc i
ldc.i4 1
add
stloc i
br loop
bye:
ret
}
結果
なるほど、これはIL(中間言語)で書かれたFizzBuzzプログラムですね。
ILは、.NETフレームワークで動作するプログラムがコンパイルされる中間言語です。このプログラムの構造を分解してみましょう:
.assembly extern mscorlib {} と .assembly fizzbuzz {} で、アセンブリの宣言を行います。mscorlib は .NET の基本ライブラリです。
method static void main() { でメインメソッドを宣言し、その中でプログラムが実行されます。
主な処理の流れは次の通りです:
locals init (int32 n, int32 i) は、整数型のローカル変数 n と i を初期化します。
ldc.i4 100 と stloc n で、変数 n に100を格納します。
ldc.i4 1 と stloc i で、変数 i に1を格納します。
loop: ラベルでループの開始を示します。
ldloc i と ldloc n で i と n をスタックにロードし、bgt bye で i が n より大きい場合、bye ラベルにジャンプしてプログラムを終了します。
ldloc i と ldc.i4 15 で i を15で割り、その剰余を求めます。brfalse fb で剰余が0なら fb ラベル("fizzbuzz" を表示)にジャンプします。
ldloc i と ldc.i4 5 で同様に i を5で割り、brfalse b で剰余が0なら b ラベル("buzz" を表示)にジャンプします。
ldloc i と ldc.i4 3 で i を3で割り、brfalse f で剰余が0なら f ラベル("fizz" を表示)にジャンプします。
条件に当てはまらない場合は ldloc i で i の値を表示します(call void [mscorlib] System.Console::WriteLine(int32))。
tugi: ラベルで i に1を加算し(ldloc i、ldc.i4 1、add)、再び loop ラベルに戻ります(br loop)。
bye: ラベルでプログラムを終了します(ret)。
何か他にも質問があればどうぞ!