未优化的 MSIL 中多余的 NOP 和分支
Superfluous NOPs and branches in unoptimized MSIL
当我将以下代码编译为调试时...
public class MyClass
{
private int myField;
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
}
...编译器生成了带有看似无用指令的奇怪字节码。例如,查看为 属性 MyProperty
的 getter 生成的内容(使用 ildasm.exe
反汇编):
.method public hidebysig specialname instance int32
get_MyProperty() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS[=11=]00)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 MSILTest.MyClass::myField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method MyClass::get_MyProperty
具体来说,IL_0000
的 nop
在那里做什么?为什么编译器会在 IL_0008
处突然生成这个无用的 br.s
指令?为什么它会创建临时局部变量 CS[=19=]00
?
对于发布配置,指令集按预期生成:
IL_0000: ldarg.0
IL_0001: ldfld int32 MSILTest.MyClass::myField
IL_0006: ret
编辑
我想我已经找到了为什么分支和临时局部变量在 different question 中的问题的答案:这可能是为了在调试过程中轻松设置断点。所以剩下的问题是为什么会生成nop
指令。
编译器创建这些操作码是为了提供更好的调试体验。在每一行的开头,编译器都会引入一个
nop
所以调试器可以在那里中断。发出分支和临时局部变量,让您分析函数 return 值。
当我将以下代码编译为调试时...
public class MyClass
{
private int myField;
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
}
...编译器生成了带有看似无用指令的奇怪字节码。例如,查看为 属性 MyProperty
的 getter 生成的内容(使用 ildasm.exe
反汇编):
.method public hidebysig specialname instance int32
get_MyProperty() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] int32 CS[=11=]00)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 MSILTest.MyClass::myField
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method MyClass::get_MyProperty
具体来说,IL_0000
的 nop
在那里做什么?为什么编译器会在 IL_0008
处突然生成这个无用的 br.s
指令?为什么它会创建临时局部变量 CS[=19=]00
?
对于发布配置,指令集按预期生成:
IL_0000: ldarg.0
IL_0001: ldfld int32 MSILTest.MyClass::myField
IL_0006: ret
编辑
我想我已经找到了为什么分支和临时局部变量在 different question 中的问题的答案:这可能是为了在调试过程中轻松设置断点。所以剩下的问题是为什么会生成nop
指令。
编译器创建这些操作码是为了提供更好的调试体验。在每一行的开头,编译器都会引入一个
nop
所以调试器可以在那里中断。发出分支和临时局部变量,让您分析函数 return 值。