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

.net 为什么.MaxStack指令在MSIL代码中是可选的?,.net,cil,.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 { //.ma

我在业余时间学习汇编语言。有人能解释为什么.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
}

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

如果我没有记错,如果省略该语句,默认堆栈大小为8。

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

第三部分-第1.7.4节

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

代码变得不可验证。同一节还指出,任何一致性实现都不需要支持具有无效最大堆栈值的方法。然而,它并没有说它一定不能,而且很明显,运行时正在执行代码。所以,如果它似乎没有效果,为什么还要费心去做呢

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

未处理的异常:System.InvalidProgrameException:公共语言运行库检测到无效程序。 基本上


记住这一点,不可验证的代码不能在任何没有完全信任的环境中运行(通常是来自internet的程序集)。如果这对您来说不重要,您可以让它成为无效值,并且它真的不会有什么区别。如果代码本身仍然正确,它将正常运行;当然,如果IL堆栈确实存在问题,它将抛出一个
invalidProgrameException

,这是我第一次想到的,但是如果我将上述程序中的.maxstack设置为1,程序仍然运行。从我看到的情况来看,程序应该是2或更高。在这里只是猜测,但也许ILASM足够聪明,能够意识到1不够,并覆盖设置。@500 InternalServerError,它不是。根据ILDASM,发出的代码实际上包含
.maxstack 1
。根据规范,此类代码应无效且无法验证。PEVerify实际上无法验证组件。但它运行正常。@w0051977,因为使用了默认大小8,正如500所指出的。您可以使用ildasm来验证这一点。这与将其设置为1时相同:它不是可验证的代码,但它确实运行,因为.Net似乎实际上不需要该值。