例えば、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
変数は、全てスタックに取られる。
インターネット上の、スタックを分かり
やすく説明しているページ
マイコンプログラム実習へ戻る