標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第256回]

●テストプログラムをつくりました

今までいくつかの命令回路を実装するたびに、それなりのテストプログラムを作って、正しく期待通りの動作をするかどうかをテストしてきました。
しかし、[第253回]で説明しましたように、とんでもないミスがあとから発見されたりすると、なんだか心配になってきてしまいます。
このまま基板を発注してしまって、基板が出来てきてしまってから、またとんでもないミスが発見されたりしたら、思いっきり後悔することになります。

じつは以前から、全ての命令をテストできるようなテストプログラムを作って、テストをしてみるべきだ、とは思っていました。
しかし、こういうプログラムはやたら面倒なだけで、面白くもなんともないのですよね。
で、場当たり的、細切れ的なテストプログラムをちょこちょこ作って適当にテストしただけできてしまいました。

でも、もういけません。
覚悟を決めて、全命令をテストするプログラムの作成にかかりました。

しかし、全命令をテストする、といっても、必ずしも1本のプログラムで全ての命令をテストしなければいけない、というものでもありません。
命令毎にプログラムを分けて作ってもよいわけです。
その方が作りやすい、と考えました。

●まず手始めに、MOV r,r’のテストプログラムです

まず手始めに、MOV r,r’の全ての命令をテストするプログラムを作りました。
これはやたら種類が多い命令です。
A、B、C、D、E、H、Lの7つのレジスタ間でのデータ転送命令ですから、MOV A,Aのように無意味な命令(NOPの代用には使えます)も含めると、7×7=49通りの命令があります。
これを全部テストすることにしました。

いろいろな考え方があると思いますが、これからあとのほかの命令をテストするプログラムにもできるだけ応用ができるように、テストの方法を決めました。
その命令の実行前のレジスタやフラグの状態を全部スタックに保存し、そして命令の実行後にも、また同じようにフラグやレジスタの値を保存します。
実際のプログラムでは、スタックはレジスタの値を一時保存するために使われますが、今回はテスト目的ですから、PUSH命令でスタックに保存した値は、必要な場合を除いては、POP命令で戻さず、どんどんスタックに蓄えていくだけにします。

そして最後に、スタックの値を順に読み出して、あらかじめプログラムのなかにチェックデータとして書いておいた値と比較します。
一致しなかったものがでてきたら、そのスタック位置を記録します。

作成したテストプログラム(ソースプログラム)は、[第180回]で作った8080アセンブラで、マシン語の命令コードに翻訳します。
おお。[第180回]を読みますと、ちゃんと、全命令をテストするプログラムを作らなければ、と書いておりますね。そのために、8080アセンブラも作りました、ですと。
もう、すっかり忘れておりました。

8080アセンブラで作成されるマシン語命令ファイルはバイナリファイルですけれど、バイナリファイルのままではRS232Cで「つくるCPU」の試作基板に送信することができません。
バイナリファイルと同時に、マシン語コードをASCII文字コードに置き換えたファイルも作成するようにしましたので、それを送信します。
「つくるCPU」にはUSBをRS232Cに変換するICを搭載することにしましたので、USBケーブルでパソコンと接続して、送信します。

送信プログラムも、Borland C++コンパイラで作ったものを使います([第189回])。

では、まず、MOV命令のテストプログラムのリストです。


2009/6/12  7:8  TEST1.TXT
END=40EB
              ;;; MYCPU80 TEST1
              ;;; MVI r,MOV r,r'
              ;;; 09/06/09 6/11 6/12
              ;
                ORG $4000
              ;
                STCK=$5000
                ERBF=$6000
              ;
4000 310050     LXI SP,STCK
4003 0E00       MVI C,00
4005 C5         PUSH B
4006 F1         POP PSW;CLEAR FLAG REGISTER
              ; 
              ; MVI
4007 CDA540     CALL MVI
400A C5         PUSH B
400B D5         PUSH D
400C E5         PUSH H
400D F5         PUSH PSW
              ;MOV r,r
400E 40         MOV B,B
400F 49         MOV C,C
4010 52         MOV D,D
4011 5B         MOV E,E
4012 64         MOV H,H
4013 6D         MOV L,L
4014 7F         MOV A,A
4015 C5         PUSH B
4016 D5         PUSH D
4017 E5         PUSH H
4018 F5         PUSH PSW
              ;MOV1
4019 41         MOV B,C
401A 4A         MOV C,D
401B 53         MOV D,E
401C 5C         MOV E,H
401D 65         MOV H,L
401E 6F         MOV L,A
401F 78         MOV A,B;=C
4020 C5         PUSH B
4021 D5         PUSH D
4022 E5         PUSH H
4023 F5         PUSH PSW
              ;MOV2
4024 CDA540     CALL MVI
4027 7D         MOV A,L
4028 6C         MOV L,H
4029 63         MOV H,E
402A 5A         MOV E,D
402B 51         MOV D,C
402C 48         MOV C,B
402D 47         MOV B,A;=L
402E C5         PUSH B
402F D5         PUSH D
4030 E5         PUSH H
4031 F5         PUSH PSW
              ;MOV3
