[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第15回]
●最も基本的なサブルーチン(6)
TINY BASICの先頭部分185バイトのところに最も基本的なサブルーチンがまとめられています([第10回]参照)。
1バイトCALL命令RST 1〜RST 7によってCALLされるサブルーチンですがそのほかに普通のCALL命令によってCALLされるサブルーチンも2つ置かれています。
そのひとつは改行サブルーチンです([第11回])。
もうひとつが今回説明するTSTNUMサブルーチンです。
TSTNUM(TEST NUMBER)はASCIIコードで書かれた数字文字列を2進数(16進数)に変換します。
変換前の文字列は符号なし十進数に限ります。
2進数に変換後はHLレジスタに格納します。
このとき変換前の十進数の桁数がBレジスタに入れられます。
入力される文字列のアドレスはDEレジスタに入っています。
RST 5はDEレジスタで示されるメモリの値をチェックして最初に出現するブランク(スペース)ではない文字コードをAレジスタに入れるサブルーチンです([第12回])。
TN1:でAレジスタの値を30Hと比較してそれよりも小さければ数値ではないのでリターンします。
次に3AHと比較してそれと同じかそれよりも大きければ数値ではないのでリターンします。
0〜9の文字コードは30H〜39Hです。
0082から後ろが十進数を2進数に変換する部分です。
0082から0085でやっていることはちょっと説明が必要ですので後回しにします。
例として345という十進数を2進数(16進数)に変換する計算を考えてみます。
345はDEで示されるメモリに33、34、35の3バイトの文字コードとして入っています。
変換は最初に読み込まれる数(最上位桁の数)から下の桁に向かって順に1桁ずつ行なわれます。
最初は3ですからこれはそのままHLレジスタに入れます。
HLレジスタ=0003です(HLレジスタにはアドレス0077で0000が入れられています)。
その次の2桁目の数4をHLに入れる前に桁移動が必要です。
先に入れた3はただの3ではなくて実は300だからです。
いきなり3を300にするのではなくてまずは3X10を計算して10位の桁の数にします。
この計算は10進ではなくて16進の計算として行ないます。
8080には乗算命令はありませんから加算命令を使ってX10の計算を行ないます。
途中で必要になりますからHLの値をBCに保存しておきます。
HL=0003,BC=0003です。
それからDAD Hを実行します。
0003+0003、つまり0003X2=0006です。
結果はHL=0006になります。
もう一度DAD Hを実行します。
0006+0006=000Cです。
HL=000C、これで4倍になりました。
ここでDAD Bを実行します。
000C+0003=000Fです。
HL=000F、これで5倍になりました。
もう一度DAD Hを実行します。
000F+000F=001Eです。
HL=001Eになりました。
これで10倍の計算が行なわれたことになります。
確認してみましょう。
1EHは十進の30です。
確かに最初に入力した3は10倍されて、30になっています。
そこに2番目の数4を加算します。
十進では30+4=34です。
16進では001E+0004=0022です。
そしてそこに最後の3桁目の数の5を加算するために、前処理としてもう一度HLを10倍します。
計算の過程は省略しますので、上の説明を参考にして各自で計算して確かめてください。
34を10倍すると340です。
16進数では0154になります。
ここに5を加算します。
するとHL=0159になります。
159Hは十進の345です。
十進数の345が16進数に変換されました。
ここまでて説明した処理が007CのTN1:から009Cの間で行なわれています。
この過程でBCレジスタはワークレジスタとして使われますが、それと同時にBレジスタには十進数の桁数がカウントされて入れられます。
上で後回しにしたアドレス0082〜0085の説明です。
HLには変換後の16進数が格納されますがそれは0〜32767の範囲の数に限られます。
16進数では0000〜7FFFです。
アドレス0082〜0085は先に計算したHLの値を10倍する処理の直前に置かれています。
ここで何をしているのかといいますと、Hが0Fよりも大きくないことを確認しているのです(Hの上位4ビットが0000であることの確認)。
仮にHが10、Lが00だとすると、HL=1000H(4096)です。
10倍すると40960になって32767よりも大きくなってしまいます。
TINY BASICで扱える数を越えてしまいますからここでチェックをして、その場合にはHOW?表示ルーチンにジャンプします。
もっともここでのチェックは明らかにオーバーフローしてしまう数の事前チェックなので十分ではありません。
10倍後に下位桁の数を加算したあとでもう一度チェックをしています。
その加算は0090から0099で行なっています。
DEレジスタで示されるメモリから1桁分の数(文字コード30〜39)をAレジスタに入力して上位4ビットを0にして、計算できる数値0〜9にします。
実はこの文字が数値であることは最初のTN1:で確認済みです。
ちょっと考えるとそこでPUSH PSWを実行して保存すればよいのにそのようにしないで、0090でLDAX Dを実行しているのは二度手間のように思えますが、どうしてどうしてよく考えてあります。
PUSHしたものはPOPしなければ使えません。
2バイトを消費します。
0082でAレジスタが必要になったところでAレジスタをあっさりと捨ててしまい、あとであらためてLDAX Dを実行することで1バイト分のメモリを稼いでいます。
メモリが貴重であった時代には見事な判断でありましょう。
まるで達人の囲碁か将棋を見ているような気持ちになります。
さてそれで。
009CのJP TN1は”JMP”ではありません。
JPはJump if Positiveです。
0098のADC Hの結果を受けています(そこから後ろはJP命令までの間フラグを変化させる命令はありません)。
ADC Hの結果が正(プラスの数)ならばTN1にジャンプして次の桁の処理を続けます。
負(マイナスの数)ならばその下のHOW?表示ルーチンに行きます。
ここでオーバーフローの最終チェックが行なわれています。
Hの数が負ということはHLの値が8000〜FFFFということです。
いずれも0〜7FFF(0〜32767)の範囲を超える数です。
なお00A6から後ろには表示文字列(HOW?、OK、WHAT?、SORRY)が置かれています。
復活!TINY BASIC[第15回]
2020.6.4upload
前へ
次へ
ホームページトップへ戻る