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 poussé sur la pile entraîne un SP décrémenté, pas incrémenté).
Je me demande quelle est la justification historique de cela. 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), donc il n'y a qu'un problème si les deux côtés se heurtent au milieu. Mais pourquoi la pile obtient-elle traditionnellement la partie supérieure? D'autant plus que c'est l'opposé du modèle «conceptuel»?
(Et notez que dans l'architecture 6502, la pile se développe également vers le bas, même si elle est limitée à une seule page de 256 octets, et ce choix de direction semble arbitraire.)
la source
Une bonne explication que j'ai entendue était que certaines machines dans le passé ne pouvaient avoir que des décalages non signés, vous voudriez donc que la pile augmente vers le bas afin de pouvoir frapper vos habitants sans avoir à perdre l'instruction supplémentaire pour simuler un décalage négatif.
la source
Stanley Mazor (architecte 4004 et 8080) explique comment la direction de croissance de la pile a été choisie pour 8080 (et finalement pour 8086) dans "Intel Microprocessors: 8008 to 8086" :
la source
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 remettre à zéro les deux bits inférieurs pour obtenir une adresse correctement alignée. Si la pile se développe vers le haut, assurer l'alignement devient un peu plus délicat.
la source
A - B
puisse être mis en œuvre conceptuellement commeA + (-B)
(c'est-à-dire une étape de négation distincte pourB
), ce n'est pas dans la pratique.IIRC la pile se développe vers le bas parce que le tas se développe vers le haut. Cela aurait pu être l'inverse.
la source
realloc(3)
faut plus d'espace après un objet pour simplement étendre le mappage sans copier. Une réallocation répétée du même objet est possible lorsqu'elle est suivie d'une quantité arbitraire d'espace inutilisé.Je pense que c'est purement une décision de conception. Tous ne poussent pas vers le bas - voir ce fil de discussion SO pour une bonne discussion sur la direction de la croissance de la pile sur différentes architectures.
la source
Je crois que la convention a commencé avec l'IBM 704 et son infâme «registre de décrémentation». Le discours moderne appellerait cela un champ décalé de l'instruction, mais le fait est qu'ils sont descendus , pas montés .
la source
Juste 2c de plus:
Au-delà de toutes les raisons historiques mentionnées, je suis tout à fait certain qu'il n'y a aucune raison valable dans les processeurs modernes. Tous les processeurs peuvent prendre des décalages signés, et maximiser la distance tas / pile est plutôt inutile depuis que nous avons commencé à traiter 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é la direction de la croissance de la pile, la plupart des débordements de tampon de pile auraient été éliminés - ce qui est un gros problème. (puisque les cordes poussent vers le haut).
la source
Je ne suis pas sûr mais j'ai fait de la programmation pour le VAX / VMS à l'époque. Il me semble me souvenir d'une partie de la mémoire (le tas ??) qui monte et la pile descend. Lorsque les deux se sont rencontrés, vous étiez à court de mémoire.
la source
L'un des avantages de la croissance décroissante de la pile dans un système embarqué minimal est qu'un seul morceau de RAM peut être mappé de manière redondante à la fois sur la page O et la page 1, ce qui permet d'attribuer zéro variable de page à partir de 0x000 et la pile croît vers le bas à partir de 0x1FF, maximisant ainsi le montant qu'il faudrait augmenter avant d'écraser les variables.
L'un des objectifs de conception d'origine du 6502 était qu'il puisse être combiné avec, par exemple, un 6530, ce qui se traduisait par un système de microcontrôleur à deux puces avec 1 Ko de programme ROM, une minuterie, des E / S et 64 octets de RAM partagés entre les variables de pile et de page zéro. Par comparaison, le système embarqué minimal de l'époque basé sur un 8080 ou un 6800 serait de quatre ou cinq puces.
la source