这是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)
这里首先将"实例引用"加载到堆栈中,然后添加用于获取参数值的代码,其中还包括在堆栈上获取实例引用,然后是使用实例引用的实际调用.
Ldarg.0 是 this一个实例方法.
一个是得到f,另一个是打电话M2.
(从技术上讲,第二个是首先使用的,因为它在f访问时位于堆栈的顶部)
第二个也可以放在电话会议之前,但这并不重要 - 只要在拨打电话时就必须在堆栈顶部.