
■ スタック領域 ■
前回は「関数」について概要を説明しました。
関数とは、ある「機能」を持った物の事でした。
また、関数が別の関数を呼出す時に、その関数にどんな処理を
して欲しいかを教えてあげる為に「パラメータ」という物を渡
す必要がある事も説明しました。
そしてそのパラメータを渡す為にはレジスタが使用されるので
すが、インテルプロセッサのレジスタ数はとても少ない為、沢
山のパラメータを渡すにはレジスタが足りないという事も説明
しました。
今回は、沢山のパラメータを渡す為には何を使用しなければな
らないのかを説明します。
前回説明したように、ある関数が別の関数を呼出す時には「パ
ラメータ」を渡してあげる必要があるのでした。
以下に、例として「アプリケーションソフトウェア」が「絵を
表示する機能」を呼出しているイメージを示します。
┌──────────────────────────┐
│ アプリケーションソフトウェア │
│ │
└───┬──────────────────────┘
│ レジスタEBX
│ パラメータ格納 ┌──────┐
├────────────────→│丸い絵を表示│
│ └──┬───┘
│ 呼出し ┌────────┐ │
├────→│絵を表示する機能│ │
│ │ │ │
│ └───┬────┘ │
│ │ パラメータ参照 │
│ │←─────────┘
│ │
│ 画面
│ ┌──────┐
│ 表示 │ │
├───────┼→○ │
│ │ 丸い絵 │
│ │ │
│ └──────┘
絵を表示する機能はこのようにして「パラメータ」を受け取る
事で「何の絵を表示しなければならないか」を知る事が出来る
のでした。
上の例ではパラメータは1つだけですが、沢山のパラメータを
渡す為には何を使用しなければならないのでしょうか?
答えは「メモリ」です。
皆さんのパソコンにも128メガバイトとか、256メガバイ
トとか、環境によりさまざまですがメモリが搭載されていると
思います。
その中の1部分を関数間でやりとりを行なう為に使用するので
す。
以下に沢山のパラメータをメモリを使用して渡しているイメー
ジを示します。
┌──────────────────────────┐
│ アプリケーションソフトウェア │
│ │
└───┬──────────────────────┘
│ メモリ
│ パラメータ格納 ┌──────┐
├────────────────→│丸い絵を表示│
│ │ ・ │
│ 呼出し ┌────────┐ │ ・ │
├────→│絵を表示する機能│ │ ・ │
│ │ │ │ ・ │
│ └───┬────┘ └──┬───┘
│ │ パラメータ参照 │
│ │←─────────┘
│ │
│ 画面
│ ┌──────┐
│ 表示 │ │
├───────┼→○ │
│ │ 丸い絵 │
│ │ │
│ └──────┘
今までパラメータをレジスタで渡していたのが、今度はメモリ
を使用して渡していますね。
メモリは128メガバイトや、256メガバイト、512メガ
バイト等、広大な領域がありますが、その中の1部分をパラメ
ータをやりとりする為に使用するのです。
そしてこの「メモリ」ですが、使われ方によっていくつかの種
類に分けられます。
例えばメモリの中でプログラムを格納する為に使用される領域
の事を「コード領域」と呼びます。また、メモリの中でデータ
を格納する為に使用される領域の事を「データ領域」と呼びま
す。
そして、パラメータを渡す為に使用される領域としては「スタ
ック領域」と呼ばれる物が使用されます。
「スタック領域」とは、その関数の中だけで使用されるデータ
や、パラメータ等、「一時的に使用される」データを格納する
為の領域の事をいいます。
「スタック領域」にデータを格納したり、取り出したりする時
は、「積み重ねるようにして」データアクセスが行なわれます。
「積み重ねるようにして」と言っても分かりにくいので下に図
を書いて説明します。
◆パラメータを入れる時
まずスタック領域に1個のパラメータを格納している図を見て
みましょう。
パラメータ1┐
│
│
スタック領域││ │
├│ ┤
││ │
├│ ┤
│↓ │
├──────┤
│パラメータ1│
└──────┘
普通にパラメータが格納されただけです。
では、もう1つパラメータを格納してみましょう。
パラメータ2┐
│
│
スタック領域││ │
├│ ┤
│↓ │
├──────┤
│パラメータ2│
├──────┤
│パラメータ1│
└──────┘
スタック領域なので「積み重ねるようにして」パラメータが格
納されました。
◆パラメータを取り出す時
まずスタック領域から1個のパラメータを取り出している図を
見てみましょう。
┌→パラメータ2
│
│
スタック領域│ │ │
├ │ ┤
│ │ │
├──────┤
│パラメータ2│
├──────┤
│パラメータ1│
└──────┘
パラメータ2の方が先に取り出されました。
では、もう1つパラメータを取り出してみましょう。
┌→パラメータ1
│
│
│ │ │
├ │ ┤
│ │ │
├ │ ┤
│ │ │
├──────┤
│パラメータ1│
└──────┘
今度はパラメータ1が取り出されました。
なんとなくスタック(積み重ねる)領域の挙動がお分かり頂け
ると良いのですが。。
1番最後に格納したデータが1番最初に取り出されましたよね。
 ̄ ̄  ̄ ̄
