なぜスタックは通常下向きに成長するのですか?


95

私が個人的に精通しているアーキテクチャ(x86、6502など)では、スタックは通常下向きに成長します(つまり、スタックにプッシュされるすべてのアイテムは、増加したSPではなく減少したSPになります)。

これの歴史的根拠について疑問に思っています。統合されたアドレススペースでは、スタックをデータセグメントの反対側から(たとえば)開始するのが便利なので、2つの側が中央で衝突した場合にのみ問題が発生します。しかし、なぜスタックは伝統的にトップの部分を獲得するのでしょうか?特に、これが「概念」モデルとは正反対であることを考えると、

(また、6502アーキテクチャーでは、単一の256バイトのページにバインドされているにもかかわらず、スタックも下方向に大きくなることに注意してください。この方向の選択は任意です。)

回答:


52

歴史的な根拠については、私は(私がそれらを設計しなかったので)確かに言うことはできません。この問題についての私の考えは、初期のCPUは元のプログラムカウンターを0に設定していて、コードが自然に上向きに成長するため、反対側からスタックを開始して下向きに成長することは自然な欲求でした。

余談ですが、リセット時にプログラムカウンタを0に設定することは、すべての初期のCPUには当てはまりません。たとえば、Motorola 6809はアドレスからプログラムカウンターをフェッチする0xfffe/fため、そのアドレスで提供されたもの(通常はROMに限定されません)に応じて、任意の場所で実行を開始できます。

一部の歴史的システムが最初に行うことの1つは、書き込まれた同じ値を読み戻す場所が見つかるまでメモリを上からスキャンして、実際にインストールされているRAM(たとえば、64Kアドレス空間のz80)を知ることです。 64KやRAMは必ずしも必要ではありませんでした。実際、64Kは私の初期の頃は巨大でした。最上位の実際のアドレスが見つかると、スタックポインターを適切に設定し、サブルーチンの呼び出しを開始できます。このスキャンは通常、スタートアップの一部としてROM内のコードを実行するCPUによって行われます。

スタックの成長に関しては、すべてが下向きに成長するわけではありません。詳細については、この回答を参照してください。


1
Z80 RAM検出戦略の話が好きです。テキストセグメントが上に向かってレイアウトされていることには、ある程度の意味があります-昔のプログラマーは、スタックよりもその影響に対処するのにいくぶん直接的な接触を持っていました。ありがとうpaxdiablo スタック実装の代替形式のセットへのポインターも非常に興味深いものです。
Ben Zotto

初日のメモリにはそのサイズを通知する方法がないので、手動で計算する必要がありますか?
phuclv 2015

1
@LưuVĩnhPhúc、私はあなたが私の後ろの世代(または2世代)だと仮定しなければなりません。起動時にユーザー要求する日時を取得するためのTRS-80モデル3の方法を今でも覚えています。メモリスキャナを設定してメモリの上限を設定することは、当時の最新技術であると考えられていました。
paxdiablo

1
実際、Zilog Z80のドキュメントには、PCレジスタを0000hに設定して実行することでデバイスが起動することが記載されています。割り込みモードを0に設定し、割り込みを無効にし、IおよびRレジスタも0に設定します。その後、実行を開始します。0000hで、コードの実行を開始します。そのコードは、サブルーチンを呼び出したり、割り込みを有効にしたりする前に、スタックポインタを初期化する必要があります。あなたが説明するように動作するZ80を販売しているベンダーは何ですか?
MikeB 2015年

1
マイク、申し訳ありませんが、私はより明確であったはずです。CPUがメモリをスキャンすると言ったとき、それがCPU自体の機能であるとは言いませんでした。実際にはROMのプログラムから制御されていました。明確にします。
paxdiablo 2015年

21

私が聞いた良い説明の1つは、過去の一部のマシンは符号なしのオフセットしか持つことができなかったので、負のオフセットを偽造するための追加の命令を失うことなくローカルにヒットできるように、スタックを下向きに大きくしたいと考えています。


7

Stanley Mazor(4004および8080アーキテクト)は、「Intel Microprocessors:8008 to 8086」でスタックの成長方向が8080(最終的には8086)に選択された方法を説明します。

