调用堆栈和评估堆栈是如何相关的?

时间:2015-03-12 21:43:36

标签: c# .net vb.net cil callstack

第二次尝试说明这一点:

我正在采取一些步骤来掌握一些MSIL。

我一直听到'评估堆栈'被称为堆栈,操作被加载,使用等时被推动和加载。

所以,给出以下代码:

public class Program
{
    public static void Main()
    {
        var message = GetMessage();

        Console.WriteLine(message);
    }

    public static string GetMessage()
    {
        return "Hello World!";
    }
}

MSIL看起来如此:

.class public auto ansi beforefieldinit Program
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    }

    .method public hidebysig static string GetMessage () cil managed 
    {
        .locals init (
            [0] string V_0
        )

        IL_0000: nop
        IL_0001: ldstr "Hello World!"
        IL_0006: stloc.0
        IL_0007: br.s IL_0009

        IL_0009: ldloc.0
        IL_000a: ret
    }

    .method public hidebysig static void Main () cil managed 
    {
        .entrypoint
        .locals init (
            [0] string V_0
        )

        IL_0000: nop
        IL_0001: call string Program::GetMessage()
        IL_0006: stloc.0
        IL_0007: ldloc.0
        IL_0008: call void [mscorlib]System.Console::WriteLine(string)
        IL_000d: nop
        IL_000e: ret
    }
}

认为IL_xxxx开头的行是评估堆栈(如果我错了请纠正我)。因此,行call string Program::GetMessage()是调用另一个方法的行。

所以,我想我问的问题是:

  1. 每行以IL_0000 a' new'开头?评估堆?
  2. 我在运行时看到的调用堆栈是否为此IL的加入\连接\过滤?

2 个答案:

答案 0 :(得分:5)

  

我认为以IL_xxxx开头的行是评估堆栈

     

每行是否以IL_0000开头a' new'评估堆栈?

没有。每种方法有一个评估堆栈。可以将其视为Stack<object>。 IL指令通过推送和弹出项目对该堆栈进行操作。 MSDN文档精确地调用每个IL操作码的堆栈行为。

调用堆栈与评估堆栈无关。调用堆栈是Call Stack Visual Studio窗口向您显示的内容。

  

我在运行时看到调用堆栈是否正在加入\ concatenation \过滤这个IL?

没有。没有关系。

我觉得你对评估堆栈的思考太复杂了。这是一个非常简单的概念。只要你有一些复杂的想法,你就没有把握它。不过,我不确定误解在哪里。

请注意,评估堆栈是用于定义IL程序含义的逻辑概念。与调用堆栈(禁止内联)确实存在相比,它在运行时不再存在。

答案 1 :(得分:0)

在 CIL 上下文中,它是抽象的(与在处理器上执行的物理代码相比)。

我会说调用堆栈是被调用方法“方法状态”的堆栈,评估堆栈包含在每个“方法状态”中并包含“执行数据”。 我们使用如下指令操作的数据:Pop / Ldarg...

每个方法 - “方法状态” - 都有自己的本地评估堆栈

参考:ECMA-335_6th_edition_june_2012.pdf - page: 108

OpCodes.Ldarg