今回はスタックサイズについて学びます。
まずは紫檀のコードの実行結果を予測してみてください。
.assembly hina{} .method public static void main(){ .entrypoint ldstr "あさってからはじめるIL" ldstr "明日からはじめるIL" ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) ret }
・・・はい。分かりましたか?
スタックは後入れ先出しの構造ですので、出力は「今日」「明日」「あさって」の順になります。では、これを三回出力するコードを作成してみましょう。
.assembly hina{} .method public static void main(){ .entrypoint ldstr "あさってからはじめるIL" ldstr "明日からはじめるIL" ldstr "今日からはじめるIL" ldstr "あさってからはじめるIL" ldstr "明日からはじめるIL" ldstr "今日からはじめるIL" ldstr "あさってからはじめるIL" ldstr "明日からはじめるIL" ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) call void [mscorlib]System.Console::WriteLine(string) ret }
これをコンパイルして実行してみてください。たぶん、実行時に例外が発生すると思います。
実は、このプログラム、ちょっとの修正でちゃんと動くようになります。「ldstr」をしたらすぐに「call」するように書き換えるだけです。
.assembly hina{} .method public static void main(){ .entrypoint ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "明日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "あさってからはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "明日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "あさってからはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "明日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ldstr "あさってからはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ret }
都合上、ldstrの順番が変わってしまっていますが、している事は同じです。
最大スタックサイズとはload出来る最大数の事です。まず、上の二つの最大スタックサイズを考えてみましょう。
まず、上。「ldstr」を9回繰り返しています。そのため、最大スタックサイズは「9」になります。
では、下はどうでしょうか?同じく「ldstr」は9回ありますが、一回ごとにcallを呼び出しているため、ロードされたデータはその都度なくなります。そのため、最大スタックサイズは「1」になります。
このように、二つのプログラムはしている事が同じでも最大スタックサイズが違います。
ILでは一つのメソッドで必要になる最大スタックサイズをユーザーが自分で設定できます。そして設定しない場合には最大スタックサイズは「8」になります。というわけで、設定方法です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 1 ldstr "今日からはじめるIL" call void [mscorlib]System.Console::WriteLine(string) ret }
「.maxstack 最大スタックサイズ」を描けば設定完了です。同じ要領で、さっきエラーのでた、9回連続のldstrもエラーがでないように出来ます。
それで、ここからが重要な事なのですが、.maxstackは必ず書く癖をつけましょう。ちなみに、サイズは必要な分だけにしてください。さばを読む必要はありません。これを行う理由はILの実行時コンパイルを速やかにするためです。
今回はこれで終わりです。長い割にした事は少ないです。これからは毎回書くので忘れないように。
次回は簡単な計算を行ってみましょう。