スタック・ポインタによるメモリ・アクセス 前述の例1と例2では,メモリ・アクセスを行うため,必ずアドレス指定を伴っていることにお気づきでしょうか.ただし,プログラム・カウンタによるROMのプログラム・リードは異なっています そのため,1バイトのメモリ操作が3バイト命令になっています(図1-8). もし,このアドレス指定が省略できたら命令が短くなり,実行速度も上がります.これを可能にするのがスタック・ポインタによるアドレス指定です. スタック操作は,スタック・ポインタで操作するアドレスを保持し,スタックへ書き込み(押し込み)したデータ数だけポインタ値を調整する手法です. スタックへのデータ格納命令(PUSH,CALLなど)を実行すると,スタック・ポインタが保持するアドレスは格納データ数だけ若くなり,逆にデータ取り出し命令(POP,RETなど)を実行するとそのデータ数だけポインタ値は大きくなります. スタック操作の具体例 スタック操作を行うためには,あらかじめスタック・ポインタにスタック領域の先頭番地+1番地の値を設定します. 次の例の場合,7FFFH番地以下をスタック領域とするので, LD SP,8000H ;スタック・ポインタに ;8000Hを設定 を実行します. スタックは,サブルーチン・コール時の戻り番地のメモなどにも使われますから,通常のCPUの起動直後に,この命令を実行します. 図1-10に,スタック操作の具体例を説明します.
例1:スタック格納命令PUSHを実行する この状態から, PUSH BC ;BCレジスタの内容を
を実行すると,スタック・ポインタ値が1番地下がり(7FFFH),その番地へBレジスタの内容がコピーされます.次に,スタック・ポインタ値がもう1番地下がり(7FFEH),その番地へCレジスタの内容がコピーされます. その結果,図1-11のように,7FFFH番地は56H,7FFEH番地は78Hとなります.スタック・ポインタ値は7FFEHです.
例2:データ取り出し命令POPを実行 例1の状態から, POP DE ;スタック領域の内容を ;DEへ取り出し を実行すると,スタック・ポインタ値7FFEH番地の内容をEレジスタへコピー,その後スタック・ポインタ値を1番地上げます. 次にスタック・ポインタ値7FFFH番地の内容をDレジスタへコピー,その後スタック・ポインタ値を1番地上げます. その結果,図1-12のようにDレジスタは56H,Eレジスタは78Hとなり,スタック・ポインタ値は8000Hとなります.
例3:CALLおよびRET時のスタック操作 サブルーチン・コールや割り込みなどを実行するとき,プログラムの戻り番地をスタックにメモし(押し込み),サブルーチンや割り込み処理の先頭番地へジャンプします. サブルーチン内でリターン命令を検出すると,スタックにメモしていた戻り番地をプログラム・カウンタにコピーして元のプログラムに復帰します. 例2のスタック状態で,1000H番地にある, CALL 2000H 命令を実行したときのスタックの使われ方を説明します(図1-13).Z80の場合,CALL命令は3バイト命令ですから,戻り番地は1003Hです.
CALL命令が実行されるとスタック7FFFHに戻り番地の上位バイト10Hを,7FFEHに下位バイト03Hを入れ,スタック・ポインタは7FFEHとなります.その後プログラム・カウンタに2000Hを書き込み,2000H番地へジャンプします. サブルーチン内で RET命令が実行されるとスタックされていた戻り番地1003Hをプログラム・カウンタにコピーし,スタック・ポインタ値を2番地戻して8000Hとします. これでサブルーチン・コール前の状態になります. スタック使用時の注意事項 スタックを使用する命令のPUSHとPOPまたはCALLとRETは一対の命令です. ネスティングは構いませんが,図1-14のように順序を誤るとプログラムは暴走します.
Copyright 2000 武下 博彦 |
|
Copyright 1997-2001 CQ Publishing Co.,Ltd.