• 検索結果がありません。

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レジスタ内の 現在のアドレスに、メインの

EBP

レジスタに保存されている内容の

4

バイトを加えた ものになる。メインに対する動的変数はすべて、この値から正の固定オフセット位置 にある。