4032 CDA540     CALL MVI
4035 68         MOV L,B
4036 42         MOV B,D
4037 54         MOV D,H
4038 67         MOV H,A
4039 79         MOV A,C
403A 4B         MOV C,E
403B 5D         MOV E,L;=B
403C C5         PUSH B
403D D5         PUSH D
403E E5         PUSH H
403F F5         PUSH PSW
              ;MOV4
4040 CDA540     CALL MVI
4043 5F         MOV E,A
4044 7A         MOV A,D
4045 55         MOV D,L
4046 69         MOV L,C
4047 4C         MOV C,H
4048 60         MOV H,B
4049 43         MOV B,E;=A
404A C5         PUSH B
404B D5         PUSH D
404C E5         PUSH H
404D F5         PUSH PSW
              ;MOV5
404E CDA540     CALL MVI
4051 61         MOV H,C
4052 4D         MOV C,L
4053 6A         MOV L,D
4054 57         MOV D,A
4055 7B         MOV A,E
4056 58         MOV E,B
4057 44         MOV B,H;=C
4058 C5         PUSH B
4059 D5         PUSH D
405A E5         PUSH H
405B F5         PUSH PSW
              ;MOV6
405C CDA540     CALL MVI
405F 50         MOV D,B
4060 45         MOV B,L
4061 6B         MOV L,E
4062 59         MOV E,C
4063 4F         MOV C,A
4064 7C         MOV A,H
4065 62         MOV H,D;=B
4066 C5         PUSH B
4067 D5         PUSH D
4068 E5         PUSH H
4069 F5         PUSH PSW
              ;;;
              ; CHECK MVI
406A 310060     LXI SP,ERBF
406D 210050     LXI H,STCK
4070 2B         DCX H
4071 11BB40     LXI D,TBL1END
4074 D5         PUSH D
4075 0608       MVI B,08
4077 1A       LOOP0:LDAX D
4078 BE         CMP M
4079 CA7D40     JZ LOOP0_2
407C E5         PUSH H;ERR
407D 2B       LOOP0_2:DCX H
407E 1B         DCX D
407F 05         DCR B
4080 C27740     JNZ LOOP0
4083 D1         POP D
              ;CHECK MOV
4084 0E07       MVI C,07
4086 0608     LOOP1:MVI B,08
4088 1A       LOOP2:LDAX D
4089 BE         CMP M
408A CA8E40     JZ LOOP2_2
408D E5         PUSH H;ERR
408E 2B       LOOP2_2:DCX H
408F 1B         DCX D
4090 05         DCR B
4091 C28840     JNZ LOOP2
4094 E5         PUSH H
4095 211000     LXI H,$0010
4098 19         DAD D
4099 EB         XCHG
409A E1         POP H
409B 0D         DCR C
409C C28640     JNZ LOOP1
409F E5         PUSH H
40A0 210000     LXI H,$0000
40A3 E5         PUSH H
40A4 76         HLT
              ;
              ;SUBROUTINE
40A5 0612     MVI:MVI B,12
40A7 0E34       MVI C,34
40A9 1656       MVI D,56
40AB 1E78       MVI E,78
40AD 269A       MVI H,9A
40AF 2EBC       MVI L,BC
40B1 3EDE       MVI A,DE
40B3 C9         RET
              ;
              ;COMPARE DATA TABLE
              ;MVI
40B4 00       TBL1:DB 00;F
40B5 DE         DB DE;A
40B6 BC         DB BC;L
40B7 9A         DB 9A;H
40B8 78         DB 78;E
40B9 56         DB 56;D
40BA 34         DB 34;C
40BB 12       TBL1END:DB 12;B
              ;MOV1
40BC 00         DB 00;F
40BD 34         DB 34;A
40BE DE         DB DE;L
40BF BC         DB BC;H
40C0 9A         DB 9A;E
40C1 78         DB 78;D
40C2 56         DB 56;C
40C3 34         DB 34;B
              ;MOV2
40C4 00         DB 00;F
40C5 BC         DB BC;A
40C6 9A         DB 9A;L
40C7 78         DB 78;H
40C8 56         DB 56;E
40C9 34         DB 34;D
40CA 12         DB 12;C
40CB BC         DB BC;B;
              ;MOV3
40CC 00         DB 00;F
40CD 34         DB 34;A
40CE 12         DB 12;L
40CF DE         DB DE;H
40D0 12         DB 12;E
40D1 9A         DB 9A;D
40D2 78         DB 78;C
40D3 56         DB 56;B
              ;MOV4
40D4 00         DB 00;F
40D5 56         DB 56;A
40D6 34         DB 34;L
40D7 12         DB 12;H
40D8 DE         DB DE;E
40D9 BC         DB BC;D
40DA 9A         DB 9A;C
40DB DE         DB DE;B;        
              ;MOV5
