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

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



[第69回]


●EXPR(2)


前回からの続きです。
EXPRのエントリ部分はRST 3です、ということは前回説明しました。
最初にEXPR2をCALLしてその計算結果をスタックに保存したあとEXPR1にジャンプします。
下は前回もお見せしたEXPR1のプログラムリストです。



EXPR1:では関係演算子のテーブルを使って文字列を比較し、一致したらその関係演算子を処理するプログラム部分にジャンプします。
各処理プログラムでは先頭でXP18をCALLしています。
XP18:ではおかしなことをやっています。
というところまでで前回は終りました。
今回はその続きです。

035C XP18:MOV A,C

0361 MOV C,A

は何をやっているのか、はじめはわかりませんでしたが、しばらくしてやっと思い当たりました。
XP18:の中でBCレジスタを使うのですが(あとで説明します)、そのときCレジスタの値を一時的に退避させておくための処理です。
それはわかりますが問題はなぜCレジスタを退避させておく必要があるのかということです。
実はCレジスタはPRINT命令の中で数値を表示するときにその表示桁数を保持するのに使っています([第45回]参照)。
おそらくその値を壊してしまわないようにするのが目的だと思います。
Cレジスタは以下のプログラム部分でBCレジスタとして使うため、一時的にAレジスタを使って退避させているのです。

035D POP H
035E POP B
035F PUSH H
0360 PUSH B

ここでHLレジスタとBCレジスタを使っています。
何をやっているのでしょう?
この部分を実行すると、スタックトップの値(2バイトで1組)が入れ替わります。
なぜそうするのでしょうか?

最初にCALL EXPR2を実行してその結果の値をスタックに保存します。
その値とこのあとでCALLするEXPR2の値との間で比較演算を行ないます。
しかし最初は第1のEXPR2の値はスタックトップにありましたがXP18:の先頭ではスタックトップにはありません。
XP18:はサブルーチンなので、CALLされたときに戻り先のアドレスがスタックトップにPUSHされます。
そのためここで演算に使う最初のEXPR2の値はスタックトップではなくてスタックの2番目に押されてしまっています(!)。
そこでそれを入れ替えて、スタックトップにEXPR2の値を置き、その奥に戻り先アドレスを置くようにするのが上のプログラム部分の目的です。
なるほど。
でもなかなか思いつきませんよね。
スタックの使い方など手馴れたものです。
感心してしまいます。

そのように準備をしたうえで
0362 CALL EXPR2
を実行します。
その結果2番目のEXPR2の値がHLに入ります。
0365 XCHG
でHLとDEが入れ替わるため、DEに2番目のEXPR2の値が入ります。
そしてHLにはテキストプログラムの位置アドレス(もとはDEに入っていた)が入ります。
0366 XTHL
を実行すると上の035D〜0360のプログラムでスタックトップに持ってきておいた1番目のEXPR2の値がHLに入ります。
そして代わりにテキストプログラムの位置アドレスがスタックトップに置かれます。
いつもながらまるで手品を見ているような見事なプログラムです。

そのあと
0367 CALL CKHLDE
を実行します。
CKHLDEは[第48回]で説明しました。
HLとDEの比較を行ないます。
一致しているときはZフラグが立ちます。
HL<DEのときはキャリーフラグが立ちます。
このフラグがリターン後に利いてきます。

最後に
036A POP D
でテキストプログラムの位置アドレスをDEに戻します。
036B LXI H,0H
036E MVI A,1
でHLに0000を入れて、Aレジスタに01をセットして、メインルーチンにリターンします。
このHLとAもリターン後に活躍することになります。
ここのところも、実にうまいものだと感心してしまいます。

その見事な使い方については、次回にて説明をすることにします。

復活!TINY BASIC[第69回]
2020.8.19upload

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