在IL中循环 - 为什么stloc.0和ldloc.0?

Mic*_*tum 8 .net cil

我试图了解IL循环中的while循环.我写了这个C#函数:

    static void Brackets()
    {
        while (memory[pointer] > 0)
        {
            // Snipped body of the while loop, as it's not important
        }
    } 
Run Code Online (Sandbox Code Playgroud)

IL看起来像这样:

.method private hidebysig static void  Brackets() cil managed
{
  // Code size       37 (0x25)
  .maxstack  2
  .locals init ([0] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  br.s       IL_0012
  IL_0003:  nop
  // Snipped body of the while loop, as it's not important
  IL_0011:  nop
  IL_0012:  ldsfld     uint8[] BFHelloWorldCSharp.Program::memory
  IL_0017:  ldsfld     int16 BFHelloWorldCSharp.Program::pointer
  IL_001c:  ldelem.u1
  IL_001d:  ldc.i4.0
  IL_001e:  cgt
  IL_0020:  stloc.0
  IL_0021:  ldloc.0
  IL_0022:  brtrue.s   IL_0003
  IL_0024:  ret
} // end of method Program::Brackets
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这非常简单,除了cgt之后的部分.

我不明白的是local [0]和stloc.0/ldloc.0.据我所知,cgt将结果推送到堆栈,stloc.0将堆栈中的结果传递给局部变量,ldloc.0再次将结果推送到堆栈,brtrue.s从堆栈读取.

这样做的目的是什么?难道这不能缩短到cgt后跟brtrue.s吗?

Ben*_*igt 6

尝试使用优化进行编译.


Mar*_*ell 5

这是一个调试版本(来自nop)。一切皆有可能,但为了简单起见,它看起来只是引入了一个 bool 变量:

    goto testforexit;
body:
    ..
testforexit:
    bool tmp = memory[pointer] > 0;
    if(tmp) goto body;
Run Code Online (Sandbox Code Playgroud)

在启用优化的情况下构建版本,这应该会删除此类变量。