2015-12-07 3 views
3

Lorsque vous utilisez ILDASM.exe sur un programme C# compilé, cela indique qu'il existe une étiquette pour chaque instruction dans les méthodes.Pourquoi C# -> CIL a-t-il une étiquette sur chaque instruction?

Par exemple:

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 

Pourquoi? N'est-il pas inefficace de le faire ou le compilateur CIL optimise-t-il ces étiquettes?

+3

Qu'est-ce qui vous fait penser que c'est une étiquette, plutôt que la façon dont il affiche la IL? –

+0

donc c'est comme la ligne "IL_0001"? @JonSkeet –

+1

@EhsanSajjad: Sorte de. Je crois qu'ils agissent comme des étiquettes que vous * pouvez * utiliser dans IL, mais je ne crois pas qu'ils sont dans le code généré. –

Répondre

9

Les étiquettes ne sont pas présentes dans le fichier CIL compilé. Ils sont affichés pour votre commodité dans le code démonté.

Ces étiquettes particulières correspondent à des décalages d'instructions, alors qu'il n'y a pas de restriction sur le code fait à la main (les étiquettes peuvent être des chaînes arbitraires).

+2

Il est probablement plus facile de s'assurer que chaque instruction reçoit une étiquette que de suivre les étiquettes qui doivent être émises et de ne les émettre que. –

5

En IL compilé, il n'y a pas de libellé. Au lieu de cela, les instructions de saut utilisent des décalages relatifs à partir du début de l'instruction suivante.

Par exemple, considérons cette fonction trivial C#:

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

Dans IL, vous pourriez écrire comme ceci:

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

Si vous compilez que l'utilisation ilasm puis décompiler arrière à l'aide ildasm , avec "Afficher les octets" activé, vous obtenez:

.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 

Notez que les étiquettes ne sont pas dans n'importe quel moyen représenté dans les octets (montré dans les commentaires). Et que brtrue.s label de l'IL d'origine est ici représenté brtrue.s IL_0005, où les octets sont 2D 02. 2D est la forme compilée de brtrue.s et 02 est un décalage relatif. Puisque l'instruction suivante commence au décalage absolu 3, la cible est au décalage absolu 3 + 2 = 5.