アセンブリ言語 CASL2 スタックとは?
CASL2でプログラミングしているときに、「スタック」ってどう使っていいか分からないときってありますよね。
このスタックは、通常のメモリとは違った動きをする領域で、段ボール箱に入れた本を再び取り出すような動作をします。
今回はアセンブリ言語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の順で、スタック領域に退避せよ。
※ 汎用レジスタGR0のデータだけスタックに移動できません。
Rプッシュ命令は、オペランドを指定せずに使用します。
また、このRプッシュ命令は汎用レジスタGR0内の値だけ対象にしないという仕様になっています。
1回ずつPUSHするのが面倒なときに重宝する命令ですね。
ポップ命令
ポップ命令は、スタックに格納されたデータをレジスタに戻す命令です。
ポップ命令を使用した分だけスタックからデータが取り出せます。
ただし、スタックが空なのにポップ命令を使用した場合、「スタックアンダーフロー」になります。
COMET2さん「もうスタックが空だぞ?スタックアンダーフローだぞ!」
名称 | オペコード | 第1オペランド |
POP | POP | レジスタ |
使用例1: POP GR1
スタック領域上の値を、汎用レジスタGR1に転送(ロード)せよ。
Rポップ命令
名称 | オペコード | 第1オペランド |
RPOP | RPOP | --- |
使用例1: RPOP
GR7~GR1の順で、スタック領域上のデータを全汎用レジスタ内(GR0を除く)に転送(ロード)せよ。
※ 汎用レジスタGR0のデータだけスタックに移動できません。
RPUSHと同じくオペランドの指定は要りません。
スタックとは
スタックとは、最初に格納されたデータが最後に取り出される、という動作するメモリ上の領域です。
例えば、最初にダンボール箱に入れた本は最後に取り出す必要があります。
また、最後に入れた本は最初に取り出すことができます。
このように、スタックとはデータを箱の中に入れるイメージで格納されていきます。
それでは具体的に動作を見てみます。
スタックの動作
例えば、以下のように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命令を使うと、スタックオーバーフローが発生してしまいます。
ここまでで、スタックには上から見て
GR3 |
↓ |
GR2 |
↓ |
GR1 |
GR3→GR2→GR1 の順番でデータが格納されているので、まずGR3から順に取り出します。
④ POP GR3
GR3のデータなので、汎用レジスタGR3にデータを戻します。
SP(スタックポインタ)はGR2のデータが入っている位置を指し示しています。
⑤ POP GR2
GR2のデータなので、汎用レジスタGR2にデータを戻します。
SPはGR1のデータが入っている位置を指し示しています。
⑥ POP GR1
GR1のデータなので、汎用レジスタGR1にデータを戻します。
SPは何も指し示していません。
※ スタックにデータがない状態でPOP命令を使用すると、スタックアンダーフローが発生してしまいます。
SPは常に最も上にあるデータの位置(アドレス)を示しています。
このように、スタックは、一番後に入れたデータ(ここではGR3のデータ)を先に取り出して元に戻します。
これをLIFO方式といいます。
- LIFO(Last In, First Out)・・・後入れ先出し方式
さいごに
スタックは箱に本を重ねて入れてから取り出すとき、を想像すれば分かりやすいと思います。
それでは次回にお会いしましょう。