调用堆栈和评估堆栈如何关联?
How are the call stack and the evaluation stack related?
第二次尝试措辞:
我目前正在逐步掌握一些 MSIL。
我一直听到 'Evaluation Stack' 谈论操作在加载、使用等时被推送和弹出的堆栈。
所以,给定以下代码:
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()
是调用另一个方法的行。
所以,我想我要问的问题是:
- 以
IL_0000
开头的每一行都是 'new' 评估堆栈吗?
- 我在运行时看到的调用栈是这个IL的joining\concatenation\filtering吗?
I think that the lines which start with IL_xxxx are the evaluation stack
Is each line starting with IL_0000 a 'new' evaluation stack?
没有。每种方法有一个评估堆栈。将其视为 Stack<object>
。 IL 指令通过压入和弹出项目对该堆栈进行操作。 MSDN 文档精确地调用了每个 IL 操作码的堆栈行为。
调用堆栈与计算堆栈无关。调用堆栈就是调用堆栈 Visual Studio window 向您显示的内容。
Is the call stack I see at runtime a joining\concatenation\filtering of this IL?
没有。没有关系。
感觉你的求值栈思路太复杂了。这是一个很简单的概念。只要你脑子里有复杂的东西,你就没有掌握它。不过,我不确定具体的误会在哪里。
请注意,评估堆栈是一个逻辑概念,用于定义 IL 程序的含义。与(禁止内联)确实存在的调用堆栈相比,它在运行时不再存在。
在 CIL 上下文中,它是抽象的(与在处理器上执行的物理代码相比)。
我会说 调用堆栈 是被调用方法“方法状态”的堆栈,评估堆栈 包含在每个“方法状态”并包含“执行数据”。
我们使用如下指令操作的数据:Pop
/ Ldarg
...
每个方法 - “方法状态” - 都有自己的本地评估堆栈。
第二次尝试措辞:
我目前正在逐步掌握一些 MSIL。
我一直听到 'Evaluation Stack' 谈论操作在加载、使用等时被推送和弹出的堆栈。
所以,给定以下代码:
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()
是调用另一个方法的行。
所以,我想我要问的问题是:
- 以
IL_0000
开头的每一行都是 'new' 评估堆栈吗? - 我在运行时看到的调用栈是这个IL的joining\concatenation\filtering吗?
I think that the lines which start with IL_xxxx are the evaluation stack
Is each line starting with IL_0000 a 'new' evaluation stack?
没有。每种方法有一个评估堆栈。将其视为 Stack<object>
。 IL 指令通过压入和弹出项目对该堆栈进行操作。 MSDN 文档精确地调用了每个 IL 操作码的堆栈行为。
调用堆栈与计算堆栈无关。调用堆栈就是调用堆栈 Visual Studio window 向您显示的内容。
Is the call stack I see at runtime a joining\concatenation\filtering of this IL?
没有。没有关系。
感觉你的求值栈思路太复杂了。这是一个很简单的概念。只要你脑子里有复杂的东西,你就没有掌握它。不过,我不确定具体的误会在哪里。
请注意,评估堆栈是一个逻辑概念,用于定义 IL 程序的含义。与(禁止内联)确实存在的调用堆栈相比,它在运行时不再存在。
在 CIL 上下文中,它是抽象的(与在处理器上执行的物理代码相比)。
我会说 调用堆栈 是被调用方法“方法状态”的堆栈,评估堆栈 包含在每个“方法状态”并包含“执行数据”。
我们使用如下指令操作的数据:Pop
/ Ldarg
...
每个方法 - “方法状态” - 都有自己的本地评估堆栈。