【发布时间】:2023-03-11 10:05:17
【问题描述】:
第二次尝试措辞:
我目前正在逐步掌握一些 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()这一行是调用另一个方法的那一行。
所以,我想我要问的问题是这样的:
- 以
IL_0000开头的每一行都是“新”评估堆栈吗? - 我在运行时看到的调用堆栈是此 IL 的加入\串联\过滤吗?
【问题讨论】:
-
@CodeCaster 我认为
call操作码称为方法。至少,这就是我目前所读到的内容所暗示的。 -
如果您引用 CLI 规范的相关部分可能会有所帮助,以便读者了解您的思路。
-
@CodeCaster 我现在只是在学习它,现在是视频和博客。我处于 MSIL 的“Hello World”阶段,因此很可能我的问题对任何有经验的人都没有意义。我会重新措辞并重试。
-
记住 eval 堆栈是一个抽象非常重要。它为编译器为其生成 CIL 的虚拟机提供服务。它与处理器执行的真实代码完全无关。 jitter 的工作,它所做的最重要的事情是摆脱 eval 堆栈,因为它完全太低效了。但是,是的,每个方法的 CIL 都有一个从头开始的虚拟评估堆栈。而你在调试器中看到的堆栈跟踪,大致就是一堆堆栈。
标签: c# .net vb.net cil callstack