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

[第100回]

●RS232C受信プログラムにミスがありました

前回お見せしたBASICのRS232C受信プログラム(READ #命令)に、ミスがありました。
といって訂正したところで、なにやってるのかわかんないよー、ということなのでしょうけれど。
でも、間違いは間違いですので。

受信エラーが発生すると、SINERが実行されます。
前回のプログラムリストの終わりのところです。
下はエラーを修正したあとのリストです。

39E1 C1       SINER:POP BC;DUMMY =PC
39E2 C1       POP BC
39E3 D1       POP DE
39E4 E1       POP HL
39E5 77       LD (HL),A
39E6 23       INC HL
39E7 3600     LD (HL),00
39E9 3EEF     LD A,EF
39EB D398     OUT (98),A
39ED 3E49     ER49:LD A,49
39EF C33631   JP ERRDP

エントリした最初のPOP命令が、
POP AF
POP AF
になっていました。
その下のところで、
LD (HL),A
を実行しているのですが、実はこのAレジスタには、エラーが発生したときのエラーコードが入っているのです。
それがPOP AFで消されてしまっておりました。

動作確認のために、わざとエラーを発生させてみたところ、プログラムミスに気がつきました。
やっぱりテストしてみるべきなのです。
わざとエラーを発生させてみた、プログラムと実行結果です。

    10 ON ERROR GOTO 90
    20 PRINT "START"
    30 KETA%=0
    40 READ #1,RDATA$,KETA%
    50 IF KETA%<=0 GOTO 40
    60 PRINT RDATA$;
    70 IF RDATA$="END"THEN STOP 
    80 IF KETA%=40 GOTO 30 ELSE PRINT :GOTO 30
    90 PRINT "err line=";ERL,"err=";ERR,"232c err=";KETA%
>r.
START
err line=40  err=73       232c err=4

受信側のボーレートは9600ボーなのですが、そこにわざと2400ボーで送信してみました。
受信エラーが発生したときは、文字変数のバイト数を入れる整数型変数(上のプログラム例ではKETA%)に、エラー種別が入ります。232C err=4になっています。フレーミングエラーです。
ERLはエラーが発生した行番号、ERRはエラーコードが格納されるシステム変数です。
エラーコード73は232C受信エラーです。

●ND80ZVのLEDに05C0が表示されてしまうことについて(解決編です)

前回は飛び入りで横道にそれてしまいました。
[第98回]からの続きです。
ディップスイッチがSTEP側になっている状態で、リモート接続を終了すると、ND80ZVの7セグメントLEDに05C0xxxxと表示されてしまうことについて、すこし糸がほぐれてきました。
表示のされ方からすると、どうもアドレス05C0で割込みによってブレイクしているようなのです。

リモート接続を終了するときに、ND80ZVをソフトウェア的にリセットするために、[0][0][0][0][ADRSSET][RUN]のキーコードを送りますが、そこでEI命令が実行されて、割込み許可状態になってしまうことがわかりました。
しかし、LEDに表示される05C0はROMのアドレスですから、そこで割込みが発生してブレイクするというのはちょいとおかしい…。

と、最初は考えていたのですが、そこにも思い込みがありました。
ND80Zモニタのステップ、ブレイク動作(TK80モニタの動作も同じ)で表示されるアドレスはブレイクしたアドレスではなくて、ブレイクしたときに次に実行されるアドレスなのでした。
つまり05C0はまだ実行されてなくて、ブレイクしたのは、05C0の直前に実行されたアドレスだったのです。

0000番地にジャンプしたあとで、実行されるモニタプログラムの流れを調べてみました。
すると。
おお。
みつかったのです。
モニタプログラムの中でRAMアドレスを実行している部分が。

0866 21C005   NDMON3:LD HL,LEDDPA
0869 22CAFF         LD (RST6JA),HL
086C 211606   	LD HL,KEYINA
086F 22C7FF   	LD (RST5JA),HL
0872 215104   	LD HL,TK2RST1
0875 22BBFF   	LD (RST1JA),HL
              ;
0878 21D209   	LD HL,BREAK
087B 22CDFF   	LD (RST7JA),HL
087E 21CFFF   	LD HL,RMODE
0881 0629     	LD B,29
0883 AF       	XOR A
0884 77       	LD (HL),A
0885 23       	INC HL
0886 10FC     	DJNZ FC
0888 2100F8   	LD HL,USTOP
088B 22E2FF   	LD (SPL),HL
              ;
088E 3EFF     START1:LD A,FF
0890 D398     	OUT (98),A
0892 31B8FF   	LD SP,SPTOP
0895 CDC9FF         CALL LEDDP
0898 CDC6FF   START2:CALL KEYIN

ND80Zモニタプログラムのエントリ部分です。
アドレス0000からスタートしたあとは、ここへ来ます。
アドレス0895のCALL LEDDPのマシン語コードが、CDC9FFになっています。
FFC9番地をCALLしています。
RAMのアドレスです。
FFC9には何があるのでしょうか。

実は、上のリストの先頭部分、アドレス0866を見ますと
FFCAに05C0を入れています。
ここでは見えませんが、もう少し前のところで、FFC9にはC3を書いています。
つまり、RAMアドレスFFC9には、C3C005という命令が書かれていたのです。

なぜこのような面倒なことをしているかと言いますと、この部分(LED表示をする部分)が、リモート接続されたときは、LED表示をすると同時に、USB経由で表示データをWindowsパソコンに送るためのプログラムと置きかえることができるようにするためです。

これでやっと謎が解けました。
リモート接続を終了するときに、ND80ZVをソフトウェア的にリセットするために、[0][0][0][0][ADRSSET][RUN]のキーコードが送られ、そこでEI命令が実行されて、割込み許可状態になります。
しかし、0000番地からスタートしたあとは、ROMアドレスに書かれている命令を実行しますから、割込みは発生しません。
ところが上のリストのアドレス0895のCDC9FFが実行されると、次にRAMアドレスFFC9に書かれている命令、C3C005が実行されます。
その直後に割込みが発生して、その次に実行されるアドレス05C0が表示されることになったのです。

●RUNルーチンを直しました

原因がわかれば対策は立てられます。
しばらくどうするのがよいか考えていたのですが、最も簡単、easyな方法を思いつきました。
普通のRUN動作は、RAMアドレスにジャンプしたときにステップ動作や、ブレイク動作ができるように、EI命令を実行して、割込みが受付けられる状態にします。
そこのところを、アドレス0000に対するRUNのときだけ、逆にDI命令を実行して、割込みを禁止するようにすればよいはずです。
下がそのように追加を行ったプログラムリストです。

              ; RUN
09A6 2AEEFF     RUN:LD HL,(ADRSL)
09A9 22E0FF         LD (PCL),HL
09AC 7C       	LD A,H
09AD B5       	OR L
09AE F3       	DI
09AF CA0000   	JP Z,$0000
              ;
              ; CONTINUE
09B2 31D4FF    CONT:LD SP,LDSH
09B5 E1             POP HL
09B6 D1             POP DE
09B7 C1             POP BC
09B8 D9             EXX
09B9 F1             POP AF
09BA 08             EX AF,AF'
09BB FDE1           POP IY
09BD DDE1           POP IX
09BF 31E6FF         LD SP,EREG
09C2 D1             POP DE
09C3 C1             POP BC
09C4 F1             POP AF
09C5 ED7BE2FF       LD SP,(SPL)
09C9 2AE0FF         LD HL,(PCL)
09CC E5             PUSH HL
09CD 2AE4FF         LD HL,(LREG)
09D0 FB             EI
09D1 C9             RET
              ;

このように変更したところ、ディップスイッチがSTEP側のときに、リモート接続を終了しても、ND80ZVの7セグメントLEDには、STEP側にしていないときと同じように、00000000が表示されるようになりました。

めでたし、めでたし、と言いたいところなのですが、まだ問題が残っていました。

そうでした。
一番最初に、リモート接続してから、ディップスイッチをSTEP側にして、[8][0][0][0]と入力しようとしたところ、[8]を入力した直後に(多分)ブレイクしてレジスタダンプ表示が出たことについては、きちんと説明がつくのでしょうか。

今回は時間がなくなってしまいましたので、そのことにつきましては、次回に説明をすることにいたします。
[2011.7.6注記]元記事ではそのように書いているのですが、再編集するためにあらためて確認してみましたら、次回(CPUをつくろう![第612回])からはWindows7(64ビット)のふるまいについてのあれこれが始まってしまって、それどころではなくなってしまったらしく、どこまで先に進んでも今回の続きに相当するところがみつかりませんでした。
では一体本当のところ次回では何を書くつもりだったのか、なにしろ半年以上も前のことなので全く記憶にありません。
いずれ時間ができてじっくり読み直してみれば、何が書きたかったのかがわかるかもしれません。そうしたらまた追記しますので、いまのところは、ここは尻切れとんぼのままでご了承をお願いいたします。[注記ここまで]
CPUをつくろう!第611回(2010.9.15upload)を再編集

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

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