2013-10-24 1 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 스택 카운터입니까, 아니면 이것 뒤에 의미가 있습니까?

내 세계에서 IL_0014의 첫 번째 ldloc.0은 절대로 제거되지 않지만 어쩌면 get_Item의 callvirt가 작동하지 않는 것일 수도 있습니다. 내가 IL_0014에 도달했을 때 스택의 내 종이에 목록에 대한 참조가 있어야하고 그 후에 IL_0015에서 0이 평가 스택에 푸시 될 때 프로그램이 .maxstack을 위반합니다.

저는 초보자입니다. 그래서 옳지 않은 것이 있어야합니다. 어쩌면 제 카운팅이 옳고, 맥스 스택에 대한 제 이해가 잘못되었거나, 아마도 다른 방향 일 수도 있습니다. 누군가 .maxstack에 대한 나의 이해가 잘못되었다고 말해도 되겠습니까? .maxstack은 런타임에 스택의 최대 요소를 보여줍니다. 아니면 내 계산이 잘못 됐습니까? Add는 목록 인스턴스에 대한 참조를 제거합니까?

편집 : 다음은 내가 계산 한 것입니다. 카운트는 일리노이 코드가 실행 된 후입니다.

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를 읽지 않았다. 나는 그것을 사실적으로 찾고 있었다. 나는 일리노이에서 녹슬 었어. 감사! 어쩌면 그 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()의 반환 값을 하나 뒤로 푸시합니다.

편집 후 : 실제로 잘못된 부분입니다.

관련 문제