17

私はC#で次のコードを持っています

// test.Program
private static void Main()
{
    int x = 5;
    int y = 100;
    Console.WriteLine(y + ", " + x);
}

そして、私は IL コードを読んでいます。以前にアセンブリをプログラムしたことがないので、各行の動作が正しいかどうかを尋ねています。

.method private hidebysig static 
    void Main () cil managed 
{
    // Method begins at RVA 0x2058
    // Code size 33 (0x21)
    .maxstack 3 // maximum stack in this method is 3
    .entrypoint // method is initial entry point
    .locals init ( // reserves memory for x and y variables
        [0] int32 x, // x variable is reserved on position 0 of the stack
        [1] int32 y  // y variable is reserved on position 1 of the stack
    )
    IL_0000: ldc.i4.5     // integer of 4 bytes in size and the value of 5 is loaded onto the evaluation stack position 0
    IL_0001: stloc.0      // put evaluation stack position 0 into the stack position 0, the evaluation stack is emptied
    IL_0002: ldc.i4.s 100 // integer of 4 bytes in size and the value of 100 is loaded onto the evaluation stack position 0
    IL_0004: stloc.1      // put evaluation stack position 0 onto the stack position 1, the evaluation stack is emptied
    IL_0005: ldloc.1      // load stack position 1 into the evaluation stack position 0
    IL_0006: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack
    IL_000b: ldstr ", "   // put reference to string on evaluation stack position 1
    IL_0010: ldloc.0      // load stack position 0 into the evaluation stack position 2
    IL_0011: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack
    IL_0016: call string [mscorlib]System.String::Concat(object, object, object) // call Concat, pass values on evaluation stack, empty evaluation stack, put result of concat on evaluationstack
    IL_001b: call void [mscorlib]System.Console::WriteLine(string) // pass first value in evaluation stack
    IL_0020: ret         // return
} // end of method Program::Main

このプログラムを正しく理解していますか?

4

3 に答える 3

11

かなり。私が明確にしたいのは、ボックス(IL_0006およびIL_0011)がタイプ固有であるため、タイプのボックスを明示的に構築しているintことだけです(「最後の値タイプ」だけではありません)。

また、「空の評価スタック」は誤解を招きます。これは正しくありません。たとえば、指定された数のポジションをcall消費しますが、それを「空にする」わけではありません。「空の評価スタック」セマンティックは決してありません- それは常に「いくつかの値を消費し、いくつかの値を戻します」(どちらもゼロかもしれません)。

于 2012-08-29T10:13:25.947 に答える
3

はい、あなたの理解はほぼ完全に正しいです。1 つ: IL_0010 はスタックからロードされず、ローカルからロードされます。(ローカルは最終的にランタイム スタックになりますが、IL レベルではローカルと呼ばれます)。

于 2012-08-29T10:12:52.960 に答える
2

それは正しいですが、たとえば、次のような不明確な表現については少し反論したいと思います。

評価スタック位置 0 をスタック位置 0 に入れる。評価スタックは空になる

私は言うだろう

スタックの一番上から 0 番目のエントリをスタック変数 0 番目に入れ、ポップします。

ほとんどの場合、「形式ばらない」文言の方が読みやすいと思うからですが、そうでない場合は問題ないようです。

編集:うーん..後付けで、「スタック」と「評価スタック」のようなものは2つないと言います。「スタック」しかありません。スタックの可視部分の開始のマークされた部分で、ローカル変数を持つものは「スロット」と呼ばれることがあります。IL なら「ローカル変数 N 番目」と言うだけで、たいていすべてが明確になると思いますが、いくつかの異なる変数が同じスロットにマッピングされる可能性があるため、混乱を招く可能性があると思います。また、スタックを操作するときに「空にする」ような操作はありません。明示的に指定された数のエントリをコピーするプッシュ/ポップのみ。

于 2012-08-29T10:14:43.593 に答える