Nic*_*ick 6 methods il cil return ilasm
我最近一直在编写MSIL并用ilasm编译它,当时我注意到方法确实需要一个ret指令从方法结束返回; 例如,我应该写这样的代码:
.method static void Main()
{
.entrypoint
ldstr "Hello World!"
call void [mscorlib]System.Console::WriteLine(string)
ret //I am returning properly
}
Run Code Online (Sandbox Code Playgroud)
但是,如果省略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
}
Run Code Online (Sandbox Code Playgroud)
请注意,Main()和Foo()都没有return语句.Foo()甚至有一个返回值!编译并运行此代码时,我得到以下输出:
你好,世界!来自Foo的你好!再见!Foo回归:42!
该程序也正常终止.然后我想也许ilasm是自动插入ret语句,但是在用ildasm查看程序之后,这些方法与上面的代码相同,即没有返回.
奇怪的是,当我试图用DotPeek反编译该方法时,它拒绝用两个方法体替换 // ISSUE: unable to decompile the method.
如果我添加ret语句并重新编译DotPeek可以反复编译这两种方法而不会出现问题.
有人可以解释一下这里发生了什么吗?
我认为这是因为CLR有时会接受无效的IL,并且只有当它遇到它实际上无法执行的IL时才会抛出InvalidProgramException.我的猜测是出于性能原因这样做:验证IL遵循所有规则会太慢.
如果要验证IL是否有效,则应在其上使用PEVerify.
当你的代码无效时,像DotPeek这样的工具无法处理它也就不足为奇了.
| 归档时间: |
|
| 查看次数: |
951 次 |
| 最近记录: |