我试图通过编写小代码段并检查已编译的程序集来学习CIL。所以我写了这个简单的if语句:
public static void Main (string[] args)
{
Int32 i = Int32.Parse (Console.ReadLine());
if (i > 0)
Console.WriteLine ("i is greater than 0");
}
C#编译器将其编译为以下IL代码:
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 num,
[1] bool flag)
L_0000: nop
L_0001: call string [mscorlib]System.Console::ReadLine()
L_0006: call int32 [mscorlib]System.Int32::Parse(string)
L_000b: stloc.0
L_000c: ldloc.0
L_000d: ldc.i4.0
L_000e: cgt
L_0010: ldc.i4.0
L_0011: ceq
L_0013: stloc.1
L_0014: ldloc.1
L_0015: brtrue.s L_0022
L_0017: ldstr "i is greater than 0"
L_001c: call void [mscorlib]System.Console::WriteLine(string)
L_0021: nop
L_0022: ret
}
据我所知,stloc
将评估堆栈中的最高值放入局部变量中,如果我说得对,那么该值不会从堆栈中弹出,那么为什么编译器会将紧随其后的ldloc
指令?
答案 0 :(得分:8)
只有在调试模式下才能看到这些指令,因为编译器不会优化代码,因此您可以调试并在特定部分中放置断点。
如果您在发布模式下编译此应用程序,您会看到即使在IL代码上也进行了优化。
.method public hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// [13 13 - 13 55]
IL_0000: call string [mscorlib]System.Console::ReadLine()
IL_0005: call int32 [mscorlib]System.Int32::Parse(string)
// [14 13 - 14 23]
IL_000a: ldc.i4.0
IL_000b: ble.s IL_0017
// [15 17 - 15 58]
IL_000d: ldstr "i is greater than 0"
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
// [16 9 - 16 10]
IL_0017: ret
} // end of method Program::Main