为什么在IL代码中sTloc.0之后有一个ldloc.0



我正在尝试通过编写小型代码段并检查编译的组件来学习CIL。所以我写了这个简单的语句:

    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指令放在它?

只有在调试模式下,您才能将这些指令视为编译器不会优化代码,以便您可以调试并将断点放在特定的部分中。

如果您以发布模式编译此应用程序,您会发现即使在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

相关内容

最新更新