[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第14回]
●最も基本的なサブルーチン(5)
今回はTSTC(RST 1)の続きの部分の説明です。
TSTC(RST 1)は[第11回]で説明しました。
戻っていただくのも面倒なことですので、TSTC(RST 1)の先頭部分のリストと説明を再掲します。
XTHLはスタックトップとHLレジスタを交換する命令です。
スタックトップには比較する文字が置かれたアドレスが入っています。
そのアドレスがHLレジスタに入ります。
RST 5はDEレジスタで示すアドレス(通常は入力バッファ)の文字をAレジスタに入れてリターンするルーチンです(その文字がブランク(スペース)の場合には次の文字が入れられる)。
そのAレジスタの文字とM(HLで示すメモリアドレスの中身)とを比較します。
比較の結果C、ZなどのフラグがON/OFFされます。
このあと0068(TC1)にジャンプします。
そして下がTC1のプログラムリストです。
HLで示されるメモリの文字コードとDEで示されるメモリ(通常は入力バッファ)の文字コードが一致したならばTC2にジャンプします。
そこではDEとHLがともに+1されます。
HLはTC1:のところで+1していますから2バイト分先に進むことになります(ここが肝心です)。
そしてHLとスタックトップがまた交換されます(ここも巧妙な仕掛けです)。
XTHLはRST 1の先頭で使われています。
最初にスタックトップとHLの内容が交換されて今またHLとスタックトップの内容が再び交換されました。
HLの内容は変わりませんがスタックトップの値は+2されています。
さて。
スタックトップには何があるのでしょうか?
それはのちほど説明します。
プログラムリストの説明に戻ります
比較した結果不一致ならばその次のアドレス(006C)に進みます。
ここも何をやっているのかよくわからないところですが、ここでも巧妙な仕掛けを行なっています。
BCレジスタをスタックに退避しているのはBCレジスタを一時的なワークレジスタとして使うためです。
HLで示されるメモリの値をCレジスタに入れます。
HLは0068のINX Hで+1されていることに注意してください。
Bレジスタに00を入れたあと、DAD Bを実行します。
DAD BはHL←HL+BCです。
その結果HLの値には計算前のHLで示されたメモリの値が加算されます。
スタックに退避してあったBCの値をもとに戻します。
そのあとDCX Dを実行しているのはその次のTC2:のINX Dを帳消しにするためです(この場合DEの値は変わらないことになります)。
そして上の説明と同じTC2:の処理が行なわれます。
以上がTSTCサブルーチンの説明です。
???
わかりませんでしょう。
プログラムリストの右側にぎっしり書いてあるコメントを読んでもさっぱりわからん?でありましょう。
これは実に巧妙なプログラムです(感心してしまいます)。
実際にRST 1が使われているプログラムを見ていただければ「なるほど」と納得していただけると思います。
下はPRINT命令のプログラムです。
入力バッファの文字列を読み込んで、「PRINT」の文字列が検出されたあとの処理です。
アドレス0189にRST 1があります。
0192にも019Bにもそして01A9にもあります。
何をやっているのでしょう。
ここでは「PRINT」に続く文字をチェックしています。
最初は「;」(セミコロン、文字コード3B)をチェックしています。
次はCR(文字コード0D)のチェックです。
その次は「#」(文字コード23)のチェックです。
#は桁数指定で使われています。
そしてその次は「,」(カンマ、文字コード2C)のチェックです。
例として最初の0189のRST 1のところで何が行なわれるかを説明します。
RST 1の次のアドレスには「;」(セミコロン)の文字コード3Bがあります。
その次には06という数値が書かれています(ここが鍵です)。
さてRST 1が実行されました。
RST 1は1バイトのサブルーチンコール命令です。
その働きは通常のCALL命令と同じです。
RST 1がCALLされるとスタックのトップにはリターン先としてその次のアドレス(018A)が入れられます。
ここで上のRST 1プログラムの先頭で実行されるXTHLの意味が明らかになります。
つまりRST 1が実行されるとその次のメモリアドレスに置かれた文字コードが比較すべき文字コードとしてTSTCプログラムに取り込まれる仕組みなのです。
そして文字比較が一致したとします。
そのときはスタックトップの値が+2されてサブルーチンが終了すると上で説明しました。
RST 1がCALLされた時点ではサブルーチンのリターン先として、その次のアドレスがスタックトップに置かれました。
実はリターン先ではなくて、文字比較のための文字コードの格納アドレスでした。
そのアドレスがリターン時には+2されます。
するとプログラムカウンタには018Cが入ります。
つまり文字比較の結果一致した場合にはRST 1の次の2パイトがスキップされて、その次の018Cに書かれている命令が実行されることになります。
それではもし比較の結果不一致だったならば?
スタックトップの値(018A)が最初に+1されたあと(018B)、そのアドレスに置かれた値(06)が加算されてそれが新しいスタックトップの値になります(0192)。
そしてリターンしてくるとプログラムカウンタには0192が入り、そこからプログラムが続いて実行されます。
つまり文字比較を行なって一致したなら、文字コードと不一致のときにスキップするバイト数の2バイトの次に置かれた命令が実行され、不一致だった場合には一致したときに実行されるプログラム部分を全てスキップした先に置いた、次に処理すべきプログラムにジャンプするという仕掛けなのです。
マシン語プログラムに精通した者のみが書きうる実に巧妙なプログラムテクニックです。
華麗な技と言ってもよいかと思います。
本来はサブルーチンのリターン先として使われるスタックトップを比較のための文字コードのアドレスとしてちゃっかり利用しておいて、最後には本来のリターン先アドレスとして使いながら、そこでさらに任意のアドレスにジャンプさせてしまうという驚嘆すべきワザであります。
いまどきの言葉でしたら、まさに「神」プログラムでありましょう。
さすが!!!
であります。
復活!TINY BASIC[第14回]
2020.6.2upload
前へ
次へ
ホームページトップへ戻る