6.5. ブロック構造言語でのプロシージャ・コール
6.5.1. ENTER 命令
ENTER
命令は、ブロック構造言語において広く使用されている有効範囲規則(スコープルール)と互換性があるスタックフレームを作成する。ブロック構造言語では、プ ロシージャの有効範囲は、プロシージャがアクセスできる変数のセットである。有効 範囲に対する規則は、言語によって異なる。これらの規則としては、プロシージャの ネスト構造をベースとするもの、個別にコンパイルされるファイルへのプログラムの 分割をベースとするもの、その他のモジュール化スキームをベースとするものなどが ある。
ENTER
命令は、2つのオペランドを持つ。第1のオペランドには、現在コールされているプロシージャについてスタックに確保される動的記憶領域をバイト数で指定す る。動的記憶領域は、プロシージャがコールされる際に作成される変数(自動変数と も呼ばれる)用に割り当てられるメモリである。第
2
のオペランドは、プロシージャ のレキシカル・ネスト・レベル(0~31)である。ネストレベルとは、プロシージャ・
コールの階層におけるプロシージャの深さである。レキシカル・レベルは、現在実行 されているプログラムやタスクの保護特権レベルやI/O特権レベルとは無関係である。
次の例に示す
ENTER
命令は、スタック上に2K
バイトの動的記憶領域を割り当て、こ のプロシージャのスタックフレーム内で、前の2
つのスタックフレームに対するポイ ンタをセットアップする。ENTER 2048,3
IA-32 インテル® アーキテクチャ・ソフトウェア・デベロッパーズ・マニュアル 上巻:基本アーキテクチャ
6-20
レキシカル・ネスト・レベルによって、前のスタックフレームから新しいスタックフ レームにコピーするスタック・フレーム・ポインタの数が決まる。スタック・フレー ム・ポインタは、プロシージャの変数にアクセスする際に使用される
1
ダブルワード である。プロシージャが、他のプロシージャの変数にアクセスする際に使用するス タック・フレーム・ポインタのセットは、ディスプレイと呼ばれる。このディスプレ イ内の最初のダブルワードは、前のスタックフレームに対するポインタである。LEAVE
命令でこのポインタを使用して、現在のスタックフレームを廃棄してENTER
命令の効果を元に戻せる。
プロシージャに対するディスプレイを作成した後、
ENTER
命令は第1のパラメータで 指定されたバイト数だけESP
レジスタの内容をデクリメントし、そのプロシージャに 対する動的ローカル変数を割り当てる。ESP
レジスタ内のこの新しい値は、プロシー ジャ内のすべてのPUSH
操作やPOP
操作に対するスタックのトップの初期値として機 能する。プロシージャがそのディスプレイをアドレス指定できるようにするため、
ENTER
命令 によって、EBPレジスタはディスプレイ内の最初のダブルワードをポイントする。ス タックは下方向に増えるため、このダブルワードには実際にはディスプレイ内で最高 位のアドレスが入る。EBPレジスタをベースレジスタとして指定するデータ操作命令 においては、データ・セグメント内ではなくスタック・セグメント内の位置を自動的 にアドレス指定する。ENTER
命令は、ネスト形式と非ネスト形式の2
つの方法で使用できる。レキシカル・レベルが
0
の場合は、非ネスト形式が使用される。非ネスト形式では、EBPレジスタ の内容がスタックにプッシュされ、ESPレジスタの内容がEBP
レジスタにコピーされ る。同時に、動的記憶領域を割り当てるためにESPレジスタの内容から第1オペラン
ドの内容が引かれる。非ネスト形式は、スタック・フレーム・ポインタがコピーされ ない点でネスト形式とは異なる。ネスト形式のENTER
命令は、第2
オペランド(レキ シカル・レベル)がゼロでない場合に使用される。ENTER
命令の正式な定義を、次の疑似コードで示す。STORAGE
は、ローカル変数用に割り当てる動的記憶領域のバイト数で、
LEVEL
はレキシカル・ネスト・レベルである。PUSH EBP;
FRAME_PTR ← ESP;
IF LEVEL > 0 THEN
DO (LEVEL − 1) times EBP ← EBP − 4;
PUSH Pointer(EBP);(* EBPがポイントするダブルワード*) OD;
PUSH FRAME_PTR;
FI;
EBP ← FRAME_PTR;
ESP ← ESP − STORAGE;
プロシージャ・コール、 割り込み、例外
6
(他のすべてのプロシージャがネストされる)メイン・プロシージャは、最高位のレ キシカル・レベル、つまりレベル
1
で動作する。メイン・プロシージャがコールする 最初のプロシージャは、次のレキシカル・レベル、つまりレベル2
で動作する。レベ ル2
のプロシージャは、(コンパイラが指定する固定位置にある)メイン・プログラム の変数にアクセスできる。レベル1
の場合は、コピーの対象となる前回のディスプレ イが存在しないため、ENTER
命令によってリクエストされた動的格納領域だけがス タック上に割り当てられる。あるプロシージャが、それより低いレキシカル・レベルにある別のプロシージャを コールする場合は、コールされるプロシージャは、コール元の変数にアクセスできる。
ENTER
命令により、コール元プロシージャのスタックフレームへのポインタをディスプレイに配置することで、このアクセスが可能になる。
あるプロシージャが、同じレキシカル・レベルにある別のプロシージャをコールする 場合は、コールされるプロシージャにコール元の変数にアクセスさせることはできな い。この場合、ENTER命令は、すでにネストされている(自身より高いレキシカル・
レベルで動作している)プロシージャを参照するディスプレイ部分だけをコール元プ ロシージャからコピーする。新しいスタックフレームには、コール元プロシージャの スタックフレームをアドレス指定するためのポインタは含まれない。
ENTER
命令は、再入可能なプロシージャを、同じレキシカル・レベルにあるプロシージャへのコールとして処理する。この場合、再入可能なプロシージャが繰り返される たびに、そのプロシージャの変数と、それがネストされているプロシージャの変数し かアドレス指定することはできない。再入可能なプロシージャは、常に自身の変数に ついてはアドレス指定でき、以前に繰り返されたスタックフレームへのポインタは不 要である。
ENTER
命令は、当該プロシージャより高いレキシカル・レベルにあるプロシージャのスタック・フレーム・ポインタだけをコピーすることで、プロシージャが同じレキシ カル・レベルの変数ではなく、それより高いレキシカル・レベルの変数だけにアクセ スすることを可能にしている(図
6-6.
を参照)。図6-6. ネストされたプロシージャ
メイン(レキシカル・レベル1)
プロシージャA(レキシカル・レベル2)
プロシージャB(レキシカル・レベル3)
プロシージャC(レキシカル・レベル3)
プロシージャD(レキシカル・レベル4)
IA-32 インテル® アーキテクチャ・ソフトウェア・デベロッパーズ・マニュアル 上巻:基本アーキテクチャ
6-22
ブロック構造言語では、
ENTER
命令で定義されたレキシカル・レベルを使用して、ネ ストされたプロシージャの変数に対するアクセスを制御する。例えば、図6-6.
におい て、プロシージャA
がプロシージャB
を、プロシージャB
がプロシージャC
をコール する場合、プロシージャC
はメイン・プロシージャとプロシージャA
の変数にはアク セスできるが、同じレキシカル・レベルのプロシージャB
の変数にはアクセスできな い。図6-6.
に示すネストされたプロシージャにおいて、変数へのアクセスを定義する と次のようになる。1. メインは、固定位置に変数を持つ。
2. プロシージャAは、メインの変数だけにアクセスできる。
3. プロシージャBは、プロシージャAとメインの変数だけにアクセスできる。プロシー ジャBは、プロシージャCやプロシージャDの変数にはアクセスできない。
4. プロシージャCは、プロシージャAとメインの変数だけにアクセスできる。プロシー ジャCは、プロシージャBやプロシージャDの変数にはアクセスできない。
5. プロシージャD は、プロシージャC、プロシージャA、メインの変数にアクセスでき る。プロシージャDは、プロシージャBの変数にはアクセスできない。
図
6-7.
において、メイン・プロシージャの先頭にあるENTER
命令によって、メイン に対して動的記憶領域としてダブルワードが3
つ作成されるが、他のスタックフレー ムからポインタをコピーすることはしない。ディスプレイ内の最初のダブルワード は、ENTER命令が実行される前にEBP
レジスタにあった最後の値のコピーを保持す る。2
番目のダブルワードは、ENTER
命令後のEBP
レジスタの内容のコピーを保持す る。命令が実行された後、EBPレジスタはスタックにプッシュされた最初のダブル ワードをポイントし、またESP
レジスタはスタックフレーム内の最後のダブルワード をポイントする。メインがプロシージャ
A
をコールすると、ENTER命令によって新しいディスプレイ が作成される(図6-8.
を参照)。最初のダブルワードは、メインのEBP
レジスタに保 持されていた最後の値である。2番目のダブルワードは、メインのスタックフレーム に対するポインタであり、メインのディスプレイの2
番目のダブルワードからコピー されたものである。これは、メインのEBP
レジスタに保持されていた最後の値のコ ピーでもある。プロシージャA
は、メインがレベル1
にあるため、メインの変数にア クセスできる。したがって、メインが使用する動的記憶領域のベースアドレスは、EBPレジスタ内の 現在のアドレスに、メインの