Dot-Net
在 IL 程式碼中,為什麼在給定情況下沒有 nop 操作碼?為什麼在給定情況下會有 br.s 操作碼?
假設我有以下程式碼:
public class Class1 { private Class2 obj; public void MethodA() { var class2 = new Class2(); class2.PropertyI = 2; obj = MethodB(class2); } public Class2 MethodB(Class2 class2) { return class2; } } public class Class2 { public int PropertyI { get; set; } }使用 Visual Studio 2010 編譯為 .NET 2.0 程序集生成的 IL 程式碼如下:
.method public hidebysig instance void MethodA() cil managed { .maxstack 3 .locals init ( [0] class ClassLibrary1.Class2 class2) L_0000: nop L_0001: newobj instance void ClassLibrary1.Class2::.ctor() L_0006: stloc.0 L_0007: ldloc.0 L_0008: ldc.i4.2 L_0009: callvirt instance void ClassLibrary1.Class2::set_PropertyI(int32) L_000e: nop L_000f: ldarg.0 L_0010: ldarg.0 L_0011: ldloc.0 L_0012: call instance class ClassLibrary1.Class2 ClassLibrary1.Class1::MethodB(class ClassLibrary1.Class2) L_0017: stfld class ClassLibrary1.Class2 ClassLibrary1.Class1::obj L_001c: ret } .method public hidebysig instance class ClassLibrary1.Class2 MethodB(class ClassLibrary1.Class2 class2) cil managed { .maxstack 1 .locals init ( [0] class ClassLibrary1.Class2 CS$1$0000) L_0000: nop L_0001: ldarg.1 L_0002: stloc.0 L_0003: br.s L_0005 L_0005: ldloc.0 L_0006: ret }我的問題如下:
- 在 MethodA 中,為什麼和之間沒有
nop程式碼?L_0006``L_0007
- 既然
L_0001to與toL_0006不同,為什麼沒有操作碼?L_0007``L_0009``nop
- 在 MethodB 中,為什麼
L_0003需要?
C# 編譯器在大括號處發出 NOP 指令。這使得在程式碼中設置斷點變得容易得多。調試器只允許在程式碼上設置斷點,大括號通常不會產生任何程式碼。所以這只是一個簡單的調試幫助,這些 NOP 不會在發布版本中生成。
BR.S 指令是編譯器中的一個小缺陷,它沒有一個窺孔優化器來擺脫這些無關的指令。通常,優化程式碼不是 C# 編譯器的工作,而是由jitter 完成的。這將輕鬆輕鬆地刪除指令。