IL代码,有人让我解释为什么ldarg.0出现两次?

Ste*_*enS 8 c# il

这是c#代码

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

这是M1方法的IL

 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
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么两次ldarg.0?

ang*_*son 12

IL代码可以这样分组:

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
Run Code Online (Sandbox Code Playgroud)

要使用IL调用方法,请执行以下操作:

load instance reference on the stack
load argument values on the stack
call method
Run Code Online (Sandbox Code Playgroud)

这里首先将"实例引用"加载到堆栈中,然后添加用于获取参数值的代码,其中还包括在堆栈上获取实例引用,然后是使用实例引用的实际调用.


Wik*_*hla 8

Ldarg.0this一个实例方法.

一个是得到f,另一个是打电话M2.

(从技术上讲,第二个是首先使用的,因为它在f访问时位于堆栈的顶部)

第二个也可以放在电话会议之前,但这并不重要 - 只要在拨打电话时就必须在堆栈顶部.