これがスタック領域の一番の特徴です。
この入れ方/取り出し方の事をLIFO(Last In First Out)(最後
に入れたデータを最初に取り出す)と呼びます。
ちなみに、コンピュータウィルスはこの領域に書かれてある情
報を書き換えて活動する物が多いです。
スタック領域は「一時的に使用する」データを入れる為の場所
なのですが、ここに実行プログラムを入れておけば実行する事
も可能なのです。
それでは次に、スタック領域にパラメータを格納するのをアセ
ンブラ言語で書くとどうなるか、見てみましょう。
push 1
たったこれだけです。非常に簡単ですよね?
この例の場合、「1」というパラメータをスタック領域に格納
しました。
push 1┐
│
│
スタック領域││ │
├│ ┤
││ │
├│ ┤
│↓ │
├──────┤
│ 1 │
└──────┘
パラメータを5個スタック領域に格納したい場合は
push 1
push 2
push 3
push 4
push 5
等と書きます。
この場合、スタック(積み重ねる)領域なので、1番最後に格
納したデータがスタック領域の1番上に来ます。
スタック領域│ │
├──────┤
│ 5 │
├──────┤
│ 4 │
├──────┤
│ 3 │
├──────┤
│ 2 │
├──────┤
│ 1 │
└──────┘
では、上の様に5つのデータをスタック領域に格納後、データ
を取り出すのをアセンブラ言語で書くとどうなるか、見てみま
しょう。
pop ebx
たったこれだけです。非常に簡単ですよね?
この例の場合、スタック領域から取り出したデータはEBXレジ
スタに格納されます。
レジスタEBX
┌──────┐
pop ebx┌→│ 5 │
│ └──────┘
│
スタック領域│ │ │
├──────┤
│ 5 │
├──────┤
│ 4 │
├──────┤
│ 3 │
├──────┤
│ 2 │
├──────┤
│ 1 │
└──────┘
続けて、もう1つデータを取り出してみましょう。
今度も同じ命令を使います。
pop ebx
この命令の動作イメージは以下の様になります。
レジスタEBX
┌──────┐
pop ebx┌→│ 4 │
│ └──────┘
│
スタック領域│ │ │
├ │ ┤
│ │ │
├──────┤
│ 4 │
├──────┤
│ 3 │
├──────┤
│ 2 │
├──────┤
│ 1 │
└──────┘
スタック領域なので1番最後に入れたデータから順番にデータ
が取り出されているのが分かると思います。
ここでちょっと疑問に思われた方はいらっしゃらないでしょう
か?
アセンブラコードを見てもらってお分かり頂けたかと思います
が、スタック領域からデータを取り出す時、全く同じ命令を使
用しました。
pop ebx
同じ命令なのに1番最初にスタック領域からデータを取り出す
時は、ちゃんとスタック領域の下から5番目のデータが取り出
されました。
レジスタEBX
┌──────┐
pop ebx┌→│ 5 │
│ └──────┘
│
スタック領域│ │ │
├──────┤
│ 5 │←下から5番目が取り出され
├──────┤ ている。
│ 4 │
├──────┤
│ 3 │
├──────┤
│ 2 │
├──────┤
│ 1 │
└──────┘
レジスタEBX
★もう1度、全く同じ命令┌──────┐
pop ebx┌→│ 4 │
│ └──────┘
│
スタック領域│ │ │
├ │ ┤
│ │ │
├──────┤
│ 4 │←今度は下から4番目が取り
├──────┤ 出されている。
│ 3 │
├──────┤
│ 2 │
├──────┤
│ 1 │
└──────┘
全く同じ命令を使用したはずなのに、何故1回目と2回目とで
データが取り出される場所が異なるのでしょうか?
間違って下から5番目のデータが2度取り出されたり、また、
下から2番目や3番目のデータが取り出されたりする事はない
のでしょうか?
実は間違ってしまわないように、インテルプロセッサにはある
工夫がしてあります。
その工夫については次回説明します。