私は最近、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() にも return ステートメントがないことに注意してください。Foo() には戻り値もあります! このコードをコンパイルして実行すると、次の出力が得られます。
「こんにちは世界」フーからこんにちは!さよなら!Foo が返されました: 42!
プログラムも正常終了します。その後、おそらく ilasm が ret ステートメントを自動挿入しているのではないかと考えましたが、ildasm を使用してプログラムを調べたところ、メソッドは上記のコードと同じでした。つまり、リターンがありませんでした。
不思議なことに、DotPeek でメソッドを逆コンパイルしようとすると、両方のメソッド本体を// ISSUE: unable to decompile the method.
ret ステートメントを追加して再コンパイルすると、DotPeek は両方のメソッドを問題なく逆コンパイルできます。
誰かがここで何が起こっているのか説明してもらえますか?