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

●ADI、ACI、SUI、SBIのテストプログラムです

テストプログラムの後ろに置いている比較データを簡単に作る方法について説明します、と前回書きましたが、先にもう1本テストプログラムを片付けてしまいましょう。
5本目のテストプログラムです。

前回のテストプログラム(TEST4)は、B〜AレジスタおよびMとAレジスタとの間で、ADD、ADC、SUB、SBBの各命令を実行するものでしたが、今回のTEST5は、Aレジスタと定数値との間で、ADI、ACI、SUI、SBIの各命令を実行するものです。
あらかじめ各レジスタに初期値を設定する代わりに、同じ定数値を使って計算しますから、結果は前回と全く同じになります。
ですから比較データも前回のTEST4と同じものを使います。


2009/6/12  13:56  TEST5.TXT
END=40D5
              ;;; MYCPU80 TEST5
              ;;; ADI ACI SUI SBI
              ;;; 09/6/12
              ;
                ORG $4000
              ;
                STCK=$5000
                MWK=$5001
                ERBF=$6000
              ;
4000 310050     LXI SP,STCK
4003 0E00       MVI C,00
4005 C5         PUSH B
4006 F1         POP PSW;CLEAR FLAG REGISTER
              ; 
              ; ADD
4007 3EDE       MVI A,DE
              ;
4009 C612       ADI 12;=F0  S,H,P
400B F5         PUSH PSW
400C C634       ADI 34;=124  P,C
400E F5         PUSH PSW
400F C656       ADI 56;=7A  
4011 F5         PUSH PSW
4012 C678       ADI 78;=F2  S,H
4014 F5         PUSH PSW
4015 C69A       ADI 9A;=18C  S,C
4017 F5         PUSH PSW
4018 C6BC       ADI BC;=148  H,P,C
401A F5         PUSH PSW
401B C648       ADI 48;=90  S,H,P
401D F5         PUSH PSW
401E C670       ADI 70;=100 Z,P,C
4020 F5         PUSH PSW
              ;ADC
4021 CE12       ACI 12;=13
4023 F5         PUSH PSW
4024 CE34       ACI 34;=47  P
4026 F5         PUSH PSW
4027 CE56       ACI 56;=9D  S
4029 F5         PUSH PSW
402A CE78       ACI 78;=115  H,C
402C F5         PUSH PSW
402D CE9A       ACI 9A;=B0  S,H
402F F5         PUSH PSW
4030 CEBC       ACI BC;=16C  P,C
4032 F5         PUSH PSW
4033 CE6C       ACI 6C;=D9  S,H
4035 F5         PUSH PSW
4036 CE27       ACI 27;=100 Z,H,P,C
4038 F5         PUSH PSW
              ;SUB
4039 D612       SUI 12;=EE  S,H,P,C
403B F5         PUSH PSW
403C D634       SUI 34;=BA  S
403E F5         PUSH PSW
403F D656       SUI 56;=64  
4041 F5         PUSH PSW
4042 D678       SUI 78;=EC  S,H,C
4044 F5         PUSH PSW
4045 D69A       SUI 9A;=52  
4047 F5         PUSH PSW
4048 D6BC       SUI BC;=96  S,H,P,C
404A F5         PUSH PSW
404B D696       SUI 96;=00  Z,P
404D F5         PUSH PSW
404E D656       SUI 56;=AA S,H,P,C
4050 F5         PUSH PSW
              ;SBB
4051 DE12       SBI 12;=97  S
4053 F5         PUSH PSW
4054 DE34       SBI 34;=63  
4056 F5         PUSH PSW
4057 DE56       SBI 56;=0D  H
4059 F5         PUSH PSW
405A DE78       SBI 78;=95  S,H,P,C
405C F5         PUSH PSW
405D DE9A       SBI 9A;=FA  S,H,P,C
405F F5         PUSH PSW
4060 DEBC       SBI BC;=3D  H
4062 F5         PUSH PSW
4063 DE3D       SBI 3D;=00  Z,P
4065 F5         PUSH PSW
4066 DE78       SBI 78;=88  S,H,P,C
4068 F5         PUSH PSW
              ;;;
              ; CHECK
