2015-11-27 36 views
6

Mam następujący program do dodawania wartości. Kiedy nadchodzi komenda Dodaj wywołanie metody w głównej metodzie i zaglądając do pliku ILDASM.EXE. Rozmiar maksymalny to 2. Po odkomentowaniu rozmiar maksymalny staje się 4.Obliczanie wartości maksymalnej w kodzie IL

Dlaczego w przypadku metody głównej wszystkie zmienne nie wchodzą do stosu jako stos rozmiar pozostaje tylko 2, podczas gdy w przypadku metody Add call każda zmienna przechodzi na stos? Czy dzieje się tak dlatego, że główna kalkulacja metody odbywa się jedna po drugiej, tak aby pobierać tylko dwie zmienne na raz.

Proszę usunąć moje zamieszanie.

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

Odpowiedz

7

Każda zmienna inicjalizacji:

int x = 2; 

wymagać będzie wartość się na stosie (rozmiar stosu: 1 wymagane dotychczas)

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

Operacje te zdarzyć sekwencyjnie, dlatego Maksymalny wymagany rozmiar stosu to nadal 1, podczas:

int y = 3; 
int a = 4; 
int b = 5; 
int c = 6; 

A jeśli chodzi o to:

Console.WriteLine(x + y + a + b + c); 

Aby dodać dowolne dwie zmienne, rozmiar stosu 2 wymagana jest

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

Różnica IL kiedy odkomentować metoda dodawania jest poniżej.

Przy wywołaniu metody, trzeba wcisnąć odniesienie instancji na stosie (czyli, jeśli metoda dodawania był non-static, instancja wskaźnik do typu uznającej powinna być umieszczana na stosie)

Następnie każdy argument, który należy przekazać do metody, powinien również zostać przeniesiony na stos.

Dlatego jest to liczba parametrów metody Dodaj w twoim przypadku, która określa maksymalny rozmiar stosu. Dodaj parametr do tej metody Add, a zobaczysz, że maksymalny rozmiar stosu wzrośnie do 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

bym nieco podkręcić frazowanie u góry - to nie jest * deklaracja *, który wykorzystuje przestrzeń stosu, to jest * inicjalizacja *. –

+0

@Damien_The_Unbeliever Dziękujemy za recenzję i korektę. Naprawić to. –

+0

Więc to tak, jak IL nie jest generowane linia po linii. Chodzi mi o to, że jako x = 2 przyjmuje jeden stos spack, to dlaczego nie inne deklaracje wartości? Czy to tak, jak kompilator wiedział, że wymaga tylko dodania, więc 2 miejsca w stosie będą enogh. – TBAG