为什么.MaxStack指令在MSIL代码中是可选的?

w00*_*977 13 .net cil

我在业余时间学习汇编语言.谁能解释为什么.maxstack在这个程序中似乎是可选的.我试图在网上和我的书中找到答案没有这样的运气,即程序将编译并运行.Maxstack注释掉:

//Add.il
//Add Two Numbers

.assembly extern mscorlib {}

.assembly Add
{
    .ver 1:0:1:0
}
.module add.exe

.method static void main() cil managed
{
    //.maxstack 2
    .entrypoint

    ldstr "The sum of 50 and 30 is = "
    call void [mscorlib]System.Console::Write (string)

    ldc.i4.s 50
    ldc.i4 30    
    add
    call void [mscorlib]System.Console::Write (int32)
    ret
}
Run Code Online (Sandbox Code Playgroud)

我正在使用ILASM工具在命令行编译程序,然后运行生成的可执行文件.

Chr*_*ens 13

我认为你的困惑源于对.maxstack实际行为的误解.这是一个容易犯的错误,因为它似乎会在执行时导致错误.令人惊讶的是,该特定指令实际上与运行时的堆栈大小无关,而是在代码验证期间专门使用.

从分区III - 第1.7.4节

注意:Maxstack与程序分析有关,而与运行时堆栈的大小无关.它不指定堆栈帧的最大大小(以字节为单位),而是指定分析工具必须跟踪的项目数.

代码变得无法验证.同一部分指出,任何符合要求的实现都不需要支持具有无效最大堆栈值的方法.但是,它并没有说它必须不是,而且很明显,运行时正在执行代码.所以,如果它似乎没有效果,为什么甚至打扰它呢?

信不信由你,默认情况下,.NET框架运行无法验证的代码.实际上我很难弄清楚如何在.NET 4.0中启用验证,但如果你打开CAS,你的程序(with .maxstack 1)将停止运行

未处理的异常:System.InvalidProgramException:公共语言运行时检测到无效的程序.在主()

记住这一点,无法验证的代码无法在任何没有完全信任的环境中运行(通常是来自互联网的程序集).如果这对你来说不重要,你可以让它成为一个无效的价值,它实际上不会产生任何影响.如果代码本身仍然正确,它将运行良好; 当然,如果IL堆栈实际上存在问题,它将抛出一个InvalidProgramException.