Je sais que dans les architectures que je connais personnellement (x86, 6502, etc.), la pile croît généralement vers le bas (c’est-à-dire que chaque élément placé sur la pile donne un SP décrémenté et non incrémenté).
Je me demande quelle en est la raison historique. Je sais que dans un espace d'adressage unifié, il est pratique de démarrer la pile à l'extrémité opposée du segment de données (par exemple), de sorte qu'il n'y a qu'un problème si les deux côtés se heurtent au centre. Mais pourquoi la pile obtient-elle traditionnellement la partie supérieure? Surtout compte tenu du fait que c'est l'opposé du modèle "conceptuel"?
(Notez que dans l'architecture 6502, la pile croît également vers le bas, même si elle est liée à une seule page de 256 octets, et ce choix de direction semble arbitraire.)
En ce qui concerne la raison historique, je ne peux pas dire avec certitude (car je ne les ai pas conçues). Mes pensées sur le sujet sont que les premiers processeurs ont mis leur compteur de programme d'origine à 0 et qu'il était naturel de démarrer la pile à l'autre bout et de croître, car leur code croît naturellement vers le haut.
Soit dit en passant, ce paramètre du compteur de programme mis à 0 lors de la réinitialisation n'est pas le cas pour toutes les [] anciennes CPU. Par exemple, le Motorola 6809 récupèrerait le compteur de programme à partir des adresses
0xfffe/f
afin que vous puissiez commencer à exécuter à un emplacement arbitraire, en fonction de ce qui a été fourni à cette adresse (généralement, mais sans s'y limiter, la ROM).
Une des premières choses que feraient certains systèmes historiques serait d’analyser la mémoire à partir du haut jusqu’à ce qu’un emplacement qui lirait la même valeur écrite de sorte qu’il connaisse la RAM réelle installée avec 64K espace d’adresse n’avait pas nécessairement 64K ou RAM, en fait 64K aurait été massive à mes débuts). Une fois qu’elle a trouvé l’adresse réelle la plus haute, elle place le pointeur de pile de manière appropriée et peut ensuite commencer à appeler des sous-routines. Cette analyse est généralement effectuée par le code d'exécution de la CPU dans ROM dans le cadre du démarrage.
En ce qui concerne la croissance des piles, toutes ne croissent pas vers le bas, voir cette réponse pour plus de détails.
Une bonne explication que j’ai entendue est que dans le passé, certaines machines ne pouvaient avoir que des offsets non signés. Par conséquent, vous voudriez que la pile grossisse de façon à pouvoir toucher vos sections locales sans perdre l’instruction supplémentaire pour simuler un offset négatif.
Une raison possible pourrait être que cela simplifie l'alignement. Si vous placez une variable locale sur la pile qui doit être placée sur une limite de 4 octets, vous pouvez simplement soustraire la taille de l'objet du pointeur de pile, puis mettre à zéro les deux bits inférieurs pour obtenir une adresse correctement alignée. Si la pile grossit, assurer l'alignement devient un peu plus difficile.
IIRC la pile croît vers le bas parce que le tas grandit. Cela aurait pu être l'inverse.
Je crois que c'est purement une décision de conception. Tous ne descendent pas vers le bas - voir ce fil SO pour une bonne discussion sur la direction de la croissance de la pile sur différentes architectures.
Stanley Mazor (architectes 4004 et 8080) explique comment la direction de croissance de la pile a été choisie pour 8080 (et éventuellement pour 8086) dans "Intel Microprocessors: 8008 to 8086" :
Le pointeur de pile a été choisi pour fonctionner en "descente" (la pile avançant vers la mémoire réduite) afin de simplifier l'indexation dans la pile à partir du programme de l'utilisateur (indexation positive) et de simplifier l'affichage du contenu de la pile à partir d'un panneau avant.
Je crois que la convention a commencé avec l’IBM 704 et son infâme "registre de décrémentation". La parole moderne l’appellerait un champ offset de l’instruction, mais le fait est qu’ils sont passés bas, pas haut.
Juste 2c de plus:
Au-delà de toutes les raisons historiques mentionnées, je suis presque certain qu'il n'y a aucune raison valable pour les processeurs modernes. Tous les processeurs peuvent accepter des décalages signés, et maximiser la distance pile/pile est plutôt discutable depuis que nous avons commencé à traiter avec plusieurs threads.
Personnellement, je considère cela comme un défaut de conception de la sécurité. Si, par exemple, les concepteurs de l'architecture x64 avaient inversé le sens de la croissance de la pile, les débordements de mémoire tampon de la pile auraient été éliminés, ce qui est plutôt grave.
Je ne suis pas certain, mais j’ai fait de la programmation pour le VAX/VMS à l’époque. Il me semble me souvenir qu'une partie de la mémoire (le tas ??) est en train de monter et la pile de descendre. Lorsque les deux se sont rencontrés, alors vous étiez à court de mémoire.