Why does C# -> CIL have a label on every instruction?

雨燕双飞 提交于 2019-12-31 02:44:10

问题


When using ILDASM.exe on a compiled C# program, it shows that there is a label for every instruction within methods.

For example:

IL_0001:  ldc.i4.4
IL_0002:  stloc.0
IL_0003:  ldc.r8     12.34
IL_000c:  stloc.1
IL_000d:  ldc.r8     3.1415926535897931
IL_0016:  stloc.2
IL_0017:  ldstr      "Ehsan"
IL_001c:  stloc.3
IL_001d:  ret

Why is this? Is it not inefficient to do this or does the CIL compiler optimize these labels itself?


回答1:


Labels are not present in the compiled CIL. They are displayed for your convenience in the dissassembled code.

These particular labels correspond to instruction offsets, while there is no such restriction on hand-made code (labels could be arbitrary strings).




回答2:


In compiled IL, there are no labels. Instead, jump instructions use relative offsets from the start of the following instruction.

For example, consider this trivial C# function:

public static bool IsZero(int n)
{
    if (n == 0)
        return true;
    return false;
}

In IL, you might write it like this:

.method public hidebysig static bool IsZero(int32 n) cil managed
{
    ldarg.0     
    brtrue.s label
    ldc.i4.1    
    ret         
label:
    ldc.i4.0    
    ret   
}

If you compile that using ilasm and then decompile it back using ildasm, with "Show bytes" enabled, you get:

.method public hidebysig static bool  IsZero(int32 n) cil managed
// SIG: 00 01 02 08
{
  // Method begins at RVA 0x2052
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  /* 02   |                  */ ldarg.0
  IL_0001:  /* 2D   | 02               */ brtrue.s   IL_0005
  IL_0003:  /* 17   |                  */ ldc.i4.1
  IL_0004:  /* 2A   |                  */ ret
  IL_0005:  /* 16   |                  */ ldc.i4.0
  IL_0006:  /* 2A   |                  */ ret
} // end of method Program::IsZero

Notice how the labels are not in any way represented in the bytes (shown in comments). And that brtrue.s label from the original IL is here shown as brtrue.s IL_0005, where the bytes are 2D 02. 2D is the compiled form of brtrue.s, and 02 is a relative offset. Since the following instruction starts at absolute offset 3, the target is at absolute offset 3 + 2 = 5.



来源:https://stackoverflow.com/questions/34131396/why-does-c-sharp-cil-have-a-label-on-every-instruction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!