4069 310060     LXI SP,ERBF
406C 210050     LXI H,STCK
406F 2B         DCX H
4070 11D540     LXI D,TBL1END
4073 0640       MVI B,40
4075 1A       LOOP0:LDAX D
4076 BE         CMP M
4077 CA7B40     JZ LOOP0_2
407A E5         PUSH H;ERR
407B 2B       LOOP0_2:DCX H
407C 1B         DCX D
407D 05         DCR B
407E C27540     JNZ LOOP0
4081 E5         PUSH H
4082 210000     LXI H,$0000
4085 E5         PUSH H
4086 76         HLT
              ;
              ;SUBROUTINE
4087 0612     MVI:MVI B,12
4089 0E34       MVI C,34
408B 1656       MVI D,56
408D 1E78       MVI E,78
408F 269A       MVI H,9A
4091 2EBC       MVI L,BC
4093 3EDE       MVI A,DE
4095 C9         RET
              ;
              ;COMPARE DATA TABLE
              ;SBB
4096 95         DB 95
4097 88         DB 88;M
4098 44         DB 44;
4099 00         DB 00;A-A
409A 10         DB 10
409B 3D         DB 3D;L
409C 95         DB 95
409D FA         DB FA;H
409E 85         DB 85
409F 95         DB 95;E
40A0 10         DB 10
40A1 0D         DB 0D;D
40A2 04         DB 04
40A3 63         DB 63;C
40A4 80         DB 80
40A5 97         DB 97;B
              ;SUB
40A6 95         DB 95
40A7 AA         DB AA;M
40A8 44         DB 44;
40A9 00         DB 00;A-A
40AA 95         DB 95
40AB 96         DB 96;L
40AC 00         DB 00
40AD 52         DB 52;H
40AE 91         DB 91
40AF EC         DB EC;E
40B0 00         DB 00
40B1 64         DB 64;D
40B2 80         DB 80
40B3 BA         DB BA;C
40B4 95         DB 95
40B5 EE         DB EE;B
              ;ADC
40B6 55         DB 55
40B7 00         DB 00;M
40B8 90         DB 90;
40B9 D9         DB D9;A+A
40BA 05         DB 05
40BB 6C         DB 6C;L
40BC 90         DB 90
40BD B0         DB B0;H
40BE 11         DB 11
40BF 15         DB 15;E
40C0 80         DB 80
40C1 9D         DB 9D;D
40C2 04         DB 04
40C3 47         DB 47;C
40C4 00         DB 00
40C5 13         DB 13;B
              ;ADD
40C6 45         DB 45
40C7 00         DB 00;M
40C8 94         DB 94;
40C9 90         DB 90;A+A
40CA 15         DB 15
40CB 48         DB 48;L
40CC 81         DB 81
40CD 8C         DB 8C;H
40CE 90         DB 90
40CF F2         DB F2;E
40D0 00         DB 00
40D1 7A         DB 7A;D
40D2 05         DB 05
40D3 24         DB 24;C
40D4 94         DB 94
40D5 F0       TBL1END:DB F0;B
              ;
ERBF         =6000  LOOP0        =4075  LOOP0_2      =407B  
MVI          =4087  MWK          =5001  STCK         =5000  
TBL1END      =40D5  

前回のTEST4をもとにして、必要なところを直しただけです。
MVIサブルーチンが残ったままですが、今回のプログラムでは使っていません。

テストプログラムの実行結果をUSB経由でパソコンに送りましたが、これも前回の結果と全く同じです。


●思いついてしまった、うまい方法とは?

たとえば今までのテストプログラムで説明をしますと、各命令を実行したあとで、スタックに保存した値と比較データとを比較する部分を取ってしまって、比較しないでそのまま終わるようなプログラムを、まず先に作ってしまうのです。
スタックには実行した結果が入っていますから、それをそのまま比較データとしてプログラムの最後に付け加えればテストプログラムの出来あがりです。

???…。

ですよねぇ。
それじゃ、テストにもなんにもなりません。
「つくるCPU」の回路でそれをやったんでは、その通りです。テストにはなりません。
そうではないのです。
Z80で実行するのです。

もうはるかな昔に8080のボードも、8080CPUそのものも、どこかへいってしまって手元には全く残っていません。
でもZ80のボードは、現役です。
ときどきご紹介しています、当社のBASICボード、ZBKボードはZ80互換CPUであるKL5C80A12を搭載しています。

それを使って先に実行させればよかったのですよ。
思いつくのがちょいと遅かったのですけれど、でも今からでもやるだけの価値は十分にあります。

Z80CPUはマシン語コードレベルでは8080互換ですから、バイナリファイルをロードしてそのまま実行させてもよいのですけれど、Z80についてはアセンブラだけではなくて逆アセンブラもありますから、バイナリファイルからザイログニーモニックのソースプログラムファイルを逆作成したうえで、目的にぴったりあったプログラムにしてから実行してみることにしました。

そうそう、よく考えてみましたら、比較データの作成のためだけではなくて、「つくるCPU」で実行したテストプログラムと同じ内容のプログラムをZ80で実行させてみて、同じ結果が得られれば、もう文句なし、の評価ができることになります。
ということは、すでにテストしたTEST1〜TEST5についても、Z80で試してみる価値はおおいにありそうです。

●逆アセンブラを使って生成したZ80用のテストプログラムです

ということで、比較コードの作成という目的からさらに発展して、Z80でもテストをしてみることになりました。
今回はちょうどTEST5のリストを上でお見せしていますので、作業例として、TEST5のバイナリファイルをもとにして、逆アセンブラでザイログニーモニックのソースファイルを逆作成して、それに手を加えたあとで、それをZ80アセンブラにかけたリストをお見せすることにします。
あ。このZ80逆アセンブラもZ80アセンブラもともに自作したものです。

逆アセンブラというのは、マシン語のファイル(バイナリファイル)を読み込んで、そのマシン語コードをアセンブラニーモニックに翻訳するプログラムのことです。8080のマシン語プログラムをZ80のニーモニックに翻訳することができます。
こんな調子です(一部コメントなど、あとから付け加えてあります)。


2009/6/13  11:51  TEST5Z.TXT
END=4181
              ; TEST5 FOR ZBK
              ;09/6/13
              ;from TEST5.BIN
              ;
                    ORG $4100
                    Z5000=$5000
                    Z6000=$6000
                    Z0000=$0000
                    Z9585=$9585
                    Z6400=$6400
                    Z8015=$8015
                    Z7A00=$7A00
                REENT=$1033
                PA=$F440
              ;
4100 310050         LD SP,Z5000
4103 0E00           LD C,00
4105 C5             PUSH BC
4106 F1             POP AF
4107 3EDE           LD A,DE
4109 C612           ADD A,12
410B F5             PUSH AF
410C C634           ADD A,34
410E F5             PUSH AF
410F C656           ADD A,56
4111 F5             PUSH AF
4112 C678           ADD A,78
4114 F5             PUSH AF
4115 C69A           ADD A,9A
4117 F5             PUSH AF
4118 C6BC           ADD A,BC
411A F5             PUSH AF
411B C648           ADD A,48
411D F5             PUSH AF
411E C670           ADD A,70
4120 F5             PUSH AF
4121 CE12           ADC A,12
4123 F5             PUSH AF
4124 CE34           ADC A,34
4126 F5             PUSH AF
4127 CE56           ADC A,56
4129 F5             PUSH AF
412A CE78           ADC A,78
412C F5             PUSH AF
412D CE9A           ADC A,9A
412F F5             PUSH AF
4130 CEBC           ADC A,BC
4132 F5             PUSH AF
4133 CE6C           ADC A,6C
4135 F5             PUSH AF
4136 CE27           ADC A,27
4138 F5             PUSH AF
4139 D612           SUB 12
413B F5             PUSH AF
413C D634           SUB 34
413E F5             PUSH AF
413F D656           SUB 56
4141 F5             PUSH AF
4142 D678           SUB 78
4144 F5             PUSH AF
4145 D69A           SUB 9A
4147 F5             PUSH AF
4148 D6BC           SUB BC
414A F5             PUSH AF
414B D696           SUB 96
414D F5             PUSH AF
414E D656           SUB 56
4150 F5             PUSH AF
4151 DE12           SBC A,12
4153 F5             PUSH AF
4154 DE34           SBC A,34
4156 F5             PUSH AF
4157 DE56           SBC A,56
4159 F5             PUSH AF
415A DE78           SBC A,78
415C F5             PUSH AF
415D DE9A           SBC A,9A
415F F5             PUSH AF
4160 DEBC           SBC A,BC
4162 F5             PUSH AF
4163 DE3D           SBC A,3D
4165 F5             PUSH AF
4166 DE78           SBC A,78
4168 F5             PUSH AF
4169 210000     LD HL,$0000
416C 39         ADD HL,SP
416D 2240F4     LD (PA),HL
4170 C33310     JP REENT
              ;
4173 0612           LD B,12
4175 0E34           LD C,34
4177 1656           LD D,56
4179 1E78           LD E,78
417B 269A           LD H,9A
417D 2EBC           LD L,BC
417F 3EDE           LD A,DE
4181 C9             RET
              ;
PA           =F440  REENT        =1033  Z0000        =0000  
Z5000        =5000  Z6000        =6000  Z6400        =6400  
Z7A00        =7A00  Z8015        =8015  Z9585        =9585  

●ZBKボード上で実行した結果です

上のプログラムをZBKボードで実行して、その結果を保存したスタックをメモリダンプして表示させてみました。



実はこれは、他のテストプログラムもZ80でテストするように書き直して順番にテストしているところの画面コピーです。
上でお見せしたTEST5Z.BINの前に、TEST4Z.BINも実行しています。

Z80は8080の命令を同じように実行しますが、フラグについては8080とは異なった結果になります。
S(サイン)、Z(ゼロ)、H(ハーフキャリー)、C(キャリー)フラグはZ80でも8080でも同じ結果になりますがP(パリティ)フラグは8080とZ80では命令によって異なった結果になります。
また8080では使われていなかったフラグビットがZ80では命令によってセット、リセットされるものがあります。

この結果の画面で、一番下の行の最後の16バイトは、上の方でお見せしたTEST5の結果をパソコンに転送した画面での最後の16バイトと同じはずなのですが、比べてみると、P(パリティ)フラグ(ビット2)が異なっていることがわかります。
いちいちリンクをクリックして戻って見比べるのはやっかいですから、比較しやすいように、最後の16バイトを抜き出してみます。
4500 9490 1548 818C 90F2 007A 0524 94F0

ブルーで着色したところは、パリティフラグ(ビット2)がセットされているところです。
ところが、赤で示したところは上のZ80の実行結果でもビット2がセットされているところです。
ADDやSUBなどの算術演算命令では、Z80の場合、ビット2はパリティフラグではなくて、オーバーフローフラグとして使われるのです。

後ろから4番目の(プログラムでは最初から4番目に実行した命令の結果です)90F2について見てみますと、計算の結果がF2でフラグが90です。
どんな計算かといいますと、A=7AのときにADD 78を実行しています。7A+78=F2です。
正数+正数=負数ですから、オーバーフローです。
Z80ではオーバーフローフラグがセットされますが、8080にはオーバーフローフラグはありませんから、もちろんパリティフラグとしてしか働きません。

1548についても見てみます。
ここは8C+BC=148という計算をしています。
負数+負数=正数ですから、オーバーフローです。

ついでに9490も見てみましょう。
ここは48+48=90という計算をしています。
正数+正数=負数ですから、オーバーフローです。

テストプログラムについてはまだ説明の途中ですが、実際には全部の命令についてのテストプログラムをZBKボードでも実行させてみて、ここで説明したような、特殊なフラグについての相違を除いては、その他の実行結果は全部ぴったり一致することを確認済みです。
2009.6.27upload

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