我最近一直在尝试编写 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!” 完美。起初我认为这可能特定于入口点方法,但 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() 甚至有返回值!编译并运行此代码后,我得到以下输出:
你好世界!来自Foo的你好!再见!Foo 返回:42!
该程序也正常终止。然后我认为也许 ilasm 是自动插入 ret 语句,但是在使用 ildasm 查看程序之后,方法与上面的代码相同,即没有返回。
奇怪的是,当我试图用 DotPeek 反编译该方法时,它完全拒绝用// ISSUE: unable to decompile the method.
如果我添加 ret 语句并重新编译 DotPeek 可以毫无问题地反编译这两种方法。
有人可以解释一下这里发生了什么吗?