CASL2では、スタックというメモリ上の領域を使用してプログラミングすることがあります。
このスタックは、通常のメモリとは異なった動作をする領域で、箱に本を入れて再び取り出すときに似ている動作をします。
今回はスタックとそれに関わる命令について見てみたいと思います。
プッシュ命令
プッシュ命令は、メモリのスタック領域にデータを格納するための命令です。
このプッシュ命令を使用した回数だけスタックにデータが格納されます。
スタックの容量がいっぱいにも関わらず、プッシュ命令を使用した場合、「スタックオーバーフロー」になります。
COMET2さん「もう、スタックがいっぱいでデータは要らん。スタックオーバーフローっていっとこ」
名称 | オペコード | 第1オペランド | 第2オペランド
|
PUSH | PUSH | アドレス | ---
|
アドレス | レジスタ
|
使用例1: PUSH A
メモリ
A番地のアドレス値を
スタック領域に退避せよ。
使用例2: PUSH 1
メモリ
1番地のアドレス値を
スタック領域に退避せよ。
使用例3: PUSH 0, GR1
メモリ
汎用レジスタGR1のデータ+0番地のアドレス値を
スタック領域に退避せよ。
通常は、使用例3のような使い方をします。
PUSH命令は、使用例1、2を見ての通りオペランドで指定したアドレス値をスタックに退避しています。
使用例3は、指標修飾を利用することで、結果的にレジスタの値をスタックへと送ることができているということになります。
Rプッシュ命令
名称 | オペコード | 第1オペランド
|
RPUSH | RPUSH | ---
|
使用例1: RPUSH
GR0を除く全汎用レジスタ内のデータを
GR1~GR7の順で、
スタック領域に退避せよ。
オペランドを指定せずに使用します。
1回ずつPUSHするのが面倒なときに重宝する命令ですね。
ポップ命令
ポップ命令は、スタックに格納されたデータをレジスタに戻す命令です。
ポップ命令を使用した分だけ、スタックからデータが取り出されます。
スタックが空であるにも関わらず、ポップ命令を使用した場合、「スタックアンダーフロー」になります。
COMET2さん「おい、スタックは空だぞ?スタックアンダーフローっていっとこ」
名称 | オペコード | 第1オペランド
|
POP | POP | レジスタ
|
使用例1: POP GR1
スタック領域上のデータを、汎用レジスタ
GR1に転送せよ。
Rポップ命令
名称 | オペコード | 第1オペランド
|
RPOP | RPOP | ---
|
使用例1: RPOP
スタック領域上のデータを、
GR7~GR1の順で、
GR0を除く全汎用レジスタ内に転送せよ。
RPUSHと同じくオペランドの指定は要りません。
スタックとは
スタックとは、メモリ上の領域の1つで、最初にこの領域に格納されたデータが最後に取り出される、という動作をします。
最初にダンボールに入れた本は、1番下にあるため、最後に取り出す必要があります。また、最後に入れた本は1番上にあるため、最初に取り出すことができます。
このようにスタック領域では、データは箱に重ねるイメージで格納されていきます。
それでは具体的に動作を見てみます。
スタックの動作
例えば、以下のようにPUSHとPOPを実行するプログラムがあるとして、汎用レジスタ内のデータがスタックでどのように動くか見てみましょう。
: | | (中略) |
|
5 | | PUSH 0, GR1 | <--①
|
6 | | PUSH 0, GR2 | <--②
|
7 | | PUSH 0, GR3 | <--③
|
8 | | POP GR3 | <--④
|
9 | | POP GR2 | <--⑤
|
10 | | POP GR1 | <--⑥
|
: | | (中略) |
|
① PUSH 0, GR1
スタックのイメージ
SPは、GR1のデータが入っている位置を指し示しています。
② PUSH 0, GR2
SPはGR2のデータが入っている位置を指し示しています。
③ PUSH 0, GR3
SPはGR3のデータが入っている位置を指し示しています。
※ スタックの容量を超えてPUSH命令を使うと、スタックオーバーフローが、発生してしまうため、PUSHのし過ぎに注意してください。
ここまでで、スタックには上から見て
GR3のデータ --> GR2のデータ --> GR1のデータ
の順番でデータが格納されているため、下記の命令の順番で取り出します。
④ POP GR3
GR3のデータなので、汎用レジスタ
GR3にデータを戻します。
SPは、GR2のデータが入っている位置を指し示しています。
⑤ POP GR2
GR2のデータなので、汎用レジスタ
GR2にデータを戻します。
SPは、GR1のデータが入っている位置を指し示しています。
⑥ POP GR1
GR1のデータなので、汎用レジスタ
GR1にデータを戻します。
SPは、何も指し示していません。
※ スタックにデータがない状態でPOP命令を使用すると、スタックアンダーフローが発生してしまうため、PUSHとPOPの数に気をつけてください。
SPは、常に最も上にあるデータの位置(アドレス)を指しています。
このように、スタックは、一番後に入れたデータ(ここではGR3のデータ)を先に取り出して元に戻します。
これを
LIFO(Last In, First Out):後入れ先出し方式といいます。
最後に
今回は、スタックとそれを操作する命令について紹介いたしました。
スタックは、箱に本を重ねて入れ、取り出すときを想像すれば分かりやすいと思います。
続きはまた次回にご期待を!