[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第23回]
●コマンドテーブルに「該当なし」だったときの処理
[第21回]でコマンドテーブルに「該当なし」のときにはテーブルの最後にある「031D」にジャンプするということを説明しました。
今回はアドレス031Dから始まるプログラムについて説明します。
031Dから始まるプログラムは実は’LET’文の処理プログラムです。
コマンドテーブルに「該当なし」ならば即エラー表示しかないではないか、と思われるかもしれませんが、実はTINY BASICの場合にはすぐにはエラーにはなりません(多分多くのBASICも同じだと思います)。
たとえばA=123という文があった場合、「A=」はBASICの命令(コマンド)ではありませんからコマンドテーブルでは「該当なし」ということになります。
しかしこの文は正しい文です。
正確に書けば
LET A=123
という文になります。
TINY BASICでは(おそらくそのほかのほとんど全てのBASICでも)’LET’を省略していきなり数式(代入文)を書くことが許されています。
そういう理由でコマンドテーブルに「該当なし」なら次にLET文の処理が行なわれることになります。
LET文については雑誌掲載のプログラムリストの031Dの処理の前のところに次のような説明文がついています。
アドレス031DにはDEFLT:のラベルがついています。
’DEFLT’はdefault LETかなあと思いますがそうなのかどうかはわかりません。
上の説明文では’LET’そのものを省略した場合に実行される処理プログラムが’DEFLT’だと書いてあります。
下がそのプログラムリストです。
最初のところで改行コード(0D)かどうかの確認をしています。
これはダイレクトモード(行番号をつけないでいきなり命令文を入力するとその文が直ちに実行されることからそのように称します)で、何も入力しないでただ「Enter」キーを押したときの処理になります。
右のコメントでもそのように書いてあります。
EMPTY LINE IS OK
ELSE IT IS ’LET’
実際に入力してみるとわかるのですが、BASICに限らず大抵の処理系では、何も入力しないで「Enter」キーを押しただけの場合にはただの「改行命令」として処理されます(一行の改行が行なわれます)。
プログラムでは’0D’コードのときにはアドレス032CのLT1:にジャンプします。
LT1:については後で説明をします。
’0D’コードでなかったときにはLET文の本体の処理、つまり変数=計算式が行なわれます。
それがLET:CALL SETVALです。
SETVALについてはいずれ説明をすることになると思います。
(SETVALは[第55回]で説明をしています)
そこでは変数(A〜Zまたは@(n))=計算式という文が解読され実行されます。
変数(A〜Zまたは@(n))ではなかった場合にはWHAT?メッセージの表示ルーチンに行きます(SETVALサブルーチンからはリターンしてきません)。
SETVALサブルーチンからリターンしてきて次の0326に来たということはSETVALが正しく実行されたことになります。
0326では’,’(カンマ)のチェックが行なわれます。
TINY BASICではLET文の1行の中で複数の代入文を’,’(カンマ)で区切って書くことが許されます。
その区切りマークの確認です。
ここでは1文字の比較を行なうRST 1が実行されています。
RST 1は[第14回]で説明をしました。
’,’であれば0329のJMP LETが実行されます。
つまり’,’で区切った次の代入文の処理を続けます。
では’,’ではなかった場合には?
そのときには[第14回]で説明をした通り次の’03’で示される3バイトがパスされて032CのLT1:に行きます。
ところでLT1:は最初の’0D’コードだったときのジャンプ先でもありました。
LT1:ではRST 6を実行しています(この部分についてはまた後の方で戻って説明をします)。
RST 6は[第12回]で説明をしました。
[第12回]ではRST 6でCALLされている’FIN’サブルーチンについてはその処理内容のみを文章で説明しただけでした。
今回はそれを補足する意味で’FIN’のプログラム部分を下に示します。
’FIN’の説明は下の英文で説明がされています。
[第12回]で説明をした通り’;’(セミコロン)であれば次に書かれているはずの命令文の処理にジャンプし、’0D’コードだった場合には次のプログラム行の処理にジャンプします。
JMP RUNSML、JMP RUNNXLの前にPOP PSWがあるのは重要なポイントです。
初心者はよくここで間違いをしてしまいます。
FINはサブルーチンなので本来はRETで終らなければなりません。
このプログラムのようにJMPでサブルーチンの外に出るのはルール違反です(スタックが食い違ったまま消費されていきます)。
それをルール違反にしないようにするのがその前に置かれたPOP PSWです。
これはCALLによってPUSHされたスタックをもとに戻すためのダミー命令として使われています。
’;’でも’0D’でもなかった場合にはそのままFI2:でRETが実行されます。
FIN:は[第12回]で説明をしていますがRST 6でCALLされています。
そこでも説明していますようにFINからリターンすると、’WHAT?’の処理に行きます。
さて。
今回のプログラムでは、そもそもRST 6は最初に説明をしました031Dから始まるプログラムリストの終わりにある032CのLT1:でCALLされていました。
ところが実は032CのLT1:RST 6には続きがありません。
そこでプログラムはぷっつり切れていて032Dからは別の処理プログラムが始まっています。
いや。
それはおかしいでしょう。
RST 6はCALL命令の一種なのだから、RST 6の処理が終ったら、当然その次のアドレスに戻ってそこから実行されるはず。
なのですが。
なにしろこのTINY BASICのプログラムは随所でテクニックが使われています。
RST 6の場合、確かにCALLはされるのですけれど、リターンがないのです。
[第12回]のRST 6のプログラムリストと今回のFIN:のプログラムリストをよく見てそのことを(RST 6にはリターンがないことを)確かめてみてください。
RST 6の先頭(アドレス0030)でもPOP PSWが使われています。
なぜこんなまぎらわしいことをしているのでしょうか?
RST 6にはリターンがないというのでしたら、本来は(教科書的には)RST 6と書くところはJMP $0030と書くべきです。
でもそうしないでRST 6を使っている理由については確か前の方のどこかでも書きました(その理由はあくまで私の推測なのですが)。
この時代にはメモリはとても高価だったのです。
JMP $0030と書くべきところを1バイト命令のRST 6で置き換えれば、1箇所につき2バイト短くできるのです。
調べてみましたところRST 6は7箇所で使われていました。
都合14バイトの節約です。
こういうあたりも、つくづく「名人芸」だなあ、とあらためて思います。
復活!TINY BASIC[第23回]
2020.6.21upload
前へ
次へ
ホームページトップへ戻る