x86 アセンブリではesp
、スタック ポインターebp
はヒープ ポインターですか? また、データ構造が 1 つではなく 2 つあるのはなぜでしょうか。
そして、何をesi
/edi
表すのですか?
x86 アセンブリではesp
、スタック ポインターebp
はヒープ ポインターですか? また、データ構造が 1 つではなく 2 つあるのはなぜでしょうか。
そして、何をesi
/edi
表すのですか?
一般に、マシン アーキテクチャ上のレジスタは、いかなる目的にも専用である必要はありません。実際問題として、一般的に使用される機能をサポートするレジスタを指定することにより、そのレジスタはその機能専用になります。
x86 では、ESP ポインターは PUSH/CALL 命令とさまざまな割り込み/トラップで使用され、リターン アドレスなどの回復可能な状態を格納します。これらはプログラミングをサポートする上で非常に魅力的であり、したがってコンパイラと OS ベンダーによってコミットされているため、ESP は基本的に他の目的には使用できません。ESP に関して任意のインデックスからメモリを参照できるため、「スタック」と現在の関数スタック フレームの両方を管理するために使用できます。
ただし、ESP に関する変数 (現在のスタック フレームに対してローカル) のインデックス オフセットは、プログラムが値をスタックにプッシュおよびポップし、ESP が変更されると変化します。コンパイラはこれらすべてを追跡できるため、正しいインデックス オフセットを使用できます。ただし、アセンブリを手動でコーディングしている場合、これを確実に行うことは現実的に不可能であり、スタック フレームのベース ポインターを使用する方が簡単です。その場合、変数のインデックス オフセットは、スタック フレーム ポインターに対する定数にすることができます。EBP はこの目的のために早くから Intel によって指定されており、これをサポートするための特別なインデックス モードと、ディスプレイを構築するための特別な EBP 関連の命令(Algol スタイルでスタック フレームを字句的に囲むためのポインターのセット) もあります。
ただし、コンパイラはこの目的で EBP を使用する必要はありません。レジスタの数が少ないマシン (x86) では、別の空きレジスタがあると、より小さくてタイトなコードを生成するのに役立ちます。古い CPU では、EBP を使用しないと別のペナルティがありました。ローカル変数の ESP からのインデックス オフセットは、スタック フレーム ベースからのインデックス オフセットよりも大きくなる傾向があるため、EBP をフリー レジスタとして使用すると、オフセットが大きくなるため、プログラムが大きくなります。 ESPで使用。これは、命令のフェッチが高価だったときに重要でした。命令キャッシュが現状と同じくらい優れているため、これはほとんど問題になりません。Microsoft の C コンパイラ (GCC と思われます) には、フレーム ポインタを使用しないようにするスイッチがあり、そのため、コードを高速化するためにプログラム サイズの一部を放棄しています。
ヒープ変数は、単にスタック フレームにないものです。任意のレジスタを使用してアクセスできます。
一部の言語 (例: PARLANSE コンパイラ) はヒープ割り当てのみを使用します。スタック フレームもヒープから取得されます (また、ESP は割り当てられたスペース ブロックの先頭に設定されます)。
通常、ESP はスタックの上部を指し、EBP はスタック フレームの下部を指すため、どちらもヒープではなくスタック上のアドレスを指します。ほとんどの場合、スタック フレームの下部へのポインターを保持する必要はまったくないため、一部のコンパイラーは単に EBP を別の汎用レジスターとして使用する場合があります。
ESI と EDI は汎用レジスタですが、例外が 1 つあります。文字列命令 (movs、lods など) は、これらをそれぞれソース アドレスと宛先アドレスとして扱います。
xBP
レジスタ、 、xSI
およびに固有のものや動作がいくつかありますがxDI
、これらはいずれの関数にもバインドされていません。アセンブリ コードで好きなように使用できます。
メモリ全体は 4 つのセグメントに編成されます。コード、データ、スタック、エクストラ。ヒープは多目的ストレージ (動的割り当て (malloc など) など) 用であり、スタックは特に命令ポインターと別のプロシージャを呼び出すとき (再帰中など) に変数を格納するために使用されます。データ セグメントは、グローバル変数と静的変数用です。
ESI/EDI については、SO に関するこの質問を参照してください: ESI & EDI レジスタの目的?
編集: これも参照してください:ヒープ vs データ セグメント vs スタック割り当て