[Atelier Blue アトリエブルー]Homeプログラミング IL(CIL,MSIL)>スタックの大きさ

スタックの大きさ

前回は次のコードを実行させると失敗するところで終わりました。というわけで、今回はこの不具合を解決することに全力を注ごうと思います。

.assembly extern mscorlib {}
.assembly outnum {}

.method static public void main () cil managed
{
    .entrypoint
    ldc.i4.1
    ldc.i4.2
    ldc.i4.3
    ldc.i4.4
    ldc.i4.5
    ldc.i4.6
    ldc.i4.7
    ldc.i4.8
    ldc.i4.s 9
    ldc.i4.s 10
    add
    add
    add
    add
    add
    add
    add
    add
    add
    call void [mscorlib]System.Console::WriteLine(int32)
    ret
}

ソースコードには間違いはないようです。こんな時は逆アセンブラの登場です。

.assembly extern mscorlib
{
  .ver 0:0:0:0
}
.assembly outnum
{
  .ver 0:0:0:0
}
.module outnum.EXE
// MVID: {71F6BFAC-F405-4546-BBF0-310B33FF02ED}
.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000001
// Image base: 0x00d90000

// =============== GLOBAL FIELDS AND METHODS ===================

//Global methods
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.method public static void  main() cil managed
{
  .entrypoint
  // コード サイズ       27 (0x1b)
  .maxstack  8
  IL_0000:  ldc.i4.1
  IL_0001:  ldc.i4.2
  IL_0002:  ldc.i4.3
  IL_0003:  ldc.i4.4
  IL_0004:  ldc.i4.5
  IL_0005:  ldc.i4.6
  IL_0006:  ldc.i4.7
  IL_0007:  ldc.i4.8
  IL_0008:  ldc.i4.s  9
  IL_000a:  ldc.i4.s  10
  IL_000c:  add
  IL_000d:  add
  IL_000e:  add
  IL_000f:  add
  IL_0010:  add
  IL_0011:  add
  IL_0012:  add
  IL_0013:  add
  IL_0014:  add
  IL_0015:  call     void [mscorlib]System.Console::WriteLine(int32)
  IL_001a:  ret
} // end of global method main

色々追加されていますが、今回注目すべき点は.maxstackです。

.maxstack

ちょっと前にスタックに積んで計算のモデルを書きましたよね?その時は入れたぶんだけスタックが延びていきましたが、現実には色々な制限が付きます。要するにスタックには最大サイズがあるのです。そして、この値は何も設定しないと「8」になります。

これで問題が解決しました。とりあえずは「.maxstack」の値を「10」にすればいいようです。

.assembly extern mscorlib {}
.assembly outnum {}

.method static public void main () cil managed
{
    .entrypoint
    .maxstack 10
    ldc.i4.1
    ldc.i4.2
    ldc.i4.3
    ldc.i4.4
    ldc.i4.5
    ldc.i4.6
    ldc.i4.7
    ldc.i4.8
    ldc.i4.s 9
    ldc.i4.s 10
    add
    add
    add
    add
    add
    add
    add
    add
    add
    call void [mscorlib]System.Console::WriteLine(int32)
    ret
}

これで問題は解決しました。このようにスタックマシンのスタックサイズは実行時に大きな意味を持つようです。

スタック使用数が少ない場合

スタック使用数が少ない場合も使うギリギリの値にスタックの使用数を調整した方がパフォーマンスが上がると考えられます。ですので、今までのソースコードにも「.maxstack」を使用してみましょう。

.assembly extern mscorlib {} /*入れても入れなくても良い。*/
.assembly hello {}

.method static public void main() cil managed
{
    .entrypoint
    .maxstack 1
    ldstr "Hello world!" //スタックに文字列を積む
    call void [mscorlib]System.Console::
                           WriteLine(class System.String)
                         //関数をコール
    ret                  //終了
}

こんな感じでスタックは節約した方が良さそうです。

ここまで読んでくれた方の中でILに詳しい方。スタック領域を少々大きく取っても連続の方がパフォーマンスが良かったりしますか?教えて頂けるとありがたいです。


ページの一番上へ
前のページへ一覧に戻る 次のページへ
初版2006-4-6
[Atelier Blue アトリエブルー]Homeプログラミング IL(CIL,MSIL)>スタックの大きさ