ワンボードマイコンをつくろう!(パソコンの原点はここから始まった)
TK80ソフトコンパチブル!8080、Z80マシン語からBASICまでこれ1台でこなせます
当記事は2009年11月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 2011.7.5
前へ
次へ
目次へ戻る
ホームページトップへ戻る
☆またもやトラブル発生
ND80ZVの説明書作業も大詰めを迎えて、あと一息で販売開始というところまできて、最後の動作確認をしていましたら、おかしなところが出て来てしまいました。

[第98回]

●どうやら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つは、ステップ回路にあります。
ステップ回路については、[第27回]の前後で説明をしています。
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を実行するところまでいってからブレイクする、というのは、やっぱりどこかがまだおかしい。
むむ。
そこには、まだ解明しなければならない謎が潜んでいるようです。

おお。こうなってきますと、本格推理小説みたいなもので、謎を解明するまで、止められません。
CPUをつくろう!第609回(2010.9.13upload)を再編集

ワンボードマイコンをつくろう![第98回]
2011.7.5upload

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