2013-10-24 45 views
1

我在調試模式下編譯了一些測試代碼,並用ILSpy反映了生成的程序集。這是我收到的IL:爲我解釋maxstack指令

.class private auto ansi beforefieldinit ArrayListBoxAndUnBox.Program 
extends [mscorlib]System.Object 
    { 
// Nested Types 
.class nested public auto ansi beforefieldinit Point 
    extends [mscorlib]System.Object 
{ 
    // Fields 
    .field public int32 x 
    .field public int32 y 

    // Methods 
    .method public hidebysig specialname rtspecialname 
     instance void .ctor() cil managed 
    { 
     // Method begins at RVA 0x209f 
     // Code size 7 (0x7) 
     .maxstack 8 

     IL_0000: ldarg.0 
     IL_0001: call instance void [mscorlib]System.Object::.ctor() 
     IL_0006: ret 
    } // end of method Point::.ctor 

} // end of class Point 


// Methods 
.method private hidebysig static 
    void Main (
     string[] args 
    ) cil managed 
{ 
    // Method begins at RVA 0x2050 
    // Code size 59 (0x3b) 
    .maxstack 2 
    .entrypoint 
    .locals init (
     [0] class [mscorlib]System.Collections.ArrayList list, 
     [1] int32 i, 
     [2] class ArrayListBoxAndUnBox.Program/Point p 
    ) 

    IL_0000: nop 
    IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor() 
    IL_0006: stloc.0 
    IL_0007: ldloc.0 
    IL_0008: ldc.i4.1 
    IL_0009: box [mscorlib]System.Int32 
    IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 
    IL_0013: pop 
    IL_0014: ldloc.0 
    IL_0015: ldc.i4.0 
    IL_0016: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32) 
    IL_001b: unbox.any [mscorlib]System.Int32 
    IL_0020: stloc.1 
    IL_0021: ldloc.0 
    IL_0022: newobj instance void ArrayListBoxAndUnBox.Program/Point::.ctor() 
    IL_0027: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 
    IL_002c: pop 
    IL_002d: ldloc.0 
    IL_002e: ldc.i4.1 
    IL_002f: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32) 
    IL_0034: castclass ArrayListBoxAndUnBox.Program/Point 
    IL_0039: stloc.2 
    IL_003a: ret 
} // end of method Program::Main 

.method public hidebysig specialname rtspecialname 
    instance void .ctor() cil managed 
{ 
    // Method begins at RVA 0x2097 
    // Code size 7 (0x7) 
    .maxstack 8 

    IL_0000: ldarg.0 
    IL_0001: call instance void [mscorlib]System.Object::.ctor() 
    IL_0006: ret 
} // end of method Program::.ctor 

} // end of class ArrayListBoxAndUnBox.Program 

我看到.maxstack被設置爲兩個,但是當我通過手工代碼我有時會計算堆棧上3個元素。爲什麼?我是一個糟糕的IL-stack-counter,還是這背後有意義?

在我的世界中,IL_0014上的第一個ldloc.0永遠不會被刪除,但也許只是我沒有得到callvirt如何get_Item的作品。當我到達IL_0014時,我必須參考堆棧文件中的列表,然後在IL_0015上,當0被推入評估堆棧時,程序違反了.maxstack。

我是新手,所以肯定有些東西是不對的。也許我的計數是正確的,我對.maxstack的理解是錯誤的,或者也許是相反的。有人能告訴我,如果我對.maxstack的理解是錯誤的,那麼.maxstack會在運行時顯示棧上的最大元素。或者如果我的計數錯誤?添加是否刪除對列表實例的引用?編輯: 這裏是我如何計數。計數是在IL代碼跑完之後:

IL_0000: 0 on stack 
IL_0001: 1 on stack (the reference to array list) 
IL_0006: 0 on stack 
IL_0007: 1 on stack (the reference to arraylist) 
IL_0008: 2 on stack (reference to arraylist and int 1) 
IL_0009: 2 on stack (refernce to arraylist and reference to object that wrap 1) 
IL_000e: 2 on stack (reference to arraylist and index to the added boxed int object) 
IL_0013: 1 on stack (reference to arraylist) 
IL_0014: 2 on stack (reference to arraylist and reference to arraylist) 
IL_0015: 3 on stack (reference to arraylist and reference to arraylist and int 0) 

我還沒有計算其餘的,因爲我知道我得到了錯誤的東西。

謝謝

+1

目前尚不清楚,你怎麼計算,這使得它很難看到你可能做錯了。你是否考慮過'callvirt'從棧中彈出目標和參數?參見ECMA-335的第III.4.2節。 –

+0

對不起。我已經更新了我的答案和我的數據。我沒有閱讀ECMA。我正在實實在在地尋找那個。我在我的IL裏有點生疏。謝謝!也許我沒有得到那個callvirt彈出的參考呢? – mslot

+0

'0e'彈出兩個ArrayList的參考和數量,然後按下一個'Int32' - 這就是你在哪裏錯了,你沒有注意到ArrayList中提及彈出。 –

回答

9

很難看到你出錯的地方。堆棧深度註釋左邊,指令執行後:

0 IL_0000: nop 
1 IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor() 
0 IL_0006: stloc.0 
1 IL_0007: ldloc.0 
2 IL_0008: ldc.i4.1 
2 IL_0009: box [mscorlib]System.Int32 
1 IL_000e: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 
0 IL_0013: pop 
1 IL_0014: ldloc.0 
2 IL_0015: ldc.i4.0 
1 IL_0016: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32) 
1 IL_001b: unbox.any [mscorlib]System.Int32 
0 IL_0020: stloc.1 
1 IL_0021: ldloc.0 
2 IL_0022: newobj instance void ArrayListBoxAndUnBox.Program/Point::.ctor() 
1 IL_0027: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object) 
0 IL_002c: pop 
1 IL_002d: ldloc.0 
2 IL_002e: ldc.i4.1 
1 IL_002f: callvirt instance object [mscorlib]System.Collections.ArrayList::get_Item(int32) 
1 IL_0034: castclass ArrayListBoxAndUnBox.Program/Point 
0 IL_0039: stloc.2 
0 IL_003a: ret 

唯一的非平凡的人是ArrayList.Add()調用。它彈出兩個堆棧值,即ArrayList對象引用和Add()參數。並且推回一個,Add()的返回值。

編輯後:這的確是你在哪裏錯了。