BRAS: link register et le pointeur de l'image
J'essaie de comprendre comment le lien s'inscrire et le pointeur de cadre de travail dans les BRAS. J'ai été à un couple de sites, et je voulais confirmer ma compréhension.
Supposons que j'ai eu le code suivant:
int foo(void)
{
//..
bar();
//(A)
//..
}
int bar(void)
{
//(B)
int b1;
//..
//(C)
baz();
//(D)
}
int baz(void)
{
//(E)
int a;
int b;
//(F)
}
et j'appelle foo(). Serait le lien registre contient l'adresse pour le code au point (A) et dans le cadre de pointeur contient l'adresse dans le code au point (B)? Et le pointeur de pile pourrait être n'importe où à l'intérieur de la barre(), après que tous les habitants ont été déclarées?
[edit] Ajout d'un autre appel de fonction baz()
- Je ne suis pas sûr de ce que vous vouliez dire par "le pointeur de pile pourrait être n'importe où à l'intérieur de la barre()". Aussi, vous avez l'air de se demander ce que l'état de ces choses pourrait être quand
foo()
appelsbar()
, pas quand quelque chose d'appelsfoo()
(mais je suis peut-être pas compris la question). - Oui, je voulais dire l'état des choses lorsque foo() appelle bar(). Ce que je voulais dire au sujet de la SP a été que les locaux ont été déclarés et mis sur la pile, le SP pointe sur le haut de la pile, où la dernière variable locale est déclarée.
- double possible de Quels sont SP (stack) et LR dans le BRAS?
Vous devez vous connecter pour publier un commentaire.
Certaines registre des conventions d'appel dépendent de la ABI (Application Binary Interface). Le
FP
est nécessaire dans la APC standard et pas dans la nouvelle VAMP (2003). Pour le VAMP GCC (5.0+) leFP
ne pas ont pour être utilisés, mais peuvent certainement être; les informations de débogage est annoté avec pile et le pointeur de l'image utilisation de la pile le suivi et le déroulement de code avec la VAMP. Si une fonction eststatic
, un compilateur n'est pas vraiment adhérer à toutes les conventions.Généralement de tous les BRAS, les registres usage général. Le
lr
(le lien s'inscrire, aussi R14) etpc
(compteur de programme, également R15) sont spéciaux et à l'intégrer dans le jeu d'instructions. Il est exact que lalr
serait Un. Lepc
etlr
sont liées. L'un est "où on en est" et l'autre ", où vous avez été". Ils sont les code aspect d'une fonction.Généralement, nous avons le
sp
(pointeur de pile, R13) et lefp
(pointeur de l'image, R11). Ces deux aspects sont d'ailleurs liées. CetteMicrosoft mise en page fait un bon travail de décrire les choses. Le pile est utilisé pour stocker des données temporaires ou habitants dans votre fonction. Toutes les variables dans
foo()
etbar()
, sont stockés ici, sur la pile ou dans les registres disponibles. Lefp
conserve la trace des variables de la fonction à la fonction. C'est un cadre ou l'image de la fenêtre sur la pile pour cette fonction. Le ABI définit une disposition de la présente cadre. Généralement, lelr
et d'autres registres sont sauvegardés ici en coulisses par le compilateur ainsi que la valeur précédente defp
. Ce qui fait un liste liée de la pile d'images et si vous voulez, vous pouvez suivre tout le chemin du retour àmain()
. Le racine estfp
, qui pointe vers un cadre de pile (comme unstruct
) avec une variable dans lestruct
cours de la précédentefp
. Vous pouvez aller le long de la liste, jusqu'à la finalefp
qui est normalementNULL
.De sorte que le
sp
est où la pile est et lefp
est là que la pile était, un peu comme lepc
etlr
. Chaque ancienlr
(link register) est stockée dans l'anciennefp
(frame pointer). Lesp
etfp
sont un données aspect de fonctions.Votre point de B est active
pc
etsp
. Point Un est en fait lefp
etlr
; à moins que vous appelez encore une autre fonction, puis le compilateur peut préparez-vous pour l'installation de l'fp
à point pour les données en B.Ci-après quelques BRAS assembleur qui pourrait montrer comment ça fonctionne. Ce sera différent en fonction de la façon dont le compilateur optimise, mais il devrait donner une idée,
C'est ce que
foo()
ressemblerait. Si vous n'appelez pasbar()
, alors le compilateur ne un feuille d'optimisation et n'a pas besoin d'enregistrer le cadre; seule labx lr
est nécessaire. Sans doute cela peut-être pourquoi vous êtes confus par le web des exemples. Il n'est pas toujours le même.L'emporter devrait être,
pc
etlr
sont liées code registres. L'un est "Où vous êtes", l'autre "Où vous avez été".sp
etfp
sont liées de données locales registres.L'un est", Où les données locales", l'autre ", Où le dernier les données locales".
Ces concepts sont génériques à tous les Processeurs et les langages compilés, bien que les détails peuvent varier. L'utilisation de la lien s'inscrire, pointeur de cadre font partie de la prologue de fonction et un épilogue, et si vous avez tout compris, vous savez comment une débordement de pile fonctionne sur un BRAS.
Voir aussi: BRAS de convention d'appel.
MSDN BRAS de la pile de l'article
L'université de Cambridge APC aperçu
BRAS de trace de la pile blog
Apple ABI lien
L'armature de base de mise en page est,
pc
, où nous avons stocké ce cadre.lr
, l'adresse de retour pour cette fonction.sp
, avant cette fonction mange pile.fp
, la dernière frame de pile.Un ABI peut utiliser d'autres valeurs, mais le ci-dessus sont typiques pour la plupart des configurations.
Addendum: Ce n'est pas une erreur dans l'assembleur; c'est normal. Une explication se trouve dans le BRAS généré prologs question.
lr
est où le code a été, etfp
est là que la pile a été. Cela signifie que si j'avais une autre fonctionbaz()
,sp
serait au point (F) parce que le pointeur de pile a été déplacé à allouer les variablesa
etb
à l'intérieur debaz()
;fp
être au point (E) parce quesp
était au sommet debaz()
; etlr
serait à (D)?baz()
, le ps seraitbaz()
de données.pc
estbaz()
code. Lefp
points de trucs à restaurerbar()
contexte à la fois le code et les données OU vieuxsp
et vieuxlr
==foo()
retour.lr
est le retour à labar()
, à moins quebaz()
appels avec plus de fonctions alors le compilateur doit enregistrerlr
dans un autre cadre de la pile parce que l'appel va détruirelr
.lr
contient l'adresse de retour dans le précédent cadre de pile (c'est "où vous avez été"). L'actiffp
est une adresse à l'intérieur de la frame de pile actuel.fp
,lr
, etip
sont sauvegardés sur la pile avant de la branche à une nouvelle fonction. Lorsque vous nebx lr
vous revenir à la précédente trame de pile. Mais ensuite, dans votre code, ne devriez-vous pas être la restauration delr
de la pile après l'bx lr
depuislr
contient déjà où vous avez besoin de revenir? Sinon, vous aurez la branche à la précédente-frame de pile précédent.lr
contient l'adresse du code, à partir du précédent appel de la fonction, afin de retourner à pas l'adresse de retour dans le précédent cadre de pile.lr
points à quelque part dans le segment de texte tout enfp
points à quelque part dans la pile.Avertissement: je pense que c'est à peu près droit; s'il vous plaît corrigez-la au besoin.
Comme indiqué ailleurs dans ce Q&A, sachez que le compilateur ne peut pas être nécessaire pour générer (ABI) du code qui utilise des pointeurs de frame. Images dans la pile d'appel peut souvent exiger des informations inutiles à être mis là.
Si les options du compilateur d'un appel "pas de cadres" (un pseudo indicateur d'option), puis le compilateur peut générer plus petit code qui maintient la pile des appels de données plus petits. La fonction d'appel est compilé à ne stocker le besoin d'appeler info sur la pile, et la fonction appelée est compilé à seulement pop le besoin d'information sur l'appel à partir de la pile.
Cela permet d'économiser le temps d'exécution et l'espace de pile - mais il rend le traçage en arrière dans le code appelant extrêmement dur (j'ai renoncé à essayer de...)
Info sur la taille et la forme de l'appel d'informations sur la pile n'est connue que par le compilateur et cette info a été jeté après le moment de la compilation.