Пока петля в IL-почему stloc.0 и ldloc.0?
Я пытаюсь понять, как цикл while выглядит в IL. Я написал эту функцию C#:
static void Brackets()
{
while (memory[pointer] > 0)
{
// Snipped body of the while loop, as it's not important
}
}
IL выглядит так:
.method private hidebysig static void Brackets() cil managed
{
// Code size 37 (0x25)
.maxstack 2
.locals init ([0] bool CS00)
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
по большей части это действительно просто, за исключением части после cgt.
чего я не понимаю, это локальный [0] и stloc.0/ldloc.0. Насколько я вижу, cgt толкает результат в стек, stloc.0 получает результат из стека в локальную переменную, ldloc.0 снова помещает результат в стек и brtrue.s читает из стека.
какова цель этого? Не может ли это быть сокращено до просто cgt, а затем brtrue.s?
2 ответов
это отладочная сборка (с nop
). Все ставки отключены, но похоже, что это просто введение переменной bool для простоты:
goto testforexit;
body:
..
testforexit:
bool tmp = memory[pointer] > 0;
if(tmp) goto body;
сборка в выпуске с включенной оптимизацией, которая должна удалить такие переменные.