Ce qui se passe en langage d'assemblage lorsque vous appelez une méthode/fonction?
Si j'ai un programme en C++/C (la langue n'a pas beaucoup d'importance, juste pour illustrer un concept):
#include <iostream>
void foo() {
printf("in foo");
}
int main() {
foo();
return 0;
}
Ce qui se passe dans l'assemblée? Je ne suis pas à la recherche de code assembleur que je ne suis pas allé loin en elle encore, mais ce qui est le principe de base?
- Notez que vous ne l'appelez pas "méthodes" en c, juste de "fonctions". C'est pourquoi il n'a pas de sens de faire comme si c et c++ sont dans la même langue.
- "la langue n'a pas d'importance combien": les concepts sont assez similaires pour les langages compilés. Les langages interprétés (comme php, javascript) peuvent être très différents. Je crois que vous êtes à la recherche pour le comportement de langages compilés?
- C++ n'a pas de notion de méthodes, seules les fonctions de membre.
Vous devez vous connecter pour publier un commentaire.
En général, c'est ce qui se passe:
call
instruction ou dans le cadre d'unjmp
oubr
instruction (saut/branche)Les détails de la ci-dessus varient d'une plateforme à une autre, et même d'un compilateur de compilateur (voir, par exemple, STDCALL vs CDECL conventions d'appel). Par exemple, dans certains cas, les registres du CPU sont utilisés au lieu de stocker des trucs sur la pile. L'idée générale est la même
Vous pouvez voir par vous-même:
Sous Linux 'compiler' votre programme avec:
Et vous obtiendrez une liste de programme en assembleur (myprogram.s).
De sûr, vous devriez savoir un peu plus sur l'assembleur pour comprendre (mais il vaut la peine de l'apprentissage, car il permet de comprendre le fonctionnement de votre machine). L'appel d'une fonction (architecture x86) c'est en gros:
-masm=intel
à la gcc de commande.Une brève explication: La pile actuelle de l'état est enregistré, une nouvelle création de la pile et le code de la fonction qui doit être exécutée est chargé et exécuté. Cela implique de pénaliser les quelques registres de votre microprocesseur, certains frénétique et-vient de lecture/écriture de la mémoire et une fois fait, la fonction d'appel de la pile de l'etat est restaurée.
Arguments sont poussés dans la pile et "appel" l'instruction est faite
Appel est un simple "jmp" avec en poussant une adresse de l'instruction dans la pile ("ret" à la fin d'une méthode de popping et sautant sur lui)
Je pense que vous voulez prendre un coup d'oeil à la pile d'appel pour obtenir une meilleure idée de ce qui se passe lors d'un appel de la fonction: http://en.wikipedia.org/wiki/Call_stack
Ce qui se passe? En x86, la première ligne de votre fonction principale pourrait ressembler à quelque chose comme:
call foo
La
call
instruction va pousser l'adresse de retour sur la pile, puisjmp
à l'emplacement de foo.Une très bonne illustration:
http://www.cs.uleth.ca/~holzmann/C/système/memorylayout.pdf
Ce qui se passe?
C imite ce qui se passera dans l'assemblée...
Il est si proche de la machine que vous pouvez réaliser ce qui va se produire
1 - un appel le contexte est établi sur la pile
2 - les paramètres sont poussés sur la pile
3 - un "appel" est réalisée à la méthode
La général idée est que vous avez besoin de
RET
instruction sait où pour continuer.Les caractéristiques varient en fonction de l'architecture à l'architecture. Et le plus spécifique, les détails peuvent varier entre les différentes langues. Bien qu'il n'y a habituellement des moyens de contrôler dans une certaine mesure afin de permettre l'interopérabilité entre les différentes langues.
Un assez bon point de départ est la Article de wikipédia sur les conventions d'appel. Sur x86, par exemple, la pile est presque toujours utilisé pour passer des arguments aux fonctions. Sur de nombreuses architectures RISC, toutefois, les registres sont principalement utilisés alors que la pile n'est nécessaire que dans des cas exceptionnels.
L'idée commune est que les registres qui sont utilisés dans l'appel de la méthode sont poussés sur la pile (pointeur de pile est en
ESP
registre), ce processus est appelé "pousser les registres". Parfois, ils sont également mis à zéro, mais cela dépend. Assemblée programmeurs ont tendance à libérer plus de registres puis la commune 4 (EAX
,EBX
,ECX
etEDX
sur x86), avoir plus de possibilités à l'intérieur de la fonction.Lorsque la fonction se termine, le même phénomène se produit dans le sens inverse: la pile est restauré à l'état d'avant l'appel. Ceci est appelé le "popping les registres".
Mise à jour: ce processus ne doit pas nécessairement se produire. Les compilateurs peuvent optimiser loin et en ligne vos fonctions.
Mise à jour: normalement les paramètres de la fonction sont poussés sur la pile dans l'ordre inverse, lorsqu'elles sont récupérées à partir de la pile, ils apparaissent comme si dans l'ordre normal. Cet ordre n'est pas garanti par C. (réf:
Inner Loops
par Rick Stand)