スタックポインターは、ユーザープログラムからスタックへのインデックス付け(正のインデックス付け)を簡略化し、フロントパネルからのスタックの内容の表示を簡略化するために、「下り坂」で実行されます(スタックは下位メモリに向かって進みます)。


6

考えられる理由の1つは、配置が簡単になることです。4バイト境界に配置する必要があるローカル変数をスタックに配置する場合、スタックポインターからオブジェクトのサイズを差し引くだけで、下位2ビットをゼロにして適切に配置されたアドレスを取得できます。スタックが上方向に大きくなると、整列を確実にするのが少し難しくなります。


1
コンピュータは減算しません。彼らは2の賛辞を追加します。減算によって行われることはすべて、実際には加算によって行われます。コンピュータには減算器ではなく加算器があることを考慮してください。
jww

1
@jww-それは違いのない違いです。私はコンピュータがそれらを減算するだけではなく、減算するだけだと主張しているかもしれません!この回答の目的では、それは実際には重要ではありませんが、ほとんどのALUは、同じパフォーマンスで加算と減算の両方をサポートする回路を使用ます。つまり、A - B概念的には実装できますがA + (-B)(つまり、の個別の否定ステップB)、実際には実装されていません。
BeeOnRope

@jww初期のコンピューターではあなたのnitpickは間違っています。2の補数が勝つまでに少し時間がかかりました。勝つまでは、1の補数と符号と大きさを使用するコンピューターがありました。これらの実装では、足し算と引き算を比較したほうが有利な場合があります。したがって、追加情報がない場合、スタック方向などのアドレス指定スキームの選択に影響を与える可能性のある要因としてこれを除外するのは誤りです。
mtraceur

4

IIRCヒープは上向きに成長するため、スタックは下向きに成長します。それは逆だったかもしれません。


5
上向きに成長するヒープは、いくつかのケースで効率的な再割り当てを可能にしますが、下向きに成長するヒープはほとんどしません。
Peter Cordes

@PeterCordesなんで?
Yashas

3
@Yashas:コピーせずにマッピングを拡張するには、オブジェクトの後にrealloc(3)さらにスペースが必要なため。同じオブジェクトを繰り返し再割り当てすると、その後に任意の量の未使用のスペースが続く場合があります。
Peter Cordes

2

純粋に設計上の決定だと思います。それらすべてが下向きに成長するわけではありません- 異なるアーキテクチャーでのスタックの成長の方向についての良い議論については、このSOスレッドを参照してください。


1

大会はIBM 704とその悪名高い「デクリメントレジスタ」から始まったと思います。現代のスピーチはそれを命令のオフセットフィールドと呼びますが、要点は、彼らが下がったことです 上昇はなくことです。


1

あと2c以上:

言及されたすべての歴史的根拠を超えて、私は現代のプロセッサで有効である理由がないことを確信しています。すべてのプロセッサは符号付きオフセットをとることができ、ヒープ/スタック距離を最大化することは、複数のスレッドの処理を開始して以来、あまり重要ではありません。

私は個人的にこれをセキュリティ設計上の欠陥だと考えています。たとえば、x64アーキテクチャの設計者がスタックの成長方向を逆にした場合、ほとんどのスタックバッファオーバーフローは解消されたでしょう。これは大きな問題です。(文字列が上向きに成長するため)。


0

確かではありませんが、当時はVAX / VMSのプログラミングを行っていました。メモリの一部(ヒープ??)が上がり、スタックが下がるのを覚えているようです。ふたりが出会ったとき、あなたは記憶が不足していました。


1
これは本当ですが、なぜヒープが上向きに成長し、その逆ではないのですか?
Ciro Santilli郝海东冠状病六四事件法轮功

0

最小の組み込みシステムでスタックの増加を下降させる1つの利点は、RAMの単一のチャンクをページOとページ1の両方に冗長にマップできるため、0x000から始まるゼロのページ変数を割り当て、スタックを0x1FFから下方向に増加させ、変数を上書きする前に大きくする必要がある量。

6502の当初の設計目標の1つは、たとえば6530と組み合わせて、1 KBのプログラムROM、タイマー、I / O、および64バイトのRAMを共有する2チップマイクロコントローラーシステムを実現できることでした。スタック変数とページゼロ変数の間。比較すると、8080または6800に基づく当時の最小組み込みシステムは、4または5チップになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.