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

C# IL代码,有人让我解释为什么ldarg.0出现两次吗?,c#,il,C#,Il,这是c代码 class SimpleIL { private int f = 2; public void M1() { M2(f); } public void M2(Object p) { Console.WriteLine(p); } } 这是M1方法的IL IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.0 IL_0003: ldfld int32 Cons

这是c代码

class SimpleIL { 
        private int f = 2; 
        public void M1() { M2(f); } 
        public void M2(Object p) { Console.WriteLine(p); } 
}
这是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

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

ldarg.0
在实例方法中是
这个

一个是获取
f
,另一个是调用
M2

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


第二个也可以放在调用之前,但这并不重要——调用时它必须位于堆栈顶部

第一个
ldarg.0
this
指针作为
M2
调用的
this
参数加载到堆栈上


第二个
ldarg.0
加载
this
指针,用于访问
f
字段。

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
要使用IL调用方法,请执行以下操作:

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

在这里,首先将“实例引用”加载到堆栈中,然后添加获取参数值的代码,这还涉及获取堆栈上的实例引用,然后是使用实例引用的实际调用。

@lucastrezesniewski:当然。”第二个也可以放在调用“不,它不能,如果这样做,堆栈的顺序就会错误。