IL代码中maxstack值的计算
Calculation of maxstack value in IL code
我有以下程序来添加值。
当我在 main 方法中评论 Add 方法调用并查看 ILDASM.EXE Maxstack 大小为 2。取消注释后 maxstack 大小变为 4。
为什么在 Main 方法的情况下所有变量都没有进入堆栈,因为堆栈大小仅保持 2,而在 Add 方法调用的情况下每个变量都进入堆栈?
是不是在main方法里面的计算是一个一个发生的,所以一次只需要两个变量。
请解惑。
static void Main(string[] args)
{
int x = 2;
int y = 3;
int a = 4;
int b = 5;
int c = 6;
Console.WriteLine(x + y + a + b + c);
Console.WriteLine(Add(10, 20, 30, 40));
Console.ReadLine();
}
static int Add(int x, int y, int z, int a)
{
return x + y + z + a;
}
各变量初始化:
int x = 2;
将要求值在堆栈上:(堆栈大小:到目前为止需要 1 个)
.locals init ([0] int32 x,
[1] int32 y,
[2] int32 a,
[3] int32 b,
[4] int32 c)
IL_0000: ldc.i4.2 // push 2 to the stack
IL_0001: stloc.0 // load local variable 0 from stack ( x = 2 )
这些操作按顺序发生,因此所需的最大堆栈大小仍为 1,期间:
int y = 3;
int a = 4;
int b = 5;
int c = 6;
说到这里:
Console.WriteLine(x + y + a + b + c);
要添加任意两个变量,需要 2 的堆栈大小:
IL_000b: ldloc.0 // copy to stack x, max stack size required is still 1.
IL_000c: ldloc.1 // copy to stack y, max stack size required is 2 now.
IL_000d: add // execute add, will cause the sum x + y to be on stack
IL_000e: ldloc.2 // copy to stack a
IL_000f: add // execute add... (adds a to the result of x + y)
....
下面是取消注释 Add 方法时的微分 IL。
调用方法时,需要将实例引用压入堆栈(也就是说,如果 Add 方法是非静态的,则指向其声明类型的实例指针应压入堆栈)
然后,每个需要传递给方法的参数也应该被压入堆栈。
因此,在您的案例中,定义最大堆栈大小的是 Add 方法的参数数量。给这个Add方法添加一个参数,你会看到最大堆栈大小会增加到5:
// method is static so no need to push an instance pointer to the stack
IL_001a: ldc.i4.s 10 // push to stack
IL_001c: ldc.i4.s 20 // push to stack
IL_001e: ldc.i4.s 30 // push to stack
IL_0020: ldc.i4.s 40 // push to stack
IL_0022: call int32 Program::Add(int32,
int32,
int32,
int32)
IL_0027: call void [mscorlib]System.Console::WriteLine(int32)
我有以下程序来添加值。 当我在 main 方法中评论 Add 方法调用并查看 ILDASM.EXE Maxstack 大小为 2。取消注释后 maxstack 大小变为 4。
为什么在 Main 方法的情况下所有变量都没有进入堆栈,因为堆栈大小仅保持 2,而在 Add 方法调用的情况下每个变量都进入堆栈? 是不是在main方法里面的计算是一个一个发生的,所以一次只需要两个变量。
请解惑。
static void Main(string[] args)
{
int x = 2;
int y = 3;
int a = 4;
int b = 5;
int c = 6;
Console.WriteLine(x + y + a + b + c);
Console.WriteLine(Add(10, 20, 30, 40));
Console.ReadLine();
}
static int Add(int x, int y, int z, int a)
{
return x + y + z + a;
}
各变量初始化:
int x = 2;
将要求值在堆栈上:(堆栈大小:到目前为止需要 1 个)
.locals init ([0] int32 x,
[1] int32 y,
[2] int32 a,
[3] int32 b,
[4] int32 c)
IL_0000: ldc.i4.2 // push 2 to the stack
IL_0001: stloc.0 // load local variable 0 from stack ( x = 2 )
这些操作按顺序发生,因此所需的最大堆栈大小仍为 1,期间:
int y = 3;
int a = 4;
int b = 5;
int c = 6;
说到这里:
Console.WriteLine(x + y + a + b + c);
要添加任意两个变量,需要 2 的堆栈大小:
IL_000b: ldloc.0 // copy to stack x, max stack size required is still 1.
IL_000c: ldloc.1 // copy to stack y, max stack size required is 2 now.
IL_000d: add // execute add, will cause the sum x + y to be on stack
IL_000e: ldloc.2 // copy to stack a
IL_000f: add // execute add... (adds a to the result of x + y)
....
下面是取消注释 Add 方法时的微分 IL。
调用方法时,需要将实例引用压入堆栈(也就是说,如果 Add 方法是非静态的,则指向其声明类型的实例指针应压入堆栈)
然后,每个需要传递给方法的参数也应该被压入堆栈。
因此,在您的案例中,定义最大堆栈大小的是 Add 方法的参数数量。给这个Add方法添加一个参数,你会看到最大堆栈大小会增加到5:
// method is static so no need to push an instance pointer to the stack
IL_001a: ldc.i4.s 10 // push to stack
IL_001c: ldc.i4.s 20 // push to stack
IL_001e: ldc.i4.s 30 // push to stack
IL_0020: ldc.i4.s 40 // push to stack
IL_0022: call int32 Program::Add(int32,
int32,
int32,
int32)
IL_0027: call void [mscorlib]System.Console::WriteLine(int32)