Z80アセンブラプログラミング
 
   実行環境

メモリモニタ を利用します、 Z80は 図1 のように接続されています。 メモリモニタは BUSREQ でZ80とメモリを切り離します。 また RESET でZ80の初期化も行います。

 
図1:構成
FIG0.jpg(19734 byte)
 
   プログラムの作成

アセンブラでプログラムを作るのに次のフリーソフトのアセンブラが勧められます。

最終的にはプログラムをインテルへクスファイルにすればメモリモニタの HEXコマンド でメモリに展開できます。
CP/MのアセンブラでCOMファイルのときは バイナリファイル→HEXファイル変換ツール を使ってください。


 
   プログラムの実行

Z80は初期化すると0番地から実行を始めます。 そのときそこにプログラムがなければZ80は暴走してしまいます。 メモリモニタの HEXコマンド がメモリに書き込みしている間はメモリはZ80から切り離されていますが 書き込みが終わるとZ80に接続されます。
このときに暴走しているZ80にプログラムを壊される可能性があります。
CP/Mアダプタは 0〜100h番地F000〜FFFFh番地 を使いますが事前に EEPROM に書き込んでおけば電源投入後にはZ80ではCP/Mアダプタが実行されてい るので前期以外へのメモリ番地の書き込みは支障なく行えます。
CP/Mアダプタは GOコマンド を実装していますので GO 番地 とすれば番地で指定した位置にあるプログラムを実行できます。
プログラムは最後に 0番地 への分岐を実行すればCP/Mアダプタに実行を戻せます。

 
   プログラム
 
   メモリに書き込む
                ORG       100H
0100: 3E 55     LD        A,55H
0102: 32 00 80  LD        (8000H),A
0105: C3 00 00  JP        0
                END
 

レジスタに値を設置して直接番地を指定して書き込みます。



>D 8000
>8000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>8010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>8020 00 00 00 00 00 00 00 >
>
>GO 100
>CP/M ADAPTER Ver 0.1a
>D 8000
>8000 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>8010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>8020 00 00 00 00 00 00 00 >
>
 

プログラムの実行後の8000h番地に55hが書き込まれています。


 
   メモリを読み出す
               ORG       100H
0100: 3A 00 80 LD        A,(8000H)
0103: 32 01 80 LD        (8001H),A
0106: C3 00 00 JP        0
               END
 

先のプログラムで書き込んだ8000h番地の値を読み出して8001h番地に書き込みます。


>GO 100
>CP/M ADAPTER Ver 0.1a


>D 8000
8000 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8020 00 00 00 00 00 00 00 00 00 >
>
 

プログラムの実行後に8001h番地に8000h番地と同じ値が書き込まれています。



Z80では LD (メモリ),(メモリ) の命令はありません。

 
   IO操作

通信ポートを利用してIO操作のプログラムを作ってみます。 CNTP のビット1が1のときは送信中なのでこのビットが0のときに SENDP に送信データを書き込むとメモリモニタが送信してくれます。


FIG1.jpg(17965 byte)

IO操作も専用の INOUT の命令を使うだけでメモリ操作と似ています。


FIG2.jpg(15041 byte)

STRING から始まった文字列を1文字ずつ読み出して 0 で無ければ送信します、 0 なら文字列の終端に達したのでプログラムを終わらせます。


 
   システムコール

XASM でも CP/M のプログラムを作ることができます。 コンソールへ1文字を送るシステムコールを使って文字列を送るプログラムを書いてみます。 システムコールは次の手順で発行します。

FIG3.jpg(19040 byte)

FIG4.jpg(40968 byte)

FIG5.jpg(16834 byte)
 
   8ビット足し算

Z80は8ビットの加算の命令を持っています。 メモリにある2個の8ビットの値を加算して結果をメモリに書き込みます。 プログラムはメモリの値をレジスタに記憶してそのレジスタを加算する書き方にしました。 8ビット同士の加算結果は9ビットです、9ビット目は フラグレジスタC に記憶されます。

FIG6.jpg(19539 byte)

