例えば、1文字出力のプログラムを、いたる所で呼び出したいとする。
.
.
mov.l #0,er0
jmp putchar
L0: .
.
mov.l #1,er0
jmp putchar
L1: .
.
mov.l #2,er0
jmp putchar
L2: .
.
putchar:
. なんかやってる
.
cmp.l #0,er0
bz L0
cmp.l #1,er0
bz L1
cmp.l #2,er0
bz L2
以上のように、3つくらいならばいいが、100ヶ所から呼び出されると
したら、困ってしまう。
.
.
mov.l #L0,er0
mov.l er0,@NextJump (NextJumpはRAMの領域)
jmp putchar
L0: .
.
mov.l #L1,er0
mov.l er0,@NextJump
jmp putchar
L1: .
.
mov.l #L2,er0
mov.l er0,@NextJump
jmp putchar
L2: .
.
putchar:
. なんかやってる
.
mov.l @NextJump,er0
jmp er0
この方法も、サブルーチン毎に変数を用意してやらないと
いけないので大変である。
以上のような、プログラムの呼出は、頻繁に使われるため、
以下のように名前が付いている。
あるプログラムのまとまりを呼び出す操作->サブルーチンコール
呼び出される側->サブルーチン
これも非常に面倒くさい。
で、スタックというのを用意する。
.
.
jsr putchar :L0のアドレスをスタックに積んで jump
L0: .
.
jsr putchar :L1のアドレスをスタックに積んで jump
L1: .
.
jsr putchar :L2のアドレスをスタックに積んで jump
L2: .
.
putchar:
. なんかやってる
.
rts
:スタック上のアドレスをプログラムカウンタに入れる
この機構は、サブルーチンの中でサブルーチンを呼び出している場合にも
有効である(付録:スタック)。
このCPUの場合には、er7
をスタックとして利用している。
h8300-hms-gcc -mh 1.s -o 1.x
h8300-hms-gdb 1.x
TargetSettings
で、Targetを Simulator を選択
一度RUNを押す
(8)待避領域としてのスタック
あるサブルーチンが、r0~r3 を破壊してしまうとする。
呼出側のプログラムでは、r0~r3
までを破壊されたくない場合には、
push r0
push r1
push r2
push r3
jsr サブルーチン
pop r3
pop r2
pop r1
pop r0
などとする
(9)一時的変数領域としてのスタック
C言語では、関数内の auto
変数は、全てスタックに取られる。
インターネット上の、スタックを分かり
やすく説明しているページ
マイコンプログラム実習へ戻る