標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第609回]
●どうやら05C0でブレイクしているらしい
ディップスイッチをSTEP側にしている状態で、リモート接続プログラムを終了すると、ND80ZVの7セグメントLEDに必ず表示されてしまう05C0xxxxというのは、表示のされかたから考えてみますと、どうもステップ動作(ブレイク動作)の結果表示されたアドレスのようです。
すると、その05C0というアドレスはND80ZVのモニタROMのアドレス、ということになります。
ND80ZVのROMには3つの異なるモニタプログラムが入っています。
そのうちの1番目は、0000〜3FFFの範囲にある、TK80モニタプログラムです。
その次のアドレス0400〜07FFの範囲には、TK80モニタプログラムと同じだけれど、ワークエリアのアドレスだけが83xxではなくて、FFxxになっているモニタプログラムがあります。
そして0800〜0FFFの範囲には、ND80Zモニタプログラムがあります。
ND80ZVのリモート接続動作は、このND80Zモニタプログラムの機能として組み込まれています。
そしてND80Zモニタプログラムは、キーボードや7セグメントLEDに対するアクセスや、プログラム、データのSAVE、LOADのような基本的な動作は、0400〜07FFの”TK80モニタプログラム”のサブルーチンをCALLしています。
●05C0にあるモニタプログラムのルーチン
05C0は、0400〜07FFの範囲にありますから、0400〜に移植された”TK80モニタプログラム”のアドレスです。
その部分のプログラムリストです。
; ; SEGMENT CONVERT SUB ; 05C0 21F4FF SEGCG:LXI H,DISP 05C3 11F8FF LXI D,DIG 05C6 01E905 LXI B,SEGD 05C9 7E SEGCG2:MOV A,M 05CA 23 INX H 05CB E5 PUSH H 05CC F5 PUSH PSW 05CD E6F0 ANI F0 05CF 0F RRC 05D0 0F RRC 05D1 0F RRC 05D2 0F RRC 05D3 2600 MVI H,00 05D5 6F MOV L,A 05D6 09 DAD B 05D7 7E MOV A,M 05D8 12 STAX D 05D9 13 INX D 05DA F1 POP PSW 05DB E60F ANI 0F 05DD 2600 MVI H,00 05DF 6F MOV L,A 05E0 09 DAD B 05E1 7E MOV A,M 05E2 12 STAX D 05E3 E1 POP H 05E4 1C INR E 05E5 C2C905 JNZ SEGCG2 05E8 C9 RET
これは7セグメントLEDに表示するアドレス、データ表示エリアの16進数データを7セグメントイメージに変換するルーチンです。
なぜ、こんなところでブレイクしてしまうのか、さっぱりわけがわかりませんでした。
ええ。
もちろん今ははっきりその理由はわかっております。
●ROMのプログラムではブレイクしないはず…
とにかくディップスイッチがSTEP側になっているときだけ、こういうことがおきる、ということから考えて、これはRST7割込みが関係していることに間違いはありません。
しかし。
それはありえないのです。
なぜなら、ブレイク、ステップ動作のためのRST7割込みはROMアドレスに対しては働かないようになっているはずだからです。
それには二重のガードがかかっています。
その1つは、ステップ回路にあります。
ステップ回路については、[第459回]の前後で説明をしています。
INT信号を発生させるためのフリップフロップ74HC74のクリア端子に、ROMselect信号を入れているために、ROMがアクセスされるとINT信号がクリアされてしまって、割込み信号が出ない仕組みになっています。
ですから、ROMのプログラムではブレイクするはずがないのです。
そしてもうひとつのガードは、ソフトウェア上の仕組みです。
RST7割込みは、INT信号が入力されただけでは受付けられません。
RST7割込みはマスク可能な割込みです。
Z80CPUはリセット後はINT信号による割込みは受付けられない状態になっています。
INT割込みを受付け可能にするためには、EI命令が実行される必要があります。
また、一度割込みが受付けられると、それ以後はやっぱり割込みは受付けられない状態になります。
ですから、リセット後、または割込みが受付けられたあとに、割込みが受付けられるようにするには、必ずEI命令が実行されなければなりません。
そのEI命令は、ND80Zモニタプログラムでは、ただ1箇所にしかありません。
; ; REGISTER RESTORE ; 05F9 2AE2FF RESRG:LHLD SSAVE 05FC F9 SPHL 05FD 2AE0FF LHLD PSAVE 0600 E5 PUSH H 0601 2AE4FF LHLD LSAVE 0604 E5 PUSH H 0605 2AEAFF LHLD FSAVE 0608 E5 PUSH H 0609 2AE8FF LHLD CSAVE 060C 4D MOV C,L 060D 44 MOV B,H 060E 2AE6FF LHLD ESAVE 0611 EB XCHG 0612 F1 POP PSW 0613 E1 POP H 0614 FB EI 0615 C9 RET
レジスタリストアルーチンの最後にだけ使われています。
これは何のルーチンかと言いますと、ブレイクしたときに、CPUレジスタの値を保存しておいたものを、もとのCPUレジスタに戻して、ユーザールーチンにリターンするルーチンです。
また[RUN]キーが押されたときに、ユーザープログラムにジャンプするときにも、このルーチンが実行されます。
EI命令はここでしか使われていませんから、ROMのプログラムを実行するときに、割込みが受付け可能になるはずはありません。
●INT信号の波形写真
しかし、現実に、ROMのアドレス05C0でブレイクしているらしい、ということになりますと、そのガードがいささか怪しくなってきてしまいます。
実は、最初のハード回路についてなのですが、ROMのモニタプログラムを実行中にもINT信号が出されているのです。
そのことはかなり以前から、オシロスコープでZ80のINT入力端子(pin16)を観測して確認しております。
こんな感じでしっかり出ています。
でもこのINT信号は受付けられないはずなのです。
いえ。EIの実行とは別の理由です。
ハード的なタイミングの理由からです。
しかし、現実にROMプログラムの実行中に割込みが受付けられてしまっているらしい、ということになりますと、このINT信号についても、一度しっかりと確認をしてみる必要があります。
その確認については、もう少し先のところですることにいたします。
●わかった!
仮にINT信号に問題があって、ROMのプログラムの実行中に、割込みが受付けられてしまうような信号が発生していた、としても、でもおかしい、ありえない、のですよねえ。
そもそもROMのプログラムはリモート接続の期間中ずっと実行されているのですから、よりによって、リモート接続が終了した途端に割込みが受付けられてブレイクしてしまう、というのは、どう考えてもおかしいのです。
そこは一番有り得ないタイミングだからです。
なぜなら、リモート接続が終了すると、強制的にND80ZVを0000番地から再スタートさせるために、[0][0][0][0][ADRSSET]「RUN]を送って、リスタートさせていますから、たとえ割込みが受付け可能状態になっていたとしても、そこでリスタートすることで、割込み禁止状態になってしまうからです…。
「………」
「!」
「△○□☆●■▽…!」(一時的な、錯乱状態です)
「わ。わ。わ。わかったぁ!」
わかりました。
やっと、謎の一部が解けました。
とんでもない思い違いをしておりました。
Z80CPUはリセットすると割込み禁止状態になります。
確かに、リモート接続を終了したときは、0000番地へのジャンプがソフト的に行われますが、それはハードウェアリセットではありませんから、割込み禁止にはならないのでした。
JP命令はCPUの状態に一切影響を与えません、でした。
そして、そして、おお、上でもさきほど書きました。
ROMのモニタプログラムではただ1箇所レジスタリストアルーチンの終わりでEI命令が実行され、そしてそのレジスタリストアルーチンは、[RUN]キーが押されたときに実行されるのでした!
そうだったのです。
リモート接続プログラムを終了するときに、[0][0][0][0][ADRSSET][RUN]というキーコードをND80ZVに送りますから、つまり、リモート接続を終了した直後は、EI命令が実行されるために、つねに割込みが受付け可能状態になっていたのです。
お。お。お。少し糸がほぐれてきました。
●しかしまだ謎が…
すると、やっぱり次はINT信号です。
むむ。
仮にROMをアクセスしているときにもINT信号が発生していたとしても、常にアドレス05C0でブレイクしてしまう、というのは、たまたま偶然なのだろうか?
それともなんらかの必然があるのだろうか?
そうすると、カギはZ80CPUがアドレス0000にジャンプしたあとの動きにある、ということになりそうです。
しかし。
それはやっぱりおかしい、のです。
確かに、やがて05C0は実行されることになりますが、0000番地からスタートしたあと、05C0のルーチンが実行されるまでには、かなりいろいろ初期設定の処理をやっていますから、その間にはブレイクしなくて、いつも05C0を実行するところまでいってからブレイクする、というのは、やっぱりどこかがまだおかしい。
むむ。
そこには、まだ解明しなければならない謎が潜んでいるようです。
おお。こうなってきますと、本格推理小説みたいなもので、謎を解明するまで、止められません。
2010.9.13upload
前へ
次へ
ホームページトップへ戻る