2015-11-27 3 views
6

У меня есть следующая программа для добавления значений. Когда я комментирую, добавьте метод вызова в основной метод и посмотрите в ILDASM.EXE. Размер Maxstack равен 2. И после раскомментирования размер maxstack равен 4.Расчет значения maxstack в коде IL

Почему в случае метода Main все переменные не входят в стек как стек размер остается только 2, в то время как в случае вызова метода Add каждая переменная переходит в стек? Это тот случай, когда внутри основного метода вычисляется один за другим, так что он принимает только две переменные за раз.

Пожалуйста, очистите мое замешательство.

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; 
} 

ответ

7

Каждая переменная инициализации:

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

Дифференциальный IL, когда вы раскомментировать метод Add ниже.

При вызове методы, вам необходимо нажать на ссылку экземпляра в стеке (то есть, если метод 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) 
+0

Я бы немного подправить фразировки в верхней части - это не * декларация *, которая использует пространство стека, это * инициализация *. –

+0

@Damien_The_Unbeliever Благодарим за отзыв и исправление. Фиксация. –

+0

Так же, как ИЛ не создается по строкам. Я хочу сказать, что если x = 2 принимает один стек, то почему бы не объявление другой ценности? Похоже, что компилятор пришел к пониманию того, что для этого требуется просто добавление, поэтому 2 места в стеке будут enogh. – TBAG