【问题标题】:Do I understand this MSIL code correctly?我是否正确理解此 MSIL 代码?
【发布时间】:2012-08-29 10:09:02
【问题描述】:

我在 C# 中有以下代码

// test.Program
private static void Main()
{
    int x = 5;
    int y = 100;
    Console.WriteLine(y + ", " + x);
}

而且我正在阅读 IL 代码,我以前从未编写过汇编程序,所以我在问我每一行所做的是否正确。

.method private hidebysig static 
    void Main () cil managed 
{
    // Method begins at RVA 0x2058
    // Code size 33 (0x21)
    .maxstack 3 // maximum stack in this method is 3
    .entrypoint // method is initial entry point
    .locals init ( // reserves memory for x and y variables
        [0] int32 x, // x variable is reserved on position 0 of the stack
        [1] int32 y  // y variable is reserved on position 1 of the stack
    )
    IL_0000: ldc.i4.5     // integer of 4 bytes in size and the value of 5 is loaded onto the evaluation stack position 0
    IL_0001: stloc.0      // put evaluation stack position 0 into the stack position 0, the evaluation stack is emptied
    IL_0002: ldc.i4.s 100 // integer of 4 bytes in size and the value of 100 is loaded onto the evaluation stack position 0
    IL_0004: stloc.1      // put evaluation stack position 0 onto the stack position 1, the evaluation stack is emptied
    IL_0005: ldloc.1      // load stack position 1 into the evaluation stack position 0
    IL_0006: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack
    IL_000b: ldstr ", "   // put reference to string on evaluation stack position 1
    IL_0010: ldloc.0      // load stack position 0 into the evaluation stack position 2
    IL_0011: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack
    IL_0016: call string [mscorlib]System.String::Concat(object, object, object) // call Concat, pass values on evaluation stack, empty evaluation stack, put result of concat on evaluationstack
    IL_001b: call void [mscorlib]System.Console::WriteLine(string) // pass first value in evaluation stack
    IL_0020: ret         // return
} // end of method Program::Main

我对这个程序的理解正确吗?

【问题讨论】:

    标签: c# .net cil il ilasm


    【解决方案1】:

    差不多;我唯一要澄清的是,盒子(IL_0006 和 IL_0011)是type specific,所以它明确地构造了一个int 类型的盒子(它不仅仅是“最后一个值类型”) .

    此外,“空评估堆栈”具有误导性;这不太正确 - 例如,call 消耗给定数量的位置 - 它不会“清空”它。 从不“空评估堆栈”语义 - 它始终是“消耗多个值,放回多个值”(其中任何一个都可能为零)。

    【讨论】:

    • 当某物(例如调用)消耗了 n 个位置时,只消耗顶部位置对吗?然后将一些值放回评估堆栈?我想这是真的,因为它毕竟是一个“堆栈”,但我只是想确定一下。
    • 是的。读取 A、B、C、D 并生成 Y、Z 的假设操作将从堆栈中弹出 4 个条目*,计算结果*,然后将 2 个新条目推入其中。 (*) 不一定按此顺序,但推送始终是最后一个。
    【解决方案2】:

    是的,您的理解几乎完全正确。一件事:IL_0010 不从堆栈加载,它从本地加载。 (局部变量最终出现在运行时堆栈中,但在 IL 级别,它们被称为局部变量)。

    【讨论】:

    • OP 将“评估堆栈”单独描述给堆栈上的本地人,但我同意将它们称为本地人会更好。
    【解决方案3】:

    这是正确的,虽然我会用一些不清楚的措辞争论一下,例如:

    将评估堆栈位置0放入堆栈位置0,评估堆栈被清空

    我会说

    将栈顶的第 0 个条目放入栈变量 0th,然后弹出

    只是因为我认为“不太正式”的措辞在大多数情况下更容易阅读,但除此之外,它似乎还可以。

    编辑:嗯..事后我想说,没有像“堆栈”和“评估堆栈”这样的两个东西。只有“堆栈”。堆栈可见部分开始的标记部分,带有局部变量的部分可以称为“槽”。我想对于 IL,您可以只说“局部变量 Nth”,通常一切都会很清楚,但我认为几个不同的变量可能会映射到同一个插槽,因此可能会引起一些混乱。此外,当您使用堆栈时,没有像“清空”这样的操作。仅推送/弹出具有明确指定数量的要复制的条目。

    【讨论】:

      猜你喜欢
      • 2010-11-04
      • 2020-03-03
      • 2020-02-25
      • 2012-10-14
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      相关资源
      最近更新 更多