2013-10-24 3 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-стека, или есть смысл позади этого?

В моем мире первый ldloc.0 на IL_0014 никогда не удаляется, но, возможно, это просто я не понимаю, как работает callvirt для get_Item. Когда я добираюсь до IL_0014, у меня есть ссылки на список на моей бумаге стека, и после этого в IL_0015 программа нарушает .maxstack, когда 0 помещается в стек evalution.

Я новичок, поэтому должно быть что-то, что не так. Возможно, мой подсчет прав, и мое понимание .maxstack неверно, или, может быть, это наоборот. Может кто-нибудь, пожалуйста, скажите мне, не ошибается ли мое понимание .maxstack, что .maxstack показывает максимальные элементы в стеке во время выполнения. Или если мой счет ошибочен? Добавляет ли удаление ссылку на экземпляр списка?

EDIT: Вот как я рассчитываю. Счет после запуска кода 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) 

Я не считал остальное, потому что знаю, что у меня что-то не так.

Thanks

+1

Непонятно, как вы рассчитываете, что очень сложно понять, что вы, возможно, сделали неправильно. Вы учли, что 'callvirt' выталкивает цель и аргументы из стека? См. Раздел III.4.2 ECMA-335. –

+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().

После редактирования: это действительно то место, где вы поступили не так.

Смежные вопросы