Les premiers pas
Le Common Intermediate Language (CIL) est le langage de bas niveau utilisé par la plateforme .NET de Microsoft. Les programmes écrits dans des langages de programmation tels que C# sont compilés en CIL, étant ensuite converti en code machine natif par le Common Language Runtime (CLR) lors de l'exécution. Bien que la majorité des développeurs n'écrivent pas directement en CIL, comprendre sa structure peut être bénéfique pour une meilleure appréhension du fonctionnement interne de .NET.
Structure d'un programme CIL
Un programme CIL est généralement organisé de la manière suivante :
- Déclaration des assemblies : Spécification des dépendances externes et définition de l'assembly principal.
- Définition des classes : Implémentation des types et structures de données.
- Implémentation des méthodes : Codage de la logique fonctionnelle.
Écriture d'un programme simple en CIL
Voici un exemple de programme CIL affichant "Bonjour, monde !" :
- .assembly extern mscorlib {}
- .assembly HelloWorld {}
-
- .class public HelloWorldApp
- {
- .method public static void Main() cil managed
- {
- .entrypoint
- .maxstack 1
- ldstr "Bonjour, monde !"
- call void [mscorlib]System.Console::WriteLine(string)
- ret
- }
- }
Voici à quoi correspond les éléments clefs du code d'un programme CIL :
| Élément | Description |
|---|---|
| .assembly extern mscorlib {} | Déclaration d'une dépendance à l'assembly mscorlib, contenant les classes de base du .NET Framework.? |
| .assembly HelloWorld {} | Définit l'assembly principal du programme.? |
| .class public HelloWorldApp | Déclare une classe publique nommée HelloWorldApp.? |
| .method public static void Main() cil managed | Définit la méthode statique Main, point d'entrée du programme.? |
| .entrypoint | Indique que cette méthode est le point d'entrée du programme.? |
| .maxstack 1 | Spécifie que la pile maximale utilisée est de 1 élément.? |
| ldstr "Bonjour, monde !" | Charge la chaîne de caractères "Bonjour, monde !" sur la pile.? |
| call void [mscorlib]System.Console::WriteLine(string) | Appelle la méthode WriteLine de la classe Console pour afficher la chaîne de caractères.? |
| ret | Retourne de la méthode Main, terminant ainsi le programme. |
Compilation et exécution du code CIL
Écriture du code : Rédigez le code CIL dans un éditeur de texte et enregistrez-le avec l'extension .il.
Compilation : Utilisez l'outil ilasm (IL Assembler) pour compiler le code CIL en un fichier exécutable :
| ilasm MonProgramme.il |
Exécution : Une fois compilé, exécutez le programme avec le CLR :
| MonProgramme.exe |
Instructions de base
Les instructions de base du Common Intermediate Language (CIL) sont des commandes fondamentales utilisées pour manipuler des données, contrôler le flux d'exécution, effectuer des calculs, et interagir avec la pile d'exécution. Ces instructions sont cruciales pour comprendre le fonctionnement interne des programmes .NET, car elles agissent directement sur les opérations bas-niveau du programme. Voici un tableau des instructions de base :
| Instruction | Description |
|---|---|
| ldstr | Charger une chaîne de caractères. |
| call | Appeler une méthode. |
| ret | Retourner d'une méthode. |
| add | Additionner deux valeurs. |
| sub | Soustraire deux valeurs. |
| mul | Multiplier deux valeurs. |
| div | Diviser deux valeurs. |
| neg | Négative une valeur. |
| and | Opération logique ET. |
| or | Opération logique OU. |
| xor | Opération logique XOR. |
| not | Complément à un. |
| shl | Décalage logique à gauche. |
| shr | Décalage logique à droite. |
| beq | Branche si égal. |
| bne.un | Branche si différent ou non ordonné. |
| blt | Branche si inférieur. |
| bgt | Branche si supérieur. |
| ble | Branche si inférieur ou égal. |
| bge | Branche si supérieur ou égal. |
| br | Branche inconditionnelle. |
| brfalse | Branche si faux (zéro). |
| brtrue | Branche si vrai (non zéro). |
| switch | Instruction de saut multiple. |
| throw | Lancer une exception. |
| catch | Bloc de gestion d'exception. |
| finally | Bloc d'exécution finale. |
ldstr (Load String)
L'instruction ldstr permet de charger une chaîne de caractères sur la pile. C'est une des instructions les plus couramment utilisées pour manipuler des chaînes de texte dans les programmes CIL.
Syntaxe :
| ldstr "texte" |
Exemple :
- ldstr "Bonjour le monde !"
Cet exemple charge la chaîne "Bonjour le monde !" sur la pile. Cette chaîne peut ensuite être utilisée par d'autres instructions, comme call pour l'afficher à l'écran avec System.Console.WriteLine.
add (Addition)
L'instruction add effectue l'addition de deux valeurs qui se trouvent au sommet de la pile. Elle prend ces deux valeurs, les additionne, et place le résultat de l'opération au sommet de la pile.
Syntaxe :
| add |
Exemple :
- ldc.i4 5
- ldc.i4 3
- add
Dans cet exemple, ldc.i4 5 charge la valeur 5 et ldc.i4 3 charge la valeur 3 sur la pile. L'instruction add additionne ces deux valeurs, et le résultat, 8, reste sur la pile.
sub (Subtraction)
L'instruction sub effectue la soustraction de deux valeurs, en retirant la deuxième valeur du sommet de la pile de la première valeur.
Syntaxe :
| sub |
Exemple :
- ldc.i4 10
- ldc.i4 4
- sub
Ici, ldc.i4 10 charge 10 et ldc.i4 4 charge 4 sur la pile. L'instruction sub effectue la soustraction 10 - 4, et place le résultat 6 sur la pile.
mul (Multiplication)
L'instruction mul multiplie les deux valeurs présentes au sommet de la pile. Elle remplace ces deux valeurs par leur produit.
Syntaxe :
| mul |
Exemple :
- ldc.i4 6
- ldc.i4 7
- mul
Dans cet exemple, ldc.i4 6 et ldc.i4 7 placent respectivement les valeurs 6 et 7 sur la pile. L'instruction mul calcule leur produit, 42, et place le résultat sur la pile.
div (Division)
L'instruction div effectue une division entière. Elle prend les deux valeurs au sommet de la pile, effectue la division de la première valeur par la deuxième, et place le quotient résultant sur la pile.
Syntaxe :
| div |
Exemple :
- ldc.i4 20
- ldc.i4 4
- div
Dans cet exemple, l'instruction div divise 20 par 4 et place le quotient, étant 5, sur la pile.
neg (Negate)
L'instruction neg inverse le signe de la valeur au sommet de la pile. Elle est utile pour effectuer des opérations de négation.
Syntaxe :
| neg |
Exemple :
- ldc.i4 15
- neg
Dans cet exemple, ldc.i4 15 charge la valeur 15 sur la pile, puis l'instruction neg inverse son signe, plaçant -15 sur la pile.
and (Logical AND)
L'instruction and effectue une opération logique "ET" entre les deux valeurs booléennes au sommet de la pile.
Syntaxe :
| and |
Exemple :
- ldc.i4 1 ; True (1)
- ldc.i4 0 ; False (0)
- and ; Résultat: 0 (False)
Ici, ldc.i4 1 et ldc.i4 0 placent respectivement les valeurs 1 (True) et 0 (False) sur la pile. L'instruction and effectue une opération "ET" logique, ce qui donne 0 (False), et ce résultat reste sur la pile.
or (Logical OR)
L'instruction or effectue une opération logique "OU" entre les deux valeurs booléennes au sommet de la pile.
Syntaxe :
| or |
Exemple :
- ldc.i4 1 ; True (1)
- ldc.i4 0 ; False (0)
- or ; Résultat: 1 (True)
Dans cet exemple, l'instruction or effectue une opération "OU" logique sur 1 et 0, et le résultat, 1 (True), reste sur la pile.
beq (Branch if Equal)
L'instruction beq effectue un saut conditionnel à l'adresse spécifiée si les deux valeurs au sommet de la pile sont égales. Si les valeurs sont égales, l'exécution saute à l'étiquette cible.
Syntaxe :
| beq target |
Exemple :
- ldc.i4 5
- ldc.i4 5
- beq Label
Dans cet exemple, si les deux valeurs au sommet de la pile sont égales (ce qui est le cas ici, car 5 == 5), l'exécution sautera à l'étiquette Label.
Instruction de manipulation de la pile
Les instructions de manipulation de la pile dans le Common Intermediate Language (CIL) sont fondamentales pour comprendre comment les programmes .NET gèrent les données à bas niveau. CIL est une machine à pile, ce qui signifie que presque toutes les opérations s'effectuent en poussant ou en retirant des valeurs de la pile. Ces instructions permettent d'insérer, de dupliquer, de supprimer ou de déplacer des valeurs sur cette pile, et sont utilisées dans quasiment toutes les séquences d'instructions.
Voici un tableau des instructions de manipulation de la pile :
| Instruction | Description |
|---|---|
| ldc.i4 | Empile une constante entière 32 bits signée sur la pile. |
| ldc.i4.0 à ldc.i4.8 | Versions optimisées de ldc.i4 pour les valeurs de 0 à 8. |
| ldc.i4.m1 | Empile la constante -1 sur la pile. |
| ldc.i8 | Empile une constante entière 64 bits sur la pile. |
| ldc.r4 | Empile une constante en virgule flottante 32 bits. |
| ldc.r8 | Empile une constante en virgule flottante 64 bits. |
| ldloc | Charge une variable locale (indexée) sur la pile. |
| ldloc.0 à ldloc.3 | Versions abrégées pour les 4 premières variables locales. |
| ldloc.s | Charge une variable locale à partir d'un index court (1 octet). |
| stloc | Entrepose la valeur du sommet de la pile dans une variable locale. |
| stloc.0 à stloc.3 | Versions abrégées pour les 4 premières variables locales. |
| stloc.s | Version optimisée de stloc avec index court. |
| ldarg | Charge un argument de méthode sur la pile. |
| ldarg.0 à ldarg.3 | Versions abrégées pour les 4 premiers arguments. |
| ldarg.s | Charge un argument court (index < 256). |
| starg | Entrepose une valeur dans un argument de méthode. |
| starg.s | Version courte de starg. |
| pop | Supprime la valeur au sommet de la pile. |
| dup | Duplique la valeur au sommet de la pile. |
| initobj | Initialise une valeur sur la pile à sa valeur par défaut. |
| cpobj | Copie une valeur d'un emplacement mémoire vers un autre. |
| ldind.<type> | Charge indirectement une valeur d'un certain type à partir d'un pointeur. |
| stind.<type> | Entrepose indirectement une valeur à une adresse mémoire pointée. |
| ldnull | Place la valeur null sur la pile. |
| ldstr | Empile une constante chaîne de caractères. |
| ldtoken | Empile un handle d'un type, méthode ou champ. |
| box | Convertit une valeur en objet (boxing) et l'empile. |
| unbox / unbox.any | Convertit une référence typée en valeur (unboxing). |
Voici une présentation détaillée des principales instructions de manipulation de la pile, accompagnée de leur syntaxe et d'exemples :
ldc.i4 (Load Constant Int32)
L'instruction ldc.i4 sert à empiler une constante entière 32 bits sur la pile. Elle existe sous plusieurs formes optimisées pour les petites valeurs entières (ldc.i4.0, ldc.i4.1, ..., ldc.i4.8, ldc.i4.m1).
Syntaxe :
| ldc.i4 valeur |
Exemple :
- ldc.i4 10
- ldc.i4 5
- add
Ce code empile 10 puis 5, puis les additionne. Le résultat (15) reste sur la pile.
ldloc, stloc (Load/Store Local Variable)
L'instruction ldloc charge la valeur d'une variable locale sur la pile, tandis que stloc entrepose la valeur au sommet de la pile dans une variable locale.
Syntaxe :
| ldloc index |
| stloc index |
Exemple :
- .locals init ([0] int32 x)
- ldc.i4 42
- stloc.0 // entrepose 42 dans x
- ldloc.0 // charge x sur la pile
Ce code définit une variable locale x, y stocke la valeur 42 et la recharge sur la pile.
dup (Duplicate)
L'instruction dup duplique la valeur au sommet de la pile. C'est utile pour utiliser plusieurs fois la même valeur sans avoir à la recharger.
Syntaxe :
| dup |
Exemple :
- ldc.i4 3
- dup
- add // additionne 3 + 3, résultat 6
La pile contenait une seule fois 3, dup l'a dupliquée, ce qui a permis à add de produire 6.
pop (Pop Top of Stack)
L'instruction pop supprime la valeur au sommet de la pile sans la traiter. Cela permet de nettoyer la pile si une valeur ne doit pas être utilisée.
Syntaxe :
| pop |
Exemple :
- ldc.i4 100
- pop // supprime 100 de la pile
La valeur 100 est empilée puis immédiatement supprimée.
swap (Non standard, mais souvent mentionnée)
Il est à noter que CIL ne possède pas d'instruction swap standard pour échanger les deux premières valeurs de la pile, contrairement à certains autres langages à pile comme Forth. Il faut alors recourir à des variables temporaires ou à l'utilisation combinée de stloc/ldloc.
call et gestion implicite de la pile
Lorsque vous utilisez des appels de méthodes avec call, les paramètres doivent être placés dans l'ordre inverse sur la pile, car le dernier paramètre se retrouve au sommet. La méthode dépile ces valeurs à l'exécution.
Exemple :
- ldstr "Bonjour"
- call void [mscorlib]System.Console::WriteLine(string)
Ce code empile la chaîne "Bonjour" puis appelle Console.WriteLine, qui dépile et utilise cette valeur.
ret (Return)
L'instruction ret termine une méthode. Si la méthode retourne une valeur, celle-ci doit être au sommet de la pile au moment de l'exécution de ret.
Syntaxe :
| ret |
Exemple :
- ldc.i4 7
- ret // retourne 7 à l'appelant
Instructions arithmétiques
Elles effectuent des opérations mathématiques sur les entiers, flottants,...
| Instruction | Description |
|---|---|
| add | Additionne les deux valeurs au sommet de la pile. |
| sub | Soustrait la deuxième valeur de la première (val2 - val1). |
| mul | Multiplie les deux valeurs au sommet de la pile. |
| div | Divise la deuxième valeur par la première (division signée). |
| div.un | Division non signée de la deuxième valeur par la première. |
| rem | Calcule le reste (modulo) de la division signée. |
| rem.un | Calcule le reste (modulo) de la division non signée. |
| neg | Négation (inverse le signe) de la valeur au sommet de la pile. |
Instructions de conversion de types numériques
| Instruction | Description |
|---|---|
| conv.i1 | Convertit en entier signé 8 bits (int8). |
| conv.i2 | Convertit en entier signé 16 bits (int16). |
| conv.i4 | Convertit en entier signé 32 bits (int32). |
| conv.i8 | Convertit en entier signé 64 bits (int64). |
| conv.u1 | Convertit en entier non signé 8 bits (uint8). |
| conv.u2 | Convertit en entier non signé 16 bits (uint16). |
| conv.u4 | Convertit en entier non signé 32 bits (uint32). |
| conv.u8 | Convertit en entier non signé 64 bits (uint64). |
| conv.r4 | Convertit en nombre flottant simple précision (float32). |
| conv.r8 | Convertit en nombre flottant double précision (float64). |
| conv.ovf.i4 | Convertit avec vérification de débordement vers int32. |
| conv.ovf.u4 | Convertit avec débordement vers uint32. |
| conv.ovf.i4.un | Idem, mais pour une valeur non signée. |
Instructions logiques et bit à bit
Elles gèrent les opérations booléennes et binaires.
| Instruction | Description |
|---|---|
| and | Effectue une opération logique ET bit à bit entre deux valeurs du sommet de la pile. |
| or | Effectue une opération logique OU bit à bit entre deux valeurs du sommet de la pile. |
| xor | Effectue une opération logique OU exclusif (XOR) bit à bit entre deux valeurs. |
| shl | Décale la valeur binaire vers la gauche (multiplication par 2?). |
| shr | Décale la valeur binaire vers la droite avec propagation du bit de signe (décalage arithmétique). |
| shr.un | Décale vers la droite sans propagation du bit de signe (décalage logique, pour valeurs non signées). |
Instructions de comparaison et branchement
Elles effectuent des comparaisons conditionnelles et des sauts.
| Instruction | Description |
|---|---|
| beq | Branche si les deux valeurs au sommet de la pile sont égales (égalité). |
| bne.un | Branche si les deux valeurs au sommet de la pile sont différentes (inégalité). Utilisé pour des comparaisons non signées. |
| bgt | Branche si la première valeur est supérieure à la deuxième (valeur1 > valeur2). |
| bgt.un | Branche si la première valeur est supérieure à la deuxième (pour les entiers non signés). |
| blt | Branche si la première valeur est inférieure à la deuxième (valeur1 < valeur2). |
| blt.un | Branche si la première valeur est inférieure à la deuxième (pour les entiers non signés). |
| bge | Branche si la première valeur est supérieure ou égale à la deuxième (valeur1 >= valeur2). |
| bge.un | Branche si la première valeur est supérieure ou égale à la deuxième (pour les entiers non signés). |
| ble | Branche si la première valeur est inférieure ou égale à la deuxième (valeur1 <= valeur2). |
| ble.un | Branche si la première valeur est inférieure ou égale à la deuxième (pour les entiers non signés). |
| br | Effectue un saut inconditionnel (un branchement vers l'adresse spécifiée). |
| brtrue | Branche si la valeur au sommet de la pile est vraie (différente de 0). |
| brfalse | Branche si la valeur au sommet de la pile est fausse (égale à 0). |
| ceq | Compare les deux valeurs au sommet de la pile et place 1 si elles sont égales, 0 sinon. |
| cgt | Compare les deux valeurs au sommet de la pile et place 1 si la première est supérieure à la deuxième, 0 sinon. |
| cgt.un | Compare les deux valeurs au sommet de la pile en les traitant comme non signées. |
| clt | Compare les deux valeurs au sommet de la pile et place 1 si la première est inférieure à la deuxième, 0 sinon. |
| clt.un | Compare les deux valeurs au sommet de la pile en les traitant comme non signées. |
Instructions de contrôle de flux
Pour gérer les structures conditionnelles et les boucles.
| Instruction | Description |
|---|---|
| br | Saut inconditionnel vers l'étiquette ou l'adresse spécifiée. |
| br.s | Variante courte de br avec une cible proche (meilleure optimisation). |
| brtrue | Saut vers une destination spécifié si la valeur au sommet de la pile est vraie (? 0). |
| brtrue.s | Version courte de brtrue. |
| brfalse | Saut vers une destination spécifié si la valeur au sommet de la pile est fausse (= 0). |
| brfalse.s | Version courte de brfalse. |
| beq | Saut si les deux valeurs sont égales. |
| beq.s | Version courte de beq. |
| bne.un | Saut si les deux valeurs sont différentes, comparaison non signée. |
| bne.un.s | Version courte de bne.un. |
| bgt | Saut si la première valeur est supérieure à la deuxième. |
| bgt.s | Version courte de bgt. |
| bgt.un | Saut si la première valeur est supérieure (non signé). |
| bgt.un.s | Version courte de bgt.un. |
| blt | Saut si la première valeur est inférieure à la deuxième. |
| blt.s | Version courte de blt. |
| blt.un | Saut si la première valeur est inférieure (non signé). |
| lt.un.s | Version courte de blt.un. |
| bge | Saut si la première valeur est supérieure ou égale à la deuxième. |
| bge.s | Version courte de bge. |
| bge.un | Saut si la première valeur est ? à la deuxième (non signé). |
| bge.un.s | Version courte de bge.un. |
| ble | Saut si la première valeur est inférieure ou égale à la deuxième. |
| ble.s | Version courte de ble. |
| ble.un | Saut si la première valeur est ? à la deuxième (non signé). |
| ble.un.s | Version courte de ble.un. |
| switch | Saut vers une étiquette selon la valeur au sommet de la pile (équivalent d'un switch/case). |
| leave | Quitte un bloc protégé (try) et transfère le contrôle à une autre instruction. |
| leave.s | Version courte de leave. |
| ret | Quitte la méthode en cours et retourne à l'appelant. |
| throw | Lève une exception. |
| rethrow | Relance l'exception actuellement capturée. |
| endfinally | Termine un bloc finally. Utilisé avec les structures try/finally. |
| endfault | Termine un bloc fault. Rare, utilisé pour la gestion d'exceptions non spécifiques. |
Instructions d'appel de méthode et de gestion du code
Elles permettent les appels de méthode et la gestion du contexte d'exécution.
| Instruction | Description |
|---|---|
| call | Appelle une méthode (appel direct, sans polymorphisme). Nécessite une spécification complète de la signature. |
| callvirt | Appelle une méthode virtuelle (résolution à l'exécution, support du polymorphisme). |
| calli | Appelle une méthode via un pointeur de fonction (appel indirect). Nécessite une signature de fonction. |
| jmp | Transfert d'exécution vers une autre méthode. Ne revient jamais à la méthode d'origine. |
| ret | Termine la méthode en cours et retourne à l'appelant. Optionnellement, retourne une valeur. |
| ldftn | Charge un pointeur vers une fonction (non virtuelle) sur la pile. |
| ldvirtftn | Charge un pointeur vers une méthode virtuelle, résolu dynamiquement selon le type de l'objet. |
| newobj | Crée une nouvelle instance d'un objet (appel au constructeur). |
| throw | Lève une exception. |
| rethrow | Relance l'exception en cours de traitement sans la modifier. |
| endfinally | Termine un bloc finally dans un bloc try/finally. |
| endfault | Termine un bloc fault (semblable à finally, utilisé pour les erreurs). |
| leave | Quitte un bloc try, catch ou finally et saute à l'instruction cible. |
| leave.s | Variante courte de leave pour les cibles proches. |
Instructions d'accès aux objets et aux champs
Permettent de manipuler les membres d'objet.
| Instruction | Description |
|---|---|
| ldfld | Charge la valeur d'un champ d'instance à partir d'un objet (non statique). |
| ldflda | Charge l'adresse d'un champ d'instance. |
| ldsfld | Charge la valeur d'un champ statique. |
| ldsflda | Charge l'adresse d'un champ statique. |
| stfld | Entrepose une valeur dans un champ d'instance. |
| stsfld | Entrepose une valeur dans un champ statique. |
| ldarg | Charge un paramètre de méthode sur la pile (par index). |
| ldarga | Charge l'adresse d'un paramètre. |
| starg | Entrepose une valeur dans un paramètre de méthode. |
| ldloc | Charge une variable locale sur la pile. |
| ldloca | Charge l'adresse d'une variable locale. |
| stloc | Entrepose une valeur dans une variable locale. |
| ldnull | Pousse la constante null sur la pile. |
| ldobj | Lit un objet à l'adresse spécifiée. Utilisé avec des types valeur. |
| stobj | Entrepose une valeur dans un objet à l'adresse spécifiée. |
| cpobj | Copie la valeur d'un objet vers un autre emplacement (copie champ par champ). |
| initobj | Initialise une instance d'un type valeur avec ses valeurs par défaut (zéro, null,...). |
| box | Convertit une valeur de type valeur en type référence (boxing). |
| unbox | Convertit un type référence en type valeur sans extraire la valeur (TypedRef). |
| unbox.any | Déboxe et extrait la valeur réelle d'un type référence. |
| isinst | Vérifie si un objet est d'un type donné. Résultat : référence valide ou null. |
| castclass | Effectue une conversion de type objet, lève une exception si échec. |
| sizeof | Renvoie la taille (en octets) d'un type valeur. |
| refanytype | Récupère le type d'un TypedRef. |
| refanyval | rRécupère la valeur d'un TypedRef. |
| mkrefany | Crée une instance de TypedRef. |
Instructions de gestion de types et d'objets
Elles permettent de tester, convertir ou gérer des objets.
| Instruction | Description |
|---|---|
| box | Convertit une valeur de type valeur (ex. int32) en type référence (object). Opération appelée boxing. |
| unbox | Convertit un objet en type valeur sans extraire la valeur (produit un pointeur vers la valeur). |
| unbox.any | Convertit un objet en type valeur et en extrait la valeur. |
| castclass | Tente de convertir un objet vers un type donné. Échoue avec une exception si la conversion est invalide. |
| isinst | Vérifie si un objet est d'un type donné. Retourne l'objet si la conversion est possible, sinon null. |
| newobj | Crée une nouvelle instance d'un objet en appelant son constructeur. |
| initobj | Initialise un type valeur à ses valeurs par défaut. |
| sizeof | Renvoie la taille en octets d'un type valeur. |
| mkrefany | Crée un TypedRef à partir d'un type et d'une adresse de valeur. |
| refanytype | Récupère le type contenu dans un TypedRef. |
| refanyval | Récupère la valeur pointée par un TypedRef. |
| ldtoken | Pousse sur la pile un token représentant un champ, un type, une méthode ou une string. Utilisé avec RuntimeHandle. |
| ldelem/stelem | Instructions génériques pour lire (ldelem) ou écrire (stelem) dans un tableau typé. |
| ldlen | Récupère la longueur d'un tableau (nombre d'éléments). |
| newarr | Alloue un nouveau tableau d'un type spécifique. |
| cpobj | Copie le contenu d'un objet vers un autre (par champ). |
| ldobj | Lit un objet à une adresse mémoire. |
| stobj | Écrit une valeur dans une adresse mémoire. |
Instructions spécifiques aux tableaux
Manipulent des tableaux .NET.
| Instruction | Description |
|---|---|
| newarr | Crée un nouveau tableau unidimensionnel d'un type donné. La taille est spécifiée sur la pile. |
| ldlen | Charge la longueur du tableau (nombre d'éléments) sur la pile. |
| ldelem | Charge l'élément d'un tableau typé à l'index spécifié. Nécessite le type exact (ex. ldelem.i4). |
| ldelema | Charge l'adresse d'un élément de tableau, permettant la modification directe via pointeur. |
| stelem | Entrepose une valeur dans un élément de tableau à l'index donné. Nécessite aussi le type (ex. stelem.i4). |
Instructions de gestion d'exception
Elles permettent la gestion des blocs try, catch, finally :
| Instruction | Description |
|---|---|
| throw | Lève une exception (objet de type dérivé de System.Exception) déjà présente sur la pile. |
| rethrow | Relance l'exception en cours dans un bloc catch, sans modifier la pile d'appel. |
| leave | Quitte un bloc try, catch ou finally, et transfère le contrôle à l'instruction spécifiée. |
| endfinally | Marque la fin d'un bloc finally. Utilisé pour terminer l'exécution d'un finally proprement. |
| fault | Spécifie un bloc exécuté en cas d'exception non gérée (rare, spécifique à certains langages). |
| try, catch, finally | Instructions structurelles, pas des opcodes, mais utilisées dans la déclaration de blocs exception via métadonnées dans l'IL. |