40DC 00         DB 00;F
40DD 78         DB 78;A
40DE 56         DB 56;L
40DF 34         DB 34;H
40E0 12         DB 12;E
40E1 DE         DB DE;D
40E2 BC         DB BC;C
40E3 34         DB 34;B
              ;MOV6
40E4 00         DB 00;F
40E5 9A         DB 9A;A
40E6 78         DB 78;L
40E7 12         DB 12;H
40E8 34         DB 34;E
40E9 12         DB 12;D
40EA DE         DB DE;C
40EB BC         DB BC;B;
              ;
ERBF         =6000  LOOP0        =4077  LOOP0_2      =407D  
LOOP1        =4086  LOOP2        =4088  LOOP2_2      =408E  
MVI          =40A5  STCK         =5000  TBL1         =40B4  
TBL1END      =40BB  

MOV r,r’命令のテストプログラムです、と書きましたが、MVIもついでにテストしてしまっていますね。
各レジスタに初期値を設定するためにMVI命令を使いますから、ついでにテストしてしまおう、と考えたようです。
もう、忘れてしまいました。

せっかくTK80が動くようになったのですから、プログラムのLOADから実行まで、TK80モニタのキー操作を利用することにします。
しかし最初は、テストプログラムそのものが正しく実行されているかどうかも確認したい、という考えから、プログラムの最後はHLTで終わるようにして、TK80モニタには戻らないようにしました。

比較データのテーブルは、後先をしっかり考えないで、いきなり作成してしまったために、比較する順序がちょっとちぐはぐな順番になってしまいました。
4084からのMOV命令の結果のチェックを行っている部分がちょいとややこしくなっているのはそのためです。

●テストプログラムを実行するところを写真に撮りました

[LOAD DATA]キーを押して、パソコンからUSB経由でテストプログラムをLOADしたところです。


[RUN]キーを押すと、あっという間に実行は完了し、HLTで停止しました。


リセットしてTK80モニタに戻ったあと、結果の確認です。


もしエラーがある場合には、そのエラーが記録されているスタックアドレス(4FFFから前)が、5FFFから前に順に記録されます。
つまりテスト結果の値を保存するためと、比較結果を保存するためとに、別々に2つのスタックを使用しています。
比較結果が完了した最後には、テスト結果の値を格納しているスタックアドレス(4XXX)のスタックエンドアドレスを5XXXからのスタックの最後に記録し、さらにその最後には0000を記録して終わります。
うーん。なんだか、ややこしいですねぇ。

写真を見ますと、5FFF、5FFEには4FBFが記録されていることがわかります。
[5][F][F][F][ADRSSET][READ DECR]と操作したところです。

続けて[READ DECR]を2回押しました。

0000が表示されました。
ということは、この前の値、4FBFがデータエンドで、そして結果の値とテーブルデータを比較した結果、不一致はなかったことがわかります。

テストプログラムを実行して、結果の値の比較まで行って、あらかじめ用意した比較用の値と全て一致したわけですから、もうこれでOKなのですけれど、せっかく命令を実際に実行した結果の値がスタックに記録されたことですし、TK80モニタの[STORE DATA]の機能も使えるようにしてあるはずですから、それを利用して、スタックの中身をパソコンに送ってファイルとして保存するようにしてみましょう。

[STORE DATA]のために、送信開始アドレスと終了アドレスをセットしたところです。

実行結果の値のスタックエンドは4FBFでしたから、実際に値が記録されているのは、その1つ前の4FC0から4FFFです。
このあと、[STORE DATA]キーを押せば、USB経由でパソコンにデータが送信されますが、その前にパソコン側で受信プログラムを起動させておく必要があります。

●USB(RS232C)の受信プログラムもBorland C++コンパイラで作ってしまいました

送信プログラムの逆の動作をする、RS232C受信プログラムも作ってしまいました。
R232.exeです。

R232.exeを実行して、「つくるCPU」からのデータを受信したところの様子です。

TEST1DT.HTXというファイル名で保存しています。
受信の様子をモニタできるように、受信データをそのまま(ASCIIコード)表示させています。
その下は受信完了後のTEST1DT.HTXをTYPEコマンドで表示させています。

TEST1DT.HTXはメモ帳(notepad)などで開くこともできますが、受信直後に同じDOSプロンプトの中ですぐに確認するにはTYPEコマンドに勝るものはありません。

いまどきほとんど忘れ去られてしまったみたいですけれど、DOSコマンドというのは、なかなかに便利なものなのですよ。

それはともかく。
いかが、でしょうか。
[STORE DATA]も使える、となると、ぐっと機能が充実したように思えませんでしょうか?

あ。R232.exeについても詳細をお伝えいたしましょうかねぇ。
でも、それはまた、後日。
2009.6.22upload

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