標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
やっと(!)MYCPU80の改良型基板製作に着手しました!!
[第851回]
●SHLD、LHLD、XTHL命令のテスト
SHLD、LHLD、XTHL命令のテストです。
SHLDはメモリアドレスを指定してそのアドレスとその次のアドレスにHLの値をSTOREする命令です。
LHLDはその逆の命令で、メモリの値をHLにLOADします。
XTHLはスタックトップにある2バイトのデータとHLレジスタの値を交換する命令です。
下のリストはSHLD、LHLD、XTHL命令のテストプログラムです。
0000 310000 LXI SP,0000 0003 010000 LXI B,0000 0006 110000 LXI D,0000 0009 3E00 MVI A,00 000B C5 PUSH B (8) 000C E3 XTHL (16) 000D 23 INX H (8)or(12) 000E 225000 SHLD 0050 (20) 0011 210000 LXI H,0000 (8) 0014 2A5000 LHLD 0050 (20) 0017 E3 XTHL (16) 0018 C1 POP B (8) 0019 1C INR E (8) 001A C20B00 JNZ 000B (12)or(8) 001D 14 INR D (8) 001E C20B00 JNZ 000B (12)or(8) 0021 3C INR A (8) 0022 C30B00 JMP 000B (12) |
BCレジスタとDEレジスタには初期値0000を入れます。
Aレジスタにも00を入れます。
PUSH B、POP Bは、XTHLの動作を確認するために使っています。
PUSH B命令の実行によって、スタックのトップにはBCレジスタの値が置かれます。
XTHLを実行すると、そのときにスタックトップにある2バイトのデータと、HLレジスタの値とが交換されます。
XTHL命令によって、スタックトップのデータ(実はBCレジスタの値と同じ)がHLレジスタに入り、代わりにHLレジスタの値がスタックに置かれます。
BCレジスタは変化しませんが、動作としては、BCとHLの値を交換したに近い動作になります。
ですから、HLの値は、実はBCの値と同じになっています。
そのHLの値を次のINX Hで+1します。
そしてSHLDとLHLDのテストのために、まずSHLD命令で、メモリの0050にHLの値をSTOREします。
その後に、LHLD命令で、メモリの0050から、ふただび値をHLレジスタに読み込みます。
そしてもう一度、XTHLを実行して、スタックトップのデータ(保存してあった、もともとのHLのデータ)と、現在のHLレジスタの値とを交換します。
ここまでの動作で、スタックトップの値(実はBCレジスタの値)が+1されたことになります。
そして最後に、POP Bで、スタックトップの値をBCレジスタに戻します。
結局、HLレジスタの値は変わることなく、BCレジスタの値だけが+1されたことになります。
実行時間を時計で計って、計算結果と比較できるように、以上の動作を1回実行するごとに、Eレジスタを+1します。
Eレジスタを+1した結果が00でなければ、000Bに戻って繰り返します。
結果が00のときは、Dレジスタを+1します。
Dレジスタを+1した結果が00でなければ000Bに戻って繰り返します。
Dレジスタを+1した結果が00のときは、Aレジスタを+1してから、000Bに戻って繰り返します。
上のリストの各命令の後ろの()内の数はその命令の実行クロック数です。
実行時間の計算については省略しますが(MYCPU80操作説明書では詳細な計算の説明をしています)、Aレジスタは約4秒ごとに+1されていきます。
下はプログラムを実行中の写真です。
●SPHL、PCHL命令のテスト
SPHL、PCHL命令のテストです。
SPHLはHLレジスタの値をSP(スタックポインタ)に転送する命令です。
PCHLはPC(プログラムカウンタ)にHLの値を転送します。PC(プログラムカウンタ)がHLの値になりますから、HLの値で示すアドレスにジャンプするという動作になります。
下のリストはSPHL、PCHL命令のテストプログラムです。
0000 3E00 MVI A,00 0002 47 MOV B,A 0003 4F MOV C,A 0004 57 MOV D,A 0005 5F MOV E,A 0006 210001 LXI H,$0100 0009 F9 SPHL (8) 000A E9 PCHL (8) 00FE 00 DB 00 00FF 00 DB 00 0100 3B DCX SP (8)or(12) 0101 3B DCX SP (8)or(12) 0102 F1 POP PSW (8) 0103 3C INR A (8) 0104 F5 PUSH PSW (8) 0105 C20901 JNZ $0109 (12)or(8) 0108 03 INX B (8)or(12) 0109 24 INR H (8) 010A E5 PUSH H (8) 010B 210900 LXI H,$0009 (8) 010E E3 XTHL (16) 010F C9 RET (8) 01FE 00 DB 00 01FF 00 DB 00 0200 3B DCX SP (8)or(12) 0201 3B DCX SP (8)or(12) 0202 F1 POP PSW (8) 0203 3C INR A (8) 0204 F5 PUSH PSW (8) 0205 C20902 JNZ $0209 (12)or(8) 0208 13 INX D (8)or(12) 0209 25 DCR H (8) 020A C30A01 JMP $010A (12) |
上のプログラムは2つの24ビットカウンタB、C、AとD、E、Aを交互にカウントアップさせる動作をします。
Aレジスタが共用されているため、スタックに値を退避します。
SPHLとPCHLを使って2組のプログラムと2組のスタックを使い分けています。
HLレジスタには初期値として0100を入れています。
この0100は「BCA」カウンタルーチンのエントリアドレスであるとともに、スタックポインタのアドレスでもあります。
次の命令、SPHLで、SP(スタックポインタ)に、この0100がセットされます。
そして、さらにその次の、PCHL命令によって、PC(プログラムカウンタ)にも同じ0100がセットされます。
PCの値が0100になりますから、つまり、これはJMP 0100が実行されるのと同じことです。
したがって、処理の流れは、0100に移ります。
0100と0101にはDCX SP命令があります。
DCX SPを2回実行しますから、SPの値は0100−2で00FEになります。
次にPOP PSWを実行します。
SP(スタックポインタ)に00FEをセットしておいて、POP PSWを実行することで、00FE〜00FFのメモリ内容がAレジスタとフラグレジスタに入れられます。
POP PSWのあと、INR Aを実行して、Aレジスタを+1(インクリメント)します。
そして、PUSH PSW命令で、+1したあとのAレジスタの値をまたスタックに保存します。
Aレジスタが256カウントされて、00になるたびに、その上位カウンタのBCレジスタを+1します。
次にINR Hを実行します。Hレジスタが+1されます。
HLレジスタには「BCA」カウンタルーチンを実行するために、そのエントリアドレスの0100が入っていました。
そのHレジスタが+1されるとHLレジスタの値は、0200になります。
0200はもうひとつのカウンタ「DEA」をインクリメントするためのルーチンのエントリアドレスです。
0200〜のメモリアドレスには、0100〜と同じ動作をするプログラム(対象になるレジスタだけが異なっている)が書かれています。
0100〜のプログラムを実行したあとで、次に実行するプログラムのエントリアドレスである0200をHLレジスタに入れた後、PUSH Hを実行し、最後にRETを実行します。
こうすることで、0200にジャンプしてもうひとつのカウンタルーチンが実行されることになります。
このようにして、0100〜のプログラムと0200〜のプログラムが交互に実行され、B、C、AレジスタとD、E、Aカウンタが交互にインクリメントされることを繰り返します。
上のリストの各命令の後ろの()内の数はその命令の実行クロック数です。
実行時間の計算については省略しますが(MYCPU80操作説明書では詳細な計算の説明をしています)、BおよびDレジスタは約8秒ごとに+1されていきます。
下はプログラムを実行中の写真です。
TTLでCPUをつくろう![第851回]
2018.2.25upload
前へ
次へ
ホームページトップへ戻る