2013-10-06 19 views
12

Also schrieb ich den folgenden Code in C#.Was ist der Punkt von NOP in CIL

class Test 
{ 
    int a; 
    System.IO.StreamReader reader; 

    public Test() 
    { 
     a = 5; 
     reader = new System.IO.StreamReader(String.Empty); 
    } 
} 

Und der Konstruktor der Klasse in IL wie folgt aussieht

.method public hidebysig specialname rtspecialname 
     instance void .ctor() cil managed 
{ 
    // Code size  33 (0x21) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: call  instance void [mscorlib]System.Object::.ctor() 
    IL_0006: nop 
    IL_0007: nop 
    IL_0008: ldarg.0 
    IL_0009: ldc.i4.5 
    IL_000a: stfld  int32 Test2.Test::a 
    IL_000f: ldarg.0 
    IL_0010: ldsfld  string [mscorlib]System.String::Empty 
    IL_0015: newobj  instance void [mscorlib]System.IO.StreamReader::.ctor(string) 
    IL_001a: stfld  class [mscorlib]System.IO.StreamReader Test2.Test::reader 
    IL_001f: nop 
    IL_0020: ret 
} // end of method Test::.ctor 

gibt es 3 nop Befehle. (Was ich weiß, steht für keine Operation). Was brauchen diese Befehle? Ich meine, was wäre der Unterschied, wenn es überhaupt keinen Befehl anstelle von nop

Antwort

16

Sie werden vom C# -Compiler beim Schreiben der PDB-Datei für Ihr Programm verwendet. Welche enthält Debugging-Informationen, die Datei + Zeilennummer Informationen für Ihren Code enthält. Der Debugger verwendet dies, um den Maschinencode zu finden, wo er eine INT 3-Anweisung einfügen muss, um das Programm dazu zu bringen, die Ausführung zu stoppen, wenn Sie einen Haltepunkt setzen. Der Jitter gibt eine NOP-Maschinencodeanweisung für jeden Opcodes.Nop in der MSIL aus.

Der erste NOP wird verwendet, wenn Sie einen Haltepunkt auf public Test() setzen. Beachten Sie, dass es nach der Basiskonstruktoraufruf injiziert wird, so dass die diese Variable in den Auto/Locals/Watch-Debugging-Fenstern gültig wird.

Der zweite NOP wird verwendet, wenn Sie einen Haltepunkt für die erste {geschweifte Klammer festlegen. Diese Zeile generiert überhaupt keinen Code, so dass eine falsche MSIL-Anweisung dringend benötigt wird.

Die gleiche Geschichte für den dritten nop, generiert für die letzte} geschweifte Klammer. Wenn Sie für diesen einen Haltepunkt festlegen, können Sie den Rückgabewert der Methode überprüfen (falls vorhanden). Im Fenster "Debug + Windows + Register" sichtbar. Verbessert in VS2013.

Das hilft also nur beim Debuggen Ihres Programms, sie machen Breakpoints vorhersagbar. Diese NOPs werden nicht generiert, wenn Sie die Release-Konfiguration Ihres Programms erstellen. Ein wichtiger Grund, warum ein C# -Projekt eine Debug- und eine Release-Konfiguration hat. Sie können immer noch einen Release Build debuggen, es ist jedoch eine ziemlich verwirrende Erfahrung, die Sie an Ihrer Vernunft zweifeln lässt :)

3

Sie würde verwendet, um Haltepunkte beim Aufbau im Debug-Modus zu unterstützen und wird keinen Unterschied für die Ausführung Ihrer Baugruppe machen.