10進数で 1234 を加算しています。 結果は 202H 番地から書き込まれています。 フラグCは第0ビットですから9ビット目は 0 です。

FIG7.jpg(22163 byte)

NAを10進数で 255 にNBを 1 にして同プログラムを実行するとNA+NB=256ですが16進数では 100H になります。 赤枠 で示した部分がフラグの値ですがフラグ C1 になっています。

FIG8.jpg(36076 byte)
 
   16ビット足し算

Z80は16ビットの加算の命令を持っています。 メモリにある2個の16ビットの値を加算して結果をメモリに書き込みます。 プログラムはメモリの値をレジスタに記憶してそのレジスタを加算する書き方にしました。 16ビット同士の加算結果は17ビットです、17ビット目は フラグレジスタ の C に記憶されます。

FIG9.jpg(20393 byte)

10進数で 12345678 を加算しています。 結果は 204H 番地から書き込まれています。 フラグCは第0ビットですから17ビット目は 0 です。

FIG10.jpg(39408 byte)

NAを10進数で 65535 にNBを 1 にして同プログラムを実行するとNA+NB=65536ですが16進数では 10000H になります。 赤枠 で示した部分がフラグの値ですがフラグ C1 になっています。

 
   32ビット足し算

Z80は16ビットの加算命令を持っているので32ビットの加算においても16ビットの加算を2回行えば32ビットの計算ができます。 基本的にはいくらビット数が多いときでもそれに必要な計算を繰り返すことで結果は求められます。

FIG11.jpg(40586 byte)

12345678+87654321=99999999 は16進数で 5F5E0FFH になります。

FIG12.jpg(28413 byte)
 
   8ビット引き算

Z80は8ビットの減算の命令を持っています。 メモリにある2個の8ビットの値を減算して結果をメモリに書き込みます。 プログラムはメモリの値をレジスタに記憶してそのレジスタを減算する書き方にしました。 8ビット同士の減算結果は9ビットです、9ビット目は フラグレジスタC に記憶されます。

FIG13.jpg(19474 byte)

引き算は A-B の場合はBを補数にすると A+(-B) の計算と同じなので論理的にはBの補数を加算することになります。 フラグCの値は9ビット目が反転されたものですがAがBよりも小さくて桁借りがあったことを示します。

FIG14.jpg(26959 byte)
 
   16ビット引き算

Z80は16ビットの減算の命令を持っています。 メモリにある2個の16ビットの値を減算して結果をメモリに書き込みます。 プログラムはメモリの値をレジスタに記憶してそのレジスタを減算する書き方にしました。 16ビット同士の減算結果は17ビットです、17ビット目は フラグレジスタC に記憶されます。

FIG15.jpg(22009 byte)

FIG16.jpg(26305 byte)
 
   32ビット引き算

Z80は16ビットの減算命令を持っているので32ビットの減算においても16ビットの減算を2回行えば32ビットの計算ができます。 基本的にはいくらビット数が多いときでもそれに必要な計算を繰り返すことで結果は求められます。

FIG17.jpg(40539 byte)

87654321-12345678=75308643 は16進数で 47D1E63H になります。

FIG18.jpg(27011 byte)
 
   8ビット掛け算

Z80は乗算の命令を持っていませんので加算を繰り返して乗算の結果を得ます。 下のプログラムは筆算の計算手順と同じことを2進数で行っています。

FIG19.jpg(43861 byte)

12×34=408 は16進数で 198 です。

FIG20.jpg(27127 byte)
 
   16ビット掛け算

FIG21A.jpg(52012 byte)
FIG21B.jpg(9719 byte)

1234×5678=7006652 は16進数で 6AE9BC です。

FIG22.jpg(27042 byte)
 
   32ビット掛け算

FIG23A.jpg(42250 byte)
FIG23B.jpg(23565 byte)

12345678×87654321=1082152022374638 は16進数で 3D83626E2F8EE です。

FIG24.jpg(32378 byte)
 
   8ビット割り算

FIG25.jpg(33814 byte)

234÷12=19余り6 は16進数で 13H余り6H です。

FIG26.jpg(26480 byte)
 
   16ビット割り算

FIG27A.jpg(42830 byte)
FIG27B.jpg(1208 byte)

56789÷1234=46余り25 は16進数で 2EH余り19H です。

FIG28.jpg(26983 byte)
 
   32ビット割り算

FIG29A.jpg(43338 byte)
FIG29B.jpg(31040 byte)

987654321÷123456=8000余り6321 は16進数で 1F40H余り18B1H です。

FIG30.jpg(26719 byte)
 
   文字列受信

通信プログラムを端末として文字列を通信し改行までをメモリに蓄えるプログラムです。 文字列は SIZE で示した文字数を超えた場合は改行と同じくプログラムを終わらせます。 制御文字 では改行の 0DH と後退の 08H が使えます。

FIG31A.jpg(44435 byte)
FIG31B.jpg(25090 byte)

FIG32.jpg(33730 byte)
 
   10進数の文字列をBCDに変換

10進数の文字列の個数は2桁で1バイトに数値化するので偶数個にします。

FIG33.jpg(20731 byte)

FIG34.jpg(27538 byte)
 
   10進数の文字列を数値に変換

10進数の文字列を数値に変換します。 10進数なので文字コードは 0〜930H〜39H ですから 30H を引くと一桁の10進数の数値が取り出せます。 これを過去に取り出した分を10倍してから加算することを終了文字まで連続していくと数値化できます。
10倍するプログラムはサブルーチンにしました。 計算方法は 8倍+2倍=10倍 です8倍は上位に3ビットの移動した値で2倍は上位に1ビット移動した値です。

FIG35A.jpg(47391 byte)
FIG35B.jpg(54351 byte)

10進数の 123456 は16進数で 1E240H です。

FIG36.jpg(35996 byte)
 
   16進数の文字列を数値に変換

16進数の文字列を数値に変換します。 16進数は 0〜9A〜Fa〜f の文字を使いますこれ以外の文字があった場合はプログラムを終了します。 16進数の文字列の先頭から1文字ずつ数値化してこれを過去に取り出した分を16倍してから加算することを終了文字まで連続していくと数値化できます。 16倍は上位に4ビットの移動した値です。

FIG37A.jpg(41179 byte)
FIG37B.jpg(33892 byte)

FIG38.jpg(26395 byte)
 
   2進数の文字列を数値に変換

2進数の文字列を数値に変換します。 2進数は 01 の文字を使いますこれ以外の文字があった場合はプログラムを終了します。 2進数の文字列の先頭から1文字ずつ数値化してこれを過去に取り出した分を2倍してから加算することを終了文字まで連続していくと数値化できます。 2倍は上位に1ビットの移動した値です。

FIG39A.jpg(43712 byte)
FIG39B.jpg(14034 byte)

2進数の 10100101 は16進数で A5H です。

FIG40.jpg(26607 byte)
 
   数値を10進数の文字列に変換

数値を10で割って余りを文字化します、その除数を数値にして除数が0になるまで繰り返すと文字化できます。 プログラムでは文字化を完了後に送信してみました。

FIG41A.jpg(47528 byte)
FIG41B.jpg(64599 byte)
FIG41C.jpg(24362 byte)

FIG42.jpg(27231 byte)
 
   数値を16進数の文字列に変換

数値を16で割って余りを文字化します、その除数を数値にして除数が0になるまで繰り返すと文字化できます。 プログラムでは文字化を完了後に送信してみました。

FIG43A.jpg(45184 byte)
FIG43B.jpg(64654 byte)
FIG43C.jpg(29034 byte)

FIG44.jpg(22501 byte)
 
   数値を2進数の文字列に変換

数値を2で割って余りを文字化します、その除数を数値にして除数が0になるまで繰り返すと文字化できます。 プログラムでは文字化を完了後に送信してみました。

FIG45A.jpg(47925 byte)
FIG45B.jpg(36911 byte)

FIG46.jpg(28117 byte)
 
   数値を大きさで並び替える

11個のバイト値を比較して大きい方を下位の番地に入れ替えます。

FIG47.jpg(25548 byte)

FIG48.jpg(26450 byte)