Ich weiß, dass in den Architekturen, mit denen ich persönlich vertraut bin (x86, 6502 usw.), der Stapel normalerweise nach unten wächst (dh jedes auf den Stapel geschobene Element führt zu einem dekrementierten SP, nicht zu einem inkrementierten).
Ich wundere mich über die historischen Gründe dafür. Ich weiß, dass es in einem einheitlichen Adressraum praktisch ist, den Stapel am gegenüberliegenden Ende des Datensegments zu starten (z. B.), sodass es nur dann ein Problem gibt, wenn die beiden Seiten in der Mitte kollidieren. Aber warum bekommt der Stapel traditionell den oberen Teil? Besonders wenn man bedenkt, wie das Gegenteil des "konzeptuellen" Modells ist?
(Beachten Sie, dass in der 6502-Architektur der Stapel auch nach unten wächst, obwohl er auf eine einzelne 256-Byte-Seite beschränkt ist und diese Richtungsauswahl willkürlich erscheint.)
quelle
Eine gute Erklärung, die ich gehört habe, war, dass einige Maschinen in der Vergangenheit nur vorzeichenlose Offsets haben konnten. Sie möchten also, dass der Stapel nach unten wächst, damit Sie Ihre Einheimischen treffen können, ohne die zusätzliche Anweisung verlieren zu müssen, um einen negativen Offset vorzutäuschen.
quelle
Stanley Mazor (Architekt 4004 und 8080) erklärt in "Intel Microprocessors: 8008 to 8086" , wie die Stapelwachstumsrichtung für 8080 (und schließlich für 8086) gewählt wurde :
quelle
Ein möglicher Grund könnte sein, dass dies die Ausrichtung vereinfacht. Wenn Sie eine lokale Variable auf dem Stapel platzieren, die an einer 4-Byte-Grenze platziert werden muss, können Sie einfach die Größe des Objekts vom Stapelzeiger subtrahieren und dann die beiden unteren Bits auf Null setzen, um eine richtig ausgerichtete Adresse zu erhalten. Wenn der Stapel nach oben wächst, wird die Ausrichtung etwas schwieriger.
quelle
A - B
dies konzeptionell alsA + (-B)
(dh als separater Negationsschritt fürB
) implementiert werden könnte , ist dies in der Praxis nicht der Fall .IIRC wächst der Stapel nach unten, weil der Haufen nach oben wächst. Es hätte auch umgekehrt sein können.
quelle
realloc(3)
mehr Platz benötigt wird, um das Mapping ohne Kopieren zu erweitern. Eine wiederholte Neuzuweisung desselben Objekts ist möglich, wenn eine beliebige Menge nicht genutzten Speicherplatzes folgt.Ich glaube, es ist eine reine Designentscheidung. Nicht alle wachsen nach unten - in diesem SO-Thread finden Sie eine gute Diskussion über die Richtung des Stapelwachstums auf verschiedenen Architekturen.
quelle
Ich glaube, die Konvention begann mit der IBM 704 und ihrem berüchtigten "Dekrementregister". Die moderne Sprache würde es ein Versatzfeld der Anweisung nennen, aber der Punkt ist, dass sie nach unten und nicht nach oben gingen .
quelle
Nur noch 2c:
Über alle erwähnten historischen Gründe hinaus bin ich mir ziemlich sicher, dass es keinen Grund gibt, der in modernen Prozessoren gültig ist. Alle Prozessoren können vorzeichenbehaftete Offsets verwenden, und die Maximierung des Heap / Stack-Abstands ist ziemlich umstritten, seit wir uns mit mehreren Threads befasst haben.
Ich persönlich halte dies für einen Sicherheitsfehler. Wenn beispielsweise die Designer der x64-Architektur die Stapelwachstumsrichtung umgekehrt hätten, wären die meisten Überläufe des Stapelpuffers beseitigt worden - was eine große Sache ist. (da die Saiten nach oben wachsen).
quelle
Ich bin mir nicht sicher, aber ich habe damals einige Programmierungen für VAX / VMS durchgeführt. Ich scheine mich zu erinnern, wie ein Teil des Speichers (der Haufen ??) hoch und der Stapel runter ging. Als sich die beiden trafen, war dir das Gedächtnis ausgegangen.
quelle
Ein Vorteil des absteigenden Stapelwachstums in einem minimalen eingebetteten System besteht darin, dass ein einzelner RAM-Block redundant sowohl auf Seite O als auch auf Seite 1 abgebildet werden kann, sodass ab 0x000 keine Seitenvariablen zugewiesen werden können und der Stapel von 0x1FF abwärts wächst, wodurch das maximiert wird Menge, die es wachsen müsste, bevor Variablen überschrieben werden.
Eines der ursprünglichen Entwurfsziele des 6502 war, dass er beispielsweise mit einem 6530 kombiniert werden konnte, was zu einem Zwei-Chip-Mikrocontrollersystem mit 1 KB Programm-ROM, Timer, E / A und 64 Byte gemeinsam genutztem RAM führte zwischen Stapel- und Seitennullvariablen. Im Vergleich dazu wäre das minimale eingebettete System dieser Zeit, das auf einem 8080 oder 6800 basiert, vier oder fünf Chips.
quelle