標準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
前へ
次へ
ホームページトップへ戻る