[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第54回]
●PUSHA
今回はFORプログラムについてプログラムリストをもとにしながら実際のプログラムの動作について説明するつもりだったのですが、下のリストの通り、プログラムの先頭から、まだ説明をしていない他のアドレスのプログラムをCALLしたり、他のアドレスのプログラムにジャンプしていますので、やっぱりそれらのプログラムについて先に説明をしておいたほうがよさそうです。
ということで今回は予定を変更してPUSHAについて説明をします。
PUSHAは現在のFOR変数領域をスタックに保存します。
PUSHAはスタックを消費するため、先頭のアドレス0619から0621でスタックオーバーにならないかどうかをチェックしています。
SP−STKLMTの計算をしたいのですが8080には16ビットの減算命令がありません。
そこでCHGSGNサブルーチンでSTKLMTを負数に変換したうえでそこにSPを加算します。
CHGSGNは[第48回]で説明をしました。
POP BはPUSHAをCALLしたもとのプログラムに戻るためのアドレスを一時保存しておくためです。
STKLMTはオリジナルのTINY BASICでは13DEになっています。
ここがスタックの下限アドレスです。
スタックトップは1400です。
SP<=STKLMTならスタックオーバーなのでSORRY表示ルーチンへジャンプします。
それならJNCではなくてJCではないか?と思われるかもしれませんが、この計算を行なうと本当の減算のときとはキャリーが逆になります。
実は、このプログラムにはまずいところがあります。
作者の見落としではないかと思います。
下のアドレスマップは[第16回]〜[第18回]でお見せしました。
STKLMTの前にはBUFEND(13DD)があります。
BUFFERは入力バッファです。
サイズはCRコードを含めて64バイトです。
実際に入力バッファとして使われるのは139D〜13DCまでで13DDが使われることはありません。
ということはスタックとして使えるのは13DD〜13FFまでということになります。
SPの値としては13DDが下限値です。
すると、さきほどのPUSHAの先頭の計算はおかしいのではないか?
と思います。
SP<=STKLMTでスタックオーバーになるということはSP=13DFがリミットということです。
PUSHAがリターンするときには、
PU1:PUSH H
PUSH B
RET
が実行されます。
もしもSP=13DFだったとすると、RETの直前にはSP=13DBになるのですが、それは一時的でRETしたときにはSP=13DDになります。
ぎりぎりセーフで、ここまでなら計算はあっています。
しかし。
後で説明するつもりですが、PUSHAの本来の目的はFOR変数領域をスタックに保存することです。
FOR変数領域は10バイトです。
上の計算でPUSH Hだけを実行したときにぎりぎりセーフになるとしても、本来の目的でPUSHAを実行すると、ぎりぎりのときにはスタックが8バイト不足してしまいます(入力バッファに食い込んでしまいます)。
その状態でIN命令が実行されると最悪の場合FOR変数領域の一部が破損してしまう可能性があります。
そうならないようにするためにはSTKLMTの値は13DE+8=13E6でなければならないことになります。
安全を考えると13DE+A=13E8が望ましいでしょう。
それはともかくとしまして。
もともとスタックエリアは十分とはいえないほど小さいです。
スタック領域が13DD〜13FFとした場合、スタックのサイズは36バイトしかありません。
FOR〜NEXTを多重使用した場合3重が限界です。
うーん。
確かに、TINYですねえ。
FORプログラムの説明に戻ります。
スタックオーバーではなかった場合にはアドレス0624のLHLD LOPVAR以降が実行されます。
HL=0のときはPU1:にジャンプしてリターンします。
HL=0は現在アクティブなFORループはないということを示しています。
HL=0ではなかった場合には現在アクティブなFORループの中にいることになりますから、そこで新たなFOR変数の値を設定するために、現在のFOR変数領域をスタックに退避させます。
スタックにはLOPPT、LOPLN、LOPLMT、LOPINCそしてLOPVARの順に退避されます。
復活!TINY BASIC[第54回]
2020.8.2upload
前へ
次へ
ホームページトップへ戻る