Lorsque vous compilez du code C et que vous regardez l’assemblage, la pile croît à l’arrière comme ceci:
_main:
pushq %rbp
movl $5, -4(%rbp)
popq %rbp
ret
-4(%rbp)
- Cela signifie-t-il que le pointeur de base ou le pointeur de pile déplacent les adresses de la mémoire au lieu de remonter? Pourquoi donc?
J'ai changé $5, -4(%rbp)
pour $5, +4(%rbp)
, compilé et exécuté le code et il n'y avait aucune erreur. Alors pourquoi devons-nous toujours revenir en arrière sur la pile de mémoire?
-4(%rbp)
cela ne déplace pas le pointeur de base et que+4(%rbp)
cela ne pourrait pas fonctionner.malloc
grandir le tas en arrièremain
sa RBP est annulée. C'est certainement possible. (Et oui, l'écriture4(%rbp)
irait sur la valeur RBP enregistrée). Euh, en fait, cela n’est jamais le casmov %rsp, %rbp
, donc l’accès à la mémoire est relatif à la RBP de l’appelant , si c’est ce que le PO a réellement testé !!! Si cela a été réellement copié à partir de la sortie du compilateur, certaines instructions ont été omises!Réponses:
Oui, les
push
instructions décrémentent le pointeur de pile et écrivent dans la pile, tandispop
que l’inverse effectue une lecture à partir de la pile et incrémente le pointeur de pile.Ceci est quelque peu historique dans le sens où pour les machines avec une mémoire limitée, la pile était placée haut et grossie vers le bas, alors que le tas était bas et développé vers le haut. Il n'y a qu'un seul espace de "mémoire libre" - entre le tas et la pile, et cet espace est partagé, l'un ou l'autre peut croître dans l'espace selon les besoins individuels. Ainsi, le programme ne manque de mémoire que lorsque la pile et le tas se rencontrent sans laisser de mémoire libre.
Si la pile et le tas grandissent tous deux dans la même direction, il y a deux lacunes et la pile ne peut pas vraiment se transformer dans l'espace du tas (l'inverse est également problématique).
À l'origine, les processeurs n'avaient pas d'instructions de traitement de pile dédiées. Cependant, avec l’ajout de la pile au matériel, le modèle évoluait à la baisse et les processeurs suivent encore ce modèle.
On pourrait faire valoir que sur un ordinateur 64 bits, il y a suffisamment d'espace d'adressage pour permettre plusieurs espaces vides - et, à preuve, de multiples espaces vides sont nécessairement le cas lorsqu'un processus comporte plusieurs threads. Bien que cela ne soit pas une motivation suffisante pour changer les choses, étant donné que, avec les systèmes à fractures multiples, la direction de la croissance est sans doute arbitraire. C'est pourquoi tradition / compatibilité fait pencher la balance en avant.
Il faudrait modifier les instructions de manipulation de la pile CPU afin de changer la direction de la pile, ou bien renoncer à l' utilisation des instructions pousser et popping dédiés (par exemple
push
,pop
,call
,ret
, autres).Notez que l’architecture du jeu d’instructions MIPS n’est pas dédiée
push
&pop
, il est donc pratique de faire croître la pile dans un sens ou dans l’autre - vous pouvez toujours souhaiter une disposition mémoire un espace pour un processus à un seul thread, mais vous pouvez augmenter la pile et le tas vers le bas. Cependant, si vous agissiez de la sorte , certains codes C varargs pourraient nécessiter un ajustement de la source ou du passage des paramètres sous le capot.(En fait, étant donné qu’il n’existe pas de traitement de pile dédié sur MIPS, nous pourrions utiliser pré ou post incrémentation ou pré ou post décrémentation pour la mise en place de la pile tant que nous utilisons l’inverse exact pour le vidage de la pile et en supposant que Le système d’exploitation respecte le modèle d’utilisation de pile choisi. En effet, dans certains systèmes embarqués et certains systèmes éducatifs, la pile MIPS est agrandie.
la source
push
etpop
sur la plupart des architectures, mais aussi l'interruption de manutention beaucoup plus important,call
,ret
et tout ce qui a cuit au four en interaction avec la pile.gets()
, ou fait un objetstrcpy()
qui ne soit pas en ligne, le retour dans ces fonctions de bibliothèque utilisera l'adresse de retour écrasée. Actuellement, avec des piles à la baisse, c'est quand leur appelant revient.strcpy
), sur une arche où l'adresse de retour est conservée dans un registre sauf si elle doit être renversée, l'accès n'est pas possible pour obstruer le retour adresse.Dans votre système spécifique, la pile commence à partir d'une adresse de mémoire haute et "grandit" vers le bas pour devenir une adresse de mémoire faible. (le cas symétrique de bas en haut existe aussi)
Et puisque vous avez changé de -4 à +4 et que cela a fonctionné, cela ne signifie pas que c'est correct. La structure de la mémoire d’un programme en cours d’exécution est plus complexe et dépend de nombreux autres facteurs qui peuvent avoir contribué au fait que vous n’avez pas subi une panne instantanée sur ce programme extrêmement simple.
la source
Le pointeur de pile pointe vers la limite entre la mémoire de pile allouée et non allouée. Sa croissance vers le bas signifie qu'il pointe au début de la première structure dans l'espace de pile alloué, les autres éléments alloués étant suivis par des adresses plus grandes. Avoir des pointeurs indiquant le début des structures allouées est beaucoup plus courant que l’inverse.
De nos jours, sur de nombreux systèmes, il existe un registre séparé pour les trames de pile qui peuvent être déroulées de manière relativement fiable afin de comprendre la chaîne d'appels, avec un stockage de variables local intercalé. La manière dont ce registre de trame de pile est configuré sur certaines architectures signifie qu'il pointe finalement derrière le stockage de variables local, par opposition au pointeur de pile précédent . Donc, utiliser ce registre de trame de pile nécessite alors une indexation négative.
Notez que les cadres de pile et leur indexation sont un aspect secondaire des langages informatiques compilés. C'est donc le générateur de code du compilateur qui doit gérer le "manque de naturel" plutôt qu'un programmeur de langage d'assemblage médiocre.
Ainsi, bien qu'il y ait eu de bonnes raisons historiques de choisir des piles de croître vers le bas (et certaines d'entre elles sont conservées si vous programmez en langage assembleur et que vous ne vous occupez pas de la configuration d'un cadre de pile approprié), elles sont devenues moins visibles.
la source