ildasm の .maxstack

[ad_1]

class Program
{
    static void Main(string[] args)
    {
        int first = 10;
        int second = 20;
        int third = 30;
        int forth = 40;
        int fifth = 50;

    }
}

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       18 (0x12)
  .maxstack  1
  .locals init ([0] int32 first,
           [1] int32 second,
           [2] int32 third,
           [3] int32 forth,
           [4] int32 fifth)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   10
  IL_0003:  stloc.0
  IL_0004:  ldc.i4.s   20
  IL_0006:  stloc.1
  IL_0007:  ldc.i4.s   30
  IL_0009:  stloc.2
  IL_000a:  ldc.i4.s   40
  IL_000c:  stloc.3
  IL_000d:  ldc.i4.s   50
  IL_000f:  stloc.s    fifth
  IL_0011:  ret
} // end of method Program::Main

私の質問は次のとおりです。

1 番目、2 番目、3 番目、4 番目、5 番目の変数は、スタック上のローカル変数として割り当てられます
スタック上の 5 つの変数の場合、.maxstack は 5 である必要があると思います
しかし、.maxstackは1を示しています その意味?

解決策 1

これを調べなければならなかったのですが、正確に0行のILを書きましたが、あなたの質問は興味深いです:
.maxstack は 最大評価スタックの深さ/高さ、IL を通過すると、評価スタックには最大で 1 つしかありません。

.locals init ([0] int32 first,
           [1] int32 second,
           [2] int32 third,
           [3] int32 forth,
           [4] int32 fifth)

ローカル変数を宣言します。

C#
IL_0000:  nop

無操作?? -何もしないのに、なぜわざわざ? 私が言うように、私はこのことの専門家ではありません。

IL_0001:  ldc.i4.s   10

定数 10 を評価スタックにロードします (スタック サイズ = 1)。

IL_0003:  stloc.0

値を評価スタックからローカルにポップします[0]. 評価スタック サイズ = 0。 他の変数についてすすぎ、繰り返しますが、最大評価スタック サイズ 5 つの値のそれぞれがスタックにプッシュされ、変数に個別にポップされるため、1 のままです。

仮説的に次のように書き直すことができると思います(おそらくコンパイルされません):

C#
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       18 (0x12)
  .maxstack  5
  .locals init ([0] int32 first,
           [1] int32 second,
           [2] int32 third,
           [3] int32 forth,
           [4] int32 fifth)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   10
  IL_0003:  ldc.i4.s   20
  IL_0004:  ldc.i4.s   30
  IL_0006:  ldc.i4.s   40
  IL_0007:  ldc.i4.s   50 //Stack size 5
  IL_0009:  stloc.4  //Stack size 4
  IL_000a:  stloc.3  //Stack size 3
  IL_000c:  stloc.2  //Stack size 2
  IL_000d:  stloc.1  //Stack size 1
  IL_000f:  stloc.0  //Stack size 0
  IL_0011:  ret
} 

[Edit]
これは yuthub のコメントへの返信です。MSIL/CIL は私のコンフォート ゾーンをはるかに超えているという警告とともに読む必要があります。:

実行時に複数のスタックが動作しています。 const が ldc によってプッシュされると、 評価 スタック (参照 ここ[^] 良い記事のために)。 値が評価スタックからポップされると、この場合はメソッド内の int 宣言であり、別のスタックに配置されます。スタックは、スタックとヒープについて議論するときに通常「スタック」として議論するスタックです。たとえば、C#のメモリ。 明確にするために、質問の前半を更新しました。

解決策 2

ここでの返信が非常に遅くなりましたが、それは、グーグルでこの記事を見つけた人に役立つ情報を追加したいからです.
.maxstack は、評価スタックではなくメソッド スタックの一部である .locals とはまったく関係ありません。

私たちが見ているのは、デバッグ構成で構築されたものを逆アセンブルした結果です。

これが、.locals リスト内のすべてのローカル変数に名前が付けられている理由であり、また、 いいえ オペレーション。 実際には操作はありませんが、ブレークポイントを配置できるコード内の関連するポイントをデバッガーに与えるために、プログラム内の実際のステップのようなものです。

リリース構成は、パフォーマンスのために最適化されたはるかに短いコードを生成します。これらの nop 命令は含まれておらず、ローカルの名前も削除されています。

ただし、実行時に実行される次のコンパイルステップである JIT によって、実際にはさらに多くの最適化が行われることに注意してください。

[ad_2]

Source link

コメント

タイトルとURLをコピーしました