为我解释maxstack指令
本文关键字:指令 maxstack 解释 | 更新日期: 2023-09-27 18:36:43
我在调试模式下编译了一些测试代码,并使用ILSpy反映了生成的程序集。这是我得到的 IL:
.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 设置为 2,但是当我手动浏览代码时,有时会在评估堆栈上得到 3 个元素。为什么?我是一个糟糕的IL堆栈计数器,还是这背后有什么意义?
在我的世界里,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)
其余的我没有数,因为我知道我做错了什么。
谢谢
很难看出你哪里出错了。 指令执行后左侧注释的堆栈深度:
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() 的返回值。
编辑后:这确实是您出错的地方。