2020.8.16
前へ
次へ
ホームページトップへ戻る

[新連載]復活!TINY BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
すべてはここからはじまりました。
中日電工も。
40年前を振り返りつつ新連載です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜



[第67回]


●EXPR2

前回はEXPR3について説明をしました。
今回はそのひとつ上の階層のサブルーチン、EXPR2について説明をします。
EXPR2はEXPR3を+または−で複数つないだ構造をしています([第63回]参照)。
下がEXPR2のプログラムリストです。



EXPR2:の先頭でRST 1を実行します。
RST 1は[第11回][第14回]で説明しました。
DEで示されるメモリアドレスから1バイトのデータを読み込んでそれがスペース(20H)ならスペース以外のコードが出現するまで読み飛ばし、そのようにして読み込んだコードとRST 1の次に置かれたコードとを比較します。
アドレス0372には’2D’があります。
’2D’は’−’の文字コードです。
コードが一致した場合にはその次の1バイトも飛ばして2バイト先のアドレス0374に行きます。
一致しなかったときはその文字コードの次に置かれた数値の分だけアドレスが進みます。
’2D’の次には’06’が置かれています。
その次の6バイトが飛ばされます。
6バイト先の037Aに行きます。

コードが一致した場合に実行される0374ではLXI H,0Hが実行されます。
計算の最初に計算結果を格納するレジスタを0クリアしておきます。
そのあとJMP XP26で039Bにジャンプします。
039B XP26:PUSH H
から後ろは減算プログラムです。
それまでの計算結果をPUSH Hでスタックに保存します。
039C CALL EXPR3
039F CALL CHGSGN
03A2 JMP XP24
でEXPR3をCALLしその結果の値の正負をCHGSGNで反転させます。
そのあとXP24にジャンプします。
CHGSGNは[第48回]で説明をしました。
XP24:では加算を行ないます。
2番目の値の符号を反転させたうえで加算をしますから、結果としては減算を行なったことになります。

最初の EXPR2:のところで’−’ではなかった場合には037Aにジャンプします。
そこでもRST 1が実行されます。
その次の037Bに置かれた’2B’は’+’の文字コードです。
DEで示されるテキストエリアのメモリアドレスの値と比較して、一致すれば次のアドレス037Cが飛ばされて037Dに行きます。
不一致の場合には037Cの値の分だけアドレスが進みます。
037Cの値は00ですから、結局’+’があってもなくても同じアドレス037Dに行くことになります。
それは納得できることです。
037D XP22:CALL EXPR3
で最初の項が計算されます。
そのあと
0380 XP23:RST 1
で’+’を検出しています。
’+’があった場合には0383以後が実行されます。
’+’ではなかった場合には0382に置かれた15Hバイト分だけ飛ばされて0398にジャンプします。

0398 XP25:RST 1
では’−’の検出をしています。
’−’が検出された場合にはアドレス039BのXP26:PUSH H以後が実行されます。
XP26:は減算プログラムです。
XP26:は上のほうで説明をしています。
’+’でも’−’でもなかった場合にはアドレス039Aの86Hバイト分がジャンプされます。
039B+86=0421ですからアドレス0421にジャンプします。
0421は上のプログラムリストにはありません。
[第64回]で説明したEXPR4のプログラムにあります。
0421 XP42:RET
です。
演算子の’+’も’−’もなかった場合にはEXPR2としては計算終了ですからそこでリターンします。

’+’があった場合には
0383 PUSH H
でそれまでに計算した値をスタックに退避します。
そのあと
0384 CALL EXPR3
で次の項が計算されます。
続く0387のXP24:は最初に’−’があった場合の039B XP26:の処理からのジャンプ先でもあります。
0387 XP24:XCHG
0388 XTHL
で2番目の計算結果(最後に計算した値)をDEに置いて、それまでの計算結果をスタックからHLに戻します。
このときBASICテキストプログラムの位置アドレス(通常DEに入れられている)がスタックトップに移動します。

0389 MOV A,H
038A XRA D
038B MOV A,D
で2つの値の正負をサインフラグに記憶させたあと、一方の値の符号データとしてDレジスタの値をAレジスタに保存します。
このあたりがさすがに熟練の技だなあと感心してしまいます。
038C DAD D
038D POP D
038E JM XP23
で2つの値を加算したあとテキストエリアの位置アドレスをスタックからDEに戻します。
負だったときは(サインフラグが立っていたら)XP23にジャンプして計算処理を続けます。
ここでサインフラグをチェックしているのは、その上のDAD Dの結果ではありません。
DAD命令ではサインフラグは変化しません。
038A XRA D
の結果がここで確認されています。
いやあ、すごいです。
なかなかこんなプログラムは書けるものじゃありません。

その結果が負ということは2つの値の符号が異なっているということです。
ここでは結果のオーバーフローの確認をしているのです。
符号が異なる2値の加算ではオーバーフローは起きません。
なのでそのままXP23:にジャンプして次の計算を続けることになります。

XRA Dの結果が負ではなかった場合には次の
0391 XRA H
0392 JP XP23
0395 JMP QHOW
を実行します。
結果が負ではないということは、計算前の2値の符号が同じということです。
そして
038B MOV A,D
で保存した計算前の値と
XRA H
で計算後の値の符号を確認した結果、符号が変わっていなければオーバーフローではありませんから、XP23:にジャンプして計算を続けます。
加算前と加算後で符号が違っていたらオーバーフローが起きたことになりますからHOW?表示ルーチンにジャンプします。

復活!TINY BASIC[第67回]
2020.8.16upload

前へ
次へ
ホームページトップへ戻る