web-dev-qa-db-ja.com

スタックが一般的に下向きになるのはなぜですか?

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

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

(また、6502アーキテクチャでは、スタックが単一の256バイトページに制限されていても、スタックが下に向かって成長することに注意してください。この方向の選択は任意のようです。)

85
Ben Zotto

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

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

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

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

45
paxdiablo

私が聞いた良い説明の1つは、過去の一部のマシンは符号なしオフセットしか持てなかったため、負のオフセットを偽造する余分な指示を失うことなく地元の人々を攻撃できるように、スタックを下向きに成長させたいと思っていました。

20
anq

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

6
jalf

IIRCでは、ヒープが上向きに成長するため、スタックは下向きに成長します。逆の場合もありました。

4
Christian V

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

スタックポインターは、ユーザーのプログラムからスタックへのインデックス付け(ポジティブインデックス付け)を簡素化し、フロントパネルからのスタックの内容の表示を簡素化するために、「下り坂」で実行されます。

3
roolebo

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

2
Kaleb Brasee

私は、コンベンションはIBM 704とその悪名高い「減少レジスタ」から始まったと信じています。現代のスピーチはそれを命令のオフセットフィールドと呼びますが、ポイントは彼らが行ったdownnotup

1
luser droog

あと2cだけ:

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

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

1
Ofek Shilon

確信はありませんが、昔はVAX/VMSのプログラミングをしていました。メモリーの一部(ヒープ??)が増え、スタックが下がったことを覚えているようです。二人が会ったとき、あなたはメモリ不足でした。

0
Martin