IL code, Can someone explain to me why ldarg.0 appears twice?

This is C # code

class SimpleIL { private int f = 2; public void M1() { M2(f); } public void M2(Object p) { Console.WriteLine(p); } } 

This is the M1 IL method

  IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.0 IL_0003: ldfld int32 ConsoleApplication1.SimpleIL::f IL_0008: box [mscorlib]System.Int32 IL_000d: call instance void ConsoleApplication1.SimpleIL::M2(object) IL_0012: nop IL_0013: ret 

My question is: why double ldarg.0?

+6
source share
3 answers

The IL code can be grouped as follows:

 IL_0000: nop IL_0001: ldarg.0 // get the value for the parameter IL_0002: ldarg.0 IL_0003: ldfld int32 ConsoleApplication1.SimpleIL::f IL_0008: box [mscorlib]System.Int32 // call "this.M2(...)", this is already on the stack from before IL_000d: call instance void ConsoleApplication1.SimpleIL::M2(object) IL_0012: nop IL_0013: ret 

To invoke a method using IL, you do the following:

 load instance reference on the stack load argument values on the stack call method 

Here, the “instance reference” was first loaded onto the stack, then code was added to get the value of the parameter, which also included getting the reference to the instance on the stack, followed by the actual call that uses the instance reference.

+9
source

Ldarg.0 this in instance method.

One of them is to get f , the other is to call M2 .

(Technically, the second is used first, since it is on the top of the stack when f accesses it)

The second one can also be placed immediately before the call, but this does not matter much - it just needs to be on top of the stack when called.

+6
source

The first ldarg.0 loads the this pointer as the this argument to call M2 on the stack.

The second ldarg.0 loads the this pointer to access the f field.

+3
source

All Articles