Methods 不需要ret的MSIL方法

Methods 不需要ret的MSIL方法,methods,return,cil,il,ilasm,Methods,Return,Cil,Il,Ilasm,我最近一直在尝试编写MSIL并使用ilasm编译它,当时我注意到方法确实需要ret指令才能从方法末尾返回; 例如,我应该编写如下代码: .method static void Main() { .entrypoint ldstr "Hello World!" call void [mscorlib]System.Console::WriteLine(string) ret //I am returning properly } 但是,如果省略ret,代码仍然可以

我最近一直在尝试编写MSIL并使用ilasm编译它,当时我注意到方法确实需要ret指令才能从方法末尾返回; 例如,我应该编写如下代码:

.method static void Main()
{
    .entrypoint
    ldstr "Hello World!"
    call void [mscorlib]System.Console::WriteLine(string)
    ret //I am returning properly
}
但是,如果省略ret,代码仍然可以完美地运行并输出“Hello World!”。起初我认为这可能是entrypoint方法特有的,但ilasm很高兴地编译了这段代码,既没有警告也没有错误:

.assembly Program{}
.assembly extern mscorlib{}
.method static void Main()
{
.entrypoint
ldstr   "Hello World!"
call    void    [mscorlib]System.Console::WriteLine(string)
ldstr   "Foo returned: {0}!"
call    int32   Foo()
box     int32
call    void    [mscorlib]System.Console::WriteLine(string, object)
}
.method static int32 Foo()
{
ldstr   "Hello from Foo!"
call    void    [mscorlib]System.Console::WriteLine(string)
ldstr   "GoodBye!"
call    void    [mscorlib]System.Console::WriteLine(string)
ldc.i4  42
}
请注意,Main()和Foo()都没有返回语句。Foo()甚至还有一个返回值! 当编译并运行此代码时,我得到以下输出:

你好,世界! 你好,来自福! 再见! 福:42

程序也会正常终止。然后我认为ilasm可能是自动插入ret语句,但在使用ildasm查看程序后,方法与上面的代码相同,即没有返回

奇怪的是,当我试图用DotPeek反编译该方法时,它断然拒绝用
//问题:无法反编译该方法。

如果我添加ret语句并重新编译,DotPeek可以对这两种方法进行反编译而不会出现问题


有人能解释一下这里发生了什么吗?

我认为这是因为CLR有时会接受无效的IL,并且只有当它遇到实际上无法执行的IL时,才会抛出
invalidProgrameException
。我的猜测是,这样做是出于性能原因:验证IL是否遵循所有规则会太慢

如果你想验证你的IL是有效的,你应该使用PEVerify


当您有无效代码时,一些工具(如DotPeek)无法处理它也就不足为奇了。

我想是的,只是我很惊讶ilasm如此乐于接受从未(显式)返回甚至没有警告的代码。此外,在编译代码后验证代码似乎很不直观,但PEVerify确实发现了错误。@illdans4但这不仅与ilasm有关,还与CLR有关,CLR也接受并执行此代码。