Methods 不需要ret的MSIL方法
我最近一直在尝试编写MSIL并使用ilasm编译它,当时我注意到方法确实需要ret指令才能从方法末尾返回; 例如,我应该编写如下代码: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,代码仍然可以
.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也接受并执行此代码。