IL a quelques opcodes pour fonctionner avec des arguments, tels que Je sais que ces arguments sont poussés sur la pile avant qu'un appel code> opcode est exécuté, dans certains cas, Ma question est la suivante: où sont stockés ces arguments lorsqu'un appel est initié? Est une copie de la pile de l'appelant accessible à partir de l'appel exécuté? p>
Où puis-je trouver plus d'informations sur ce sujet? p>
Je sais que la machine virtuelle est abstraite et que le compilateur JIT s'occupe de ces problèmes, mais imaginons si l'IL a été interprété, comme si elle est sur Micro Framework P> ldarg.0 code>,
ldarg.1 code> et ainsi de suite. P>
ldarg.0 code> est utilisé pour obtenir une référence à
Ce code> (par exemple des membres) p>
3 Réponses :
ECMA-335 est probablement un bon point de départ pour Ceci. P>
Par exemple, la section I.12.4.1 a ceci: p>
Les instructions émises par le générateur de code CIL contiennent des informations suffisantes pour différentes implémentations de la CLI pour utiliser différentes conventions d'appel natif. Tous les appels de méthode initialisent les zones d'état de la méthode (voir §.12.3.2) comme suit: P>
- La matrice d'arguments entrants est définie par l'appelant sur les valeurs souhaitées. LI>
- Le tableau de variables locales a toujours NULL pour les types d'objets et les champs dans des types de valeur qui contiennent des objets. De plus, si le Le drapeau localinit est défini dans l'en-tête de la méthode, puis les variables locales tableau est initialisé à 0 pour tous les types entier et à 0,0 pour tous types de points flottants. Les types de valeur ne sont pas initialisés par la CLI, mais Le code vérifié fournira un appel à une initialiseur dans le cadre de la Code du point d'entrée de la méthode. LI>
- La pile d'évaluation est vide. Li> ol> blockQuote>
et I.12.3.2 a: p>
Une partie de chaque état de la méthode est une matrice qui contient des variables locales et un tableau qui contient des arguments. Comme la pile d'évaluation, chaque élément de ces tableaux peut contenir tout type de données unique ou une instance de type de valeur. Les deux tableaux commencent à 0 (c'est-à-dire que le premier argument ou la variable locale est numéroté 0). L'adresse d'une variable locale peut être calculée à l'aide de l'instruction LDLOCA et de l'adresse d'un argument à l'aide de l'instruction LDARGA. P>
associé à chaque méthode est la métadonnée qui spécifie: p>
- si les variables locales et la mémoire de pool de mémoire seront initialisées lorsque la méthode est entrée. LI>
- Le type de chaque argument et la longueur du tableau d'arguments (mais voir ci-dessous pour les listes d'arguments variables). LI>
- Le type de chaque variable locale et la longueur du tableau de variables locales. LI> ul>
Le CLI inserve le rembourrage selon le cas pour l'architecture cible. C'est-à-dire que sur certaines architectures de 64 bits, toutes les variables locales peuvent être alignées de 64 bits, tandis que sur d'autres, ils peuvent être alignés de 8, 16 ou 32 bits. Le générateur CIL ne doit faire aucune hypothèse sur les compensations de variables locales dans le tableau. En fait, la CLI est libre de réorganiser les éléments du tableau de variables locales et différentes implémentations pourraient choisir de les commander de différentes manières. P> blockQuote>
puis dans la partition III, la description de
Callvirt code> (tout comme exemple) a: p>
Callvirt code> apparaît l'objet et les arguments de la pile d'évaluation avant d'appeler la méthode. Si la méthode a une valeur de retour, elle est poussée sur la pile lors de la fin de la méthode. Sur le côté de la calle, le paramètre Obj est accessible en argument 0, arg1 comme argument 1, etc. p> blockQuote>
Maintenant c'est tout dans un niveau em> spécification. La mise en œuvre em> peut bien décider de simplement rendre l'appel à la fonction hériter des éléments TOP N de la pile de la méthode actuelle, ce qui signifie que les arguments sont déjà au bon endroit. P>
MSIL fonctionne avec une spécification d'une machine virtuelle forte> forte>. Le modèle mental des arguments passés à une méthode est d'être présente dans un tableau. Lorsque Ldarg choisit un élément de ce réseau pour accéder à l'argument de la méthode et la pousse à la pile d'évaluation. OPCODES.LDARG_0 est une version abrégée de l'instruction OPCODES.LDARG plus générale, elle enregistre deux octets par un élément de cueillette toujours 0. Même idée pour OPCODES.LDARG_1 pour la 2e argument. Très fréquent bien sûr, LDARG ne devient "coûteux" que lorsque la méthode comporte plus de 4 arguments. L'accent mis sur les citations doubles, ce n'est pas le genre de dépenses que vous vous inquiétez. P>
Le stockage fort> réel strong> d'arguments à l'exécution est très différent. Cela dépend de la gigue que vous utilisez, différentes architectures utilisent différentes façons de passer des arguments. En général, les premiers arguments sont passés par des registres de la CPU, le reste de la pile de la CPU. Les processeurs comme X64 ou le bras ont beaucoup de registres, alors passez plus d'arguments à l'aide d'un registre que x86. Régi par les règles du __clrcall Convention d'appel pour cette architecture. p>
Bonjour Hans, s'il vous plaît voir ma mise à jour, je suis pleinement conscient de cela que l'IL est en réalité jit'ed et que la machine virtuelle est un simple résumé.
Je n'ai pas étudié l'interprète MF, ce n'est pas si intéressant. Msil a été fait pour être jeté. Il suffit de regarder vous-même, MF est open source. Vous le trouverez [ici] (netmf.codeplex.com)
La raison pour laquelle je demande cela, c'est parce que je rédigeais un interprète (voici Github.com/animaonline / ILtools ), j'ai déjà vu ces sources, merci
@HANSPASTANT: Le modèle mental des arguments transmis à une méthode est présente dans un tableau. Où Ldarg choisit un élément de ce réseau pour accéder à l'argument de la méthode et la pousse sur la pile d'évaluation i> Il aide à visualiser mais également à visualiser le modèle mental ailleurs :-) Ce que je veux dire ici est - il avant que la méthode appelait habituellement LDLOC code> ou
LDC code> etc. que j'ai lu comme appuyer sur l'article d'argument à la pile d'évaluation. Donc, si la callee au début de la méthode dispose de LDARG, cela signifie que la même valeur d'argumentation est à nouveau poussée à la pile d'évaluation?
L'IL (maintenant connu sous le nom de CIL, une langue intermédiaire commune, pas MSIL EM>) décrit les opérations sur une machine d'empilement imaginaire. Le compilateur JIT prend les instructions Il et le compose dans le code de la machine. Lorsque vous appelez une méthode, le compilateur JIT doit adhérer à une convention d'appel em>. Cette convention spécifie la manière dont les arguments sont transmis à la méthode appelée, comment la valeur de retour est transmise à l'appelant et qui est responsable de l'élimination des arguments de la pile (l'appelant ou la callee). Dans cet exemple, j'utilise le CDECL Convention d'appel, mais les compilateurs JIT utilisent d'autres conventions. Les détails exacts dépendent de la mise en œuvre, mais l'approche générale utilisée par les compilateurs .NET et mono JIT pour la compilation de CIL au code de la machine est la suivante: P> Bien sûr, il y a beaucoup d'optimisation entre ces étapes. P> prenons un exemple pour expliquer ces étapes: p> approche générale h3>
Exemple h3>
mov eax, [addr_of_arg1] // Move argument 1 in EAX
mov ecx, [addr_of_arg3] // Move argument 3 in ECX
add eax, ecx // Add ECX to EAX
push eax // Push EAX on the real stack
call [addr_of_MyMethod] // Call the method
add esp, 4
mov ecx, eax // Move the return value into ECX
mov eax, ecx // Move ECX into the return value register EAX
ret // Return
Merci pour une réponse étendue, mais je sais déjà tout cela, la question était plus théorique et plus abstraite plutôt que pratique.
@animaonline alors vous vraiment i> devez reformuler votre question. Vous dites que vous savez comment cela fonctionne en théorie (pile d'évaluation) et dans la pratique (mon message). Alors que voulez-vous savoir?