2012-08-29 9 views
17

Ich habe den folgenden Code in C#Verstehe ich diesen MSIL-Code richtig?

// test.Program 
private static void Main() 
{ 
    int x = 5; 
    int y = 100; 
    Console.WriteLine(y + ", " + x); 
} 

und ich bin der IL-Code lesen, habe ich noch nie Montage programmiert, bevor dann, wenn ich frage, was ich jede Zeile korrekt funktioniert ist.

.method private hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2058 
    // Code size 33 (0x21) 
    .maxstack 3 // maximum stack in this method is 3 
    .entrypoint // method is initial entry point 
    .locals init (// reserves memory for x and y variables 
     [0] int32 x, // x variable is reserved on position 0 of the stack 
     [1] int32 y // y variable is reserved on position 1 of the stack 
    ) 
    IL_0000: ldc.i4.5  // integer of 4 bytes in size and the value of 5 is loaded onto the evaluation stack position 0 
    IL_0001: stloc.0  // put evaluation stack position 0 into the stack position 0, the evaluation stack is emptied 
    IL_0002: ldc.i4.s 100 // integer of 4 bytes in size and the value of 100 is loaded onto the evaluation stack position 0 
    IL_0004: stloc.1  // put evaluation stack position 0 onto the stack position 1, the evaluation stack is emptied 
    IL_0005: ldloc.1  // load stack position 1 into the evaluation stack position 0 
    IL_0006: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack 
    IL_000b: ldstr ", " // put reference to string on evaluation stack position 1 
    IL_0010: ldloc.0  // load stack position 0 into the evaluation stack position 2 
    IL_0011: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack 
    IL_0016: call string [mscorlib]System.String::Concat(object, object, object) // call Concat, pass values on evaluation stack, empty evaluation stack, put result of concat on evaluationstack 
    IL_001b: call void [mscorlib]System.Console::WriteLine(string) // pass first value in evaluation stack 
    IL_0020: ret   // return 
} // end of method Program::Main 

Verstehe ich dieses Programm richtig?

Antwort

11

Ziemlich viel; Einziges, was ich klarstellen möchte, ist, dass die Box (IL_0006 und IL_0011) typspezifisch ist, so dass es explizit eine Box vom Typ int konstruiert (es ist nicht nur der "letzte Werttyp").

Auch "leerer Auswertungsstapel" ist irreführend; das ist nicht ganz richtig - zum Beispiel call verbraucht eine bestimmte Anzahl von Positionen - es "leer" es nicht. Es gibt nie einen "leeren Auswertungsstapel" semantisch - es ist immer "konsumiere eine Anzahl von Werten, setze eine Anzahl von Werten zurück" (von denen jeder Null sein kann).

+0

Wenn n Anzahl der Positionen von etwas konsumiert werden (rufen Sie zum Beispiel), nur Top-Positionen konsumiert werden richtig? Und setzt dann eine Anzahl von Werten auf den Auswertungsstapel zurück? Ich denke, das ist wahr, weil es schließlich ein "Stapel" ist, aber ich frage nur, um sicher zu sein. – ProgrammerAtWork

+1

Ja. Eine hypothetische Operation, die A, B, C, D liest und Y, Z erzeugt, würde 4 Einträge aus dem Stapel * ausgeben, das Ergebnis * berechnen und dann 2 neue Einträge darauf schieben. (*) nicht unbedingt in dieser Reihenfolge, aber Stöße sind immer die letzten. – quetzalcoatl

3

Ja, Ihr Verständnis ist fast vollständig richtig. Eine Sache: IL_0010 lädt nicht vom Stapel, es lädt von den Einheimischen. (Locals landen auf dem Runtime-Stack, auf der IL-Ebene heißen sie Locals).

+0

Das OP beschreibt den "Auswertungsstapel" getrennt von den Einheimischen auf dem Stapel, aber ich stimme zu, dass es besser wäre, sie nur Einheimische zu nennen. –

2

Es ist richtig, obwohl ich ein wenig mit etwas unklaren Formulierung argumentieren würde, zum Beispiel:

put Auswertungsstapel Position 0 in die Stapelposition 0 wird der Auswertungsstapel

geleert

ich würde sagen,

von der Oberseite des Stapels in Stapel Variable 0. 0. Eintrag setzt, dann

Pop

nur weil ich denke, eine "weniger formale" Formulierung ist in den meisten Fällen einfach zu lesen, aber ansonsten scheint es in Ordnung zu sein.

edit: hm .. im Nachhinein würde ich sagen, dass es keine zwei Dinge gibt wie "der Stapel" und "der Auswertestapel". Es gibt nur "den Stapel". Der markierte Teil des Beginns des sichtbaren Teils des Stapels, der mit lokalen Variablen, kann "Slots" genannt werden. Ich würde annehmen, dass man mit IL einfach "local variable Nth" sagen könnte und alles wäre normalerweise klar, aber ich denke, dass mehrere verschiedene Variablen auf denselben Slot abgebildet werden können, so dass es zu einiger Verwirrung führen kann. Außerdem gibt es keine Operation wie "Leeren", wenn Sie mit dem Stapel arbeiten. Nur push/pop mit einer explizit angegebenen Anzahl von zu kopierenden Einträgen.