Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of nop in CIL

Tags:

c#

cil

So I wrote the following code in C#.

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

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

And the constructor of the class in IL looks like this

.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

There are 3 nop commands. (Which as I know stands for no operation). What is the need of those commands. I mean what would be the difference if there was no command at all instead of nop

like image 812
Dimitri Avatar asked Oct 06 '13 07:10

Dimitri


People also ask

Whats the point of nop?

A NOP is most commonly used for timing purposes, to force memory alignment, to prevent hazards, to occupy a branch delay slot, to render void an existing instruction such as a jump, as a target of an execute instruction, or as a place-holder to be replaced by active instructions later on in program development (or to ...

What is the significance of CIL or IL for. net aware language?

Understanding CIL is very important in writing dynamic assembly, allows developer to do changes in assembly by changing the IL code directly even if source code is not available and above all it gives clear understanding of internals of . net languages.


2 Answers

They are used by the C# compiler when it writes the .pdb file for your program. Which contains debugging info, which includes file+line number info for your code. The debugger uses this to find the machine code where it needs to inject an INT 3 instruction to get the program to stop executing when you set a breakpoint. The jitter emits a NOP machine code instruction for each Opcodes.Nop in the MSIL.

The first nop is used when you set a breakpoint on public Test(). Note that it is injected after the base constructor call so that the this variable becomes valid in the Auto/Locals/Watch debugging windows.

The second nop is used when you set a breakpoint on the first { curly brace. That line generates no code at all so there's a hard need for a fake MSIL instruction.

Same story for the third nop, generated for the last } curly brace. When you set a breakpoint on that one then you can inspect the method return value (if any). Visible indirectly in the Debug + Windows + Registers window. Improved in VS2013.

So this just aids in debugging your program, they make breakpoints act predictably. Those NOPs are not generated when you build the Release configuration of your program. One big reason why a C# project has a Debug and a Release configuration. You can still debug a Release build, it is however a pretty confounding experience that makes you doubt your sanity :)

like image 145
Hans Passant Avatar answered Oct 22 '22 21:10

Hans Passant


They are used to support breakpoints when building in debug mode and will make no difference to the execution of your assembly.

like image 29
Jaycee Avatar answered Oct 22 '22 19:10

Jaycee