【问题标题】:Why is it loading both ldarg.0 and ldarg.1 when there are only 1 argument?为什么只有 1 个参数时同时加载 ldarg.0 和 ldarg.1?
【发布时间】:2019-06-15 21:02:12
【问题描述】:

我很困惑这个汇编代码是如何工作的。我试图四处寻找答案,但找不到任何东西。我认为 ldarg.0 是由于实例无效而加载的,但我不确定它为什么加载 ldarg.1。

如果有人能解释发生了什么,我将不胜感激。

.method public hidebysig specialname instance void set_phase(string value)
  {
    .maxstack 3
    .locals init (bool V0)
nop
ldarg.1
ldarg.0
ldfld    string KGER.Generate::_phase
call     bool [mscorlib]System.String::op_Inequality(string, string)
ldc.i4.0
ceq
stloc.0
ldloc.0
brtrue.s loc_4E8

提前致谢!

【问题讨论】:

  • ldarg.0 加载this 指针,然后ldfld 将其替换为this._phase 的值。代码基本上是在做if (value != this._phase)
  • instance 是关键,实例方法总是有一个额外的参数,它不是方法声明的一部分。它是第一个,它传递对象引用。又名this。静态方法没有那个参数。与扩展方法的语法进行比较。

标签: .net-assembly cil


【解决方案1】:

但是,您的代码并不完整:该部分执行以下操作:

.method public hidebysig specialname instance void set_phase(string value)
  {
    .maxstack 3
    .locals init (bool V0)

这是方法签名。从这里你推断出两个重要的事情:第一是该方法是一个instance 方法。这意味着第一个隐式参数包含this。 第二个重要的事情是由字符串类型的单个参数组成的签名:这将是arg1,因为arg0 隐式用于包含this

nop

从计算上讲,这没有任何作用。除此之外,nop 指令可以被调试器用来安全地放置断点

ldarg.1

这会将arg1 加载到堆栈中。堆栈包含(名为 value 的字段的值

ldarg.0
ldfld    string KGER.Generate::_phase

然后加载this 参数并立即使用它来加载KGER.Generate::_phase 字段。堆栈现在包含(值,_phase 字段的内容

call     bool [mscorlib]System.String::op_Inequality(string, string)

这会调用String 类的运算符op_Inequality,这是一个静态方法。堆栈现在包含(比较结果

ldc.i4.0

这会将 0 作为整数加载到堆栈中。我们知道这个值将是布尔比较的一部分,记住 0 相当于 false 用于这些目的

ceq

这会将两个值比较到堆栈中并将结果作为布尔值推入堆栈

stloc.0

这会将比较结果存储到一个局部变量(第一个)

ldloc.0

这会将存储到上述局部变量的比较结果再次加载到堆栈中,想必这是调试版本,而这对指令可以让开发者在调试时正确查看变量的值(或者是在你没有分享的部分代码中确实需要)

brtrue.s loc_4E8

当值为true(即1)时,这会跳转到位置loc_4E8,这意味着如果你两个字符串相等,代码就会跳转。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 2015-09-15
    相关资源
    最近更新 更多