[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第50回]
●GOSUB,RETURN
今回はGOSUBとRETURNについて説明をします。
GOSUBはGOTOと似ていますがGOTOが「行きっぱなし」であるのに対してGOSUBはRETURNによってGOSUB文の次のアドレスに戻ってきます。
その動作のためにGOSUB文の次のアドレスがスタックに保存されます。
RETURN文はスタックから「戻り先」のアドレスを得ることでそのサブルーチンを呼んだGOSUB文の次のアドレスに戻ってそこから続きを実行することができます。
GOSUB〜RETURNがペアになって使われる限り、多重使用が許されます。
たとえばGOSUBでCALLした先のサブルーチン内で別のGOSUB文を使うことができます。
しかしGOSUBとRETURNはペアで使う必要があるため、多重に使用する中でプログラムミスによってGOSUBが実行されていないのにRETURN文に遭遇してしまう可能性があります。
GOSUB文が実行されていないのにRETURN文を実行しようとした場合にはHOW?メッセージが出されます。
GOSUB文とRETURN文を多重に使用することができるようにするために、GOSUB文を実行するときにRETURN文でもとに戻るときに必要な情報、GOSUB文の次のアドレスポイント(DEに入っている)、そのGOSUB文のある行の先頭アドレス(CURRNTに入っている)をスタックに退避します。
そしてその時点でのスタックポインタの値をSTKGOSに入れます。
STKGOSはユーザープログラムの実行を開始したときに初期値として0が入れられます。
RETURNが実行されたときにSTKGOSの値が0ならばGOSUBが実行されていないことになりますから、そこでHOW?が表示されます。
GOSUB文が実行された先のサブルーチン内でまたGOSUB文が実行された場合には、もとのSTKGOSの値がスタックに退避されて、STKGOSには新しいその時点でのスタックポインタの値が入れられます。
GOSUBのプログラムの説明です。
最初にPUSHAをCALLしています。
PUSHAはPOPAとペアで使われ、本来はFOR〜NEXTのために使われます。
実はGOSUB〜RETURNがスタックを利用して多重使用(ネスティング)ができるのと全く同様にFOR〜NEXTもスタックを利用することで多重に使用することができます。
FOR〜NEXTとGOSUB〜RETURNはそれぞれがペアで使われる限り両者を混ぜて多重に使用することができます。
たとえばFOR〜NEXTのループの中にGOSUB〜RETURNを置くこともできますし、逆にGOSUB〜RETURNの中にFOR〜NEXTのループを置くこともできます。
しかしともにスタックを使うために、ペアであるための情報をしっかりと管理する必要があります。
おもにFOR〜NEXTのスタック管理のためにPUSHAとPOPAが使われますが、同じようにGOSUB〜RETURNもスタックを利用するために、GOSUB〜RETURNでもPUSHA、POPAをCALLしています。
PUSHAとPOPAについてはいずれ説明をいたします。
次のRST 3は[第11回]で簡単に説明をしました。
RST 3は数式を計算して結果の値をHLに入れます。
GOSUB文の行番号をHLに入れるためにRST 3を実行します。
ここまででGOSUB 行番号 の解読が終わり、テキスト行のその位置のアドレスをPUSH Dでスタックに保存します(RETURNの実行によってその値はDEに戻されます)。
CALL FNDLNでHLに入れた行番号の行をサーチします。
FNDLNは[第28回]で説明をしました。
その行番号の行がみつからなかったときはHOW?表示ルーチンが実行されます。
みつかったときは現在のGOSUBの情報をセットするために、以前のCURRNTとSTKGOSの値をスタックに保存します。
LOPVARは直近でFOR文が実行されていることを示す変数ですが、それに代わってGOSUBが直近で実行されることになるため、それを明示するためLOPVARに0を入れます。
01D2のLXI H,0はそのために実行されますが、それによってHL=0になったことを利用してDAD SPを実行してHLにSPの値をいれます。
SHLD STKGOSでそのときのSPの値をSTKGOSに入れます。
ここまでてGOSUBの処理は終わりです。
このあとJMP RUNTSLが実行されます。
RUNTSLは[第37回]で説明をしました。
FNDLNの実行によってGOSUBで指定した行番号の行の先頭アドレスがDEに入っています。
RUNTSLはそのDEアドレスの行を実行する処理ルーチンです。
このあとRETURNについて説明をするつもりだったのですが時間がなくなってしまいました。
次回に説明をすることにいたします。
復活!TINY BASIC[第50回]
2020.7.28upload
前へ
次へ
ホームページトップへ戻る