ワンボードマイコンをつくろう!(パソコンの原点はここから始まった)
TK80ソフトコンパチブル!8080、Z80マシン語からBASICまでこれ1台でこなせます
当記事は2009年11月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 2011.7.7
前へ
次へ
目次へ戻る
ホームページトップへ戻る
☆ルート計算プログラム
ND80ZVをご購入いただいたお客様からTK−80応用プログラムを送っていただきました。
プログラムを解析する過程でND80ZV組立キットに附属しているZ80アセンブラ、Z80逆アセンブラを使います。それらのプログラムの使用例としても参考になると思います。

[第114回]

●ルート計算プログラム(TK−80応用プログラム)(その2)

ND80ZV組立キットをご購入いただいた北海道のM様から、TK−80応用プログラムを送っていただきました。
01〜99の範囲の整数のみですが、ルート(平方根)を求めるプログラムです。
前回はそのマシン語プログラムの16進コードをお見せしました。
戻って見ていただくのも面倒なことと思いますので下に再掲いたします。

>dm 8000,80b5
8000  06 0A 21 AC 82 AF 77 23-05 C2 06 80 CD 16 02 07  ..!ャ.ッw#.ツ..ヘ...
8010  07 07 07 21 AC 82 77 E5-CD 16 02 E1 86 77 7E 11  ...!ャ.w.ヘ....w~.
8020  F4 83 12 3E 01 32 B3 82-CD 70 80 DA 37 80 CD 90  ...>.2ウ.ヘp.レ7.ヘ.
8030  80 CD A0 80 C3 28 80 21-B4 82 06 02 11 F6 83 7E  .ヘ.テ(.!エ......~
8040  12 23 13 05 C2 3F 80 CD-C0 01 21 FA 83 11 F9 83  .#..ツ?.ヘタ.!.....
8050  1A 77 21 F9 83 11 F8 83-1A 77 21 FB 83 3E 48 77  .w!......w!..>Hw
8060  21 F8 83 3E 0E 77 21 FC-83 3E 80 B6 77 C3 00 80  !..>.w!..>.カwテ..
8070  21 B3 82 11 AF 82 06 04-AF 1A 9E 27 12 2B 1B 05  !ウ..ッ...ッ..'.+..
8080  C2 79 80 C9 00 00 00 00-00 00 00 00 00 00 00 00  ツy.ノ............
8090  21 B5 82 7E C6 01 27 77-2B 7E CE 00 27 77 C9 00  !オ.~ニ.'w+~ホ.'wノ.
80A0  06 03 21 B3 82 7E C6 02-27 77 17 E6 01 2B 86 27  ..!ウ.~ニ.'w...+.'
80B0  77 05 C2 AA 80 C9 66 6F-0E 00 CD 5D 10 CD 1B 10  w.ツェ.ノfo..ヘ].ヘ..

これじゃあ何がなんだかさっぱりわからんではないか、とお思いかも知れませんが、昔は大抵こんな感じだったのです。
もっとも右のASCIIダンプは余計です。
マシン語プログラムには無用なものです。
ZB3BASICのメモリダンプコマンドを利用しましたので、こういうリストになってしまいました。

昔はソースプログラムを入力してマシン語プログラムに翻訳してくれる便利なアセンブラなど一般には使うことはできませんでしたから、みんな16進コードを直接メモリに入力したのです。
プログラムを理解するためには、このままではちょっと困りますけれど、自分のマシン(この場合には当然のことながらTK−80)に入力するためには、これで十分です。
マシン語プログラムに慣れてきますと、16進コードを見ただけで、ある程度はプログラムが読めるようになってきます。
LD B,06
LD HL,$82AC
XOR A
LD (HL),A
INC HL
DEC B
JP NZ,$8006
という調子です。
あ…。
私の場合には、ずっと長い間Z80でしたから、やっぱりZ80ニーモニックが出てきてしまいます。
しかし、それじゃあいかにも原始的すぎます。
幸い今はアセンブラも逆アセンブラも使うことができますから、それを利用しない手はありません。
で、さっそくZ80逆アセンブラを使ってみました。
Z80逆アセンブラはND80ZV組立キットの付属ソフトウェアです。

M様から送っていただいたのは、バイナリファイルなのですがTK−80形式で先頭にアドレス情報4バイトがついていますから、そのままでは逆アセンブラにかけることができません。
Z80逆アセンブラにかけるには、普通のバイナリファイルでなければいけません。
最も簡単な方法はZB3BASICを利用する方法です。
ZB3BASICもND80ZV組立キットに付属しています。

まずND80ZVをTK80モードで起動して、USBケーブルを接続し、TK−80方式のバイナリファイル(BTKファイル)をLOADします。(プログラムを実行しなければ、ND80ZモードでLOADしても構いません)
次にリセットスイッチを押しながら、ディップスイッチを操作してND80Zモードにします。
パソコンのDOSプロンプト画面からZB3BASICを起動します。
ZB3BASICが起動したら、マシン語SAVEコマンドを使って、

/SV ROOT.BIN,8000,80B5

のように入力して、バイナリファイルを作成します。



あとは、そのようにして作成したバイナリファイルをZ80逆アセンブラにかけるだけです。
DOSプロンプトで

ZDAS ROOT.BIN,8000

と入力すると、逆アセンブルリストファイルが作成されます。



●ルート計算プログラムの逆アセンブルリストです

Z80逆アセンブラによって作成されたルート計算プログラムの逆アセンブルリストです。

8000 060A           LD B,0A
8002 21AC82         LD HL,$82AC
8005 AF             XOR A
8006 77             LD (HL),A
8007 23             INC HL
8008 05             DEC B
8009 C20680         JP NZ,$8006
800C CD1602         CALL $0216
800F 07             RLCA
8010 07             RLCA
8011 07             RLCA
8012 07             RLCA
8013 21AC82         LD HL,$82AC
8016 77             LD (HL),A
8017 E5             PUSH HL
8018 CD1602         CALL $0216
801B E1             POP HL
801C 86             ADD A,(HL)
801D 77             LD (HL),A
801E 7E             LD A,(HL)
801F 11F483         LD DE,$83F4
8022 12             LD (DE),A
8023 3E01           LD A,01
8025 32B382         LD ($82B3),A
8028 CD7080         CALL $8070
802B DA3780         JP C,$8037
802E CD9080         CALL $8090
8031 CDA080         CALL $80A0
8034 C32880         JP $8028
8037 21B482         LD HL,$82B4
803A 0602           LD B,02
803C 11F683         LD DE,$83F6
803F 7E             LD A,(HL)
8040 12             LD (DE),A
8041 23             INC HL
8042 13             INC DE
8043 05             DEC B
8044 C23F80         JP NZ,$803F
8047 CDC001         CALL $01C0
804A 21FA83         LD HL,$83FA
804D 11F983         LD DE,$83F9
8050 1A             LD A,(DE)
8051 77             LD (HL),A
8052 21F983         LD HL,$83F9
8055 11F883         LD DE,$83F8
8058 1A             LD A,(DE)
8059 77             LD (HL),A
805A 21FB83         LD HL,$83FB
805D 3E48           LD A,48
805F 77             LD (HL),A
8060 21F883         LD HL,$83F8
8063 3E0E           LD A,0E
8065 77             LD (HL),A
8066 21FC83         LD HL,$83FC
8069 3E80           LD A,80
806B B6             OR (HL)
806C 77             LD (HL),A
806D C30080         JP $8000
8070 21B382         LD HL,$82B3
8073 11AF82         LD DE,$82AF
8076 0604           LD B,04
8078 AF             XOR A
8079 1A             LD A,(DE)
807A 9E             SBC A,(HL)
807B 27             DAA
807C 12             LD (DE),A
807D 2B             DEC HL
807E 1B             DEC DE
807F 05             DEC B
8080 C27980         JP NZ,$8079
8083 C9             RET
8084 00             NOP
8085 00             NOP
8086 00             NOP
8087 00             NOP
8088 00             NOP
8089 00             NOP
808A 00             NOP
808B 00             NOP
808C 00             NOP
808D 00             NOP
808E 00             NOP
808F 00             NOP
8090 21B582         LD HL,$82B5
8093 7E             LD A,(HL)
8094 C601           ADD A,01
8096 27             DAA
8097 77             LD (HL),A
8098 2B             DEC HL
8099 7E             LD A,(HL)
809A CE00           ADC A,00
809C 27             DAA
809D 77             LD (HL),A
809E C9             RET
809F 00             NOP
80A0 0603           LD B,03
80A2 21B382         LD HL,$82B3
80A5 7E             LD A,(HL)
80A6 C602           ADD A,02
80A8 27             DAA
80A9 77             LD (HL),A
80AA 17             RLA
80AB E601           AND 01
80AD 2B             DEC HL
80AE 86             ADD A,(HL)
80AF 27             DAA
80B0 77             LD (HL),A
80B1 05             DEC B
80B2 C2AA80         JP NZ,$80AA
80B5 C9             RET

オリジナルは8080のプログラムなのですが、Z80は8080の命令をそのまま実行できます。
ですからマシン語コードは8080の命令のまま全て実行できるのですが、同じ命令コードでも8080とZ80とではニーモニック表現が異なります。
ND80ZV組立キットに付属している逆アセンブラはZ80用ですから、Z80ニーモニックに翻訳してしまいます。

それはそれとして、このリストのままでも16進コードだけに比べればはるかにわかりやすいのですけれど、でも、もう少しなんとかならないかなあ、という気がします。
実はZ80逆アセンブラは、このような逆アセンブルリストを作成するだけではなくて、そのままZ80アセンブラにかけられる、ソースプログラムファイルも同時に作成してしまうのです。

●同時に作成されたソースプログラムリストです

      ORG $8000
      Z82AC=$82AC
      Z0216=$0216
      Z83F4=$83F4
      Z82B3=$82B3
      Z82B4=$82B4
      Z83F6=$83F6
      Z01C0=$01C0
      Z83FA=$83FA
      Z83F9=$83F9
      Z83F8=$83F8
      Z83FB=$83FB
      Z83FC=$83FC
      Z82AF=$82AF
      Z82B5=$82B5
Z8000:LD B,0A
      LD HL,Z82AC
      XOR A
Z8006:LD (HL),A
      INC HL
      DEC B
      JP NZ,Z8006
      CALL Z0216
      RLCA
      RLCA
      RLCA
      RLCA
      LD HL,Z82AC
      LD (HL),A
      PUSH HL
      CALL Z0216
      POP HL
      ADD A,(HL)
      LD (HL),A
      LD A,(HL)
      LD DE,Z83F4
      LD (DE),A
      LD A,01
      LD (Z82B3),A
Z8028:CALL Z8070
      JP C,Z8037
      CALL Z8090
      CALL Z80A0
      JP Z8028
Z8037:LD HL,Z82B4
      LD B,02
      LD DE,Z83F6
Z803F:LD A,(HL)
      LD (DE),A
      INC HL
      INC DE
      DEC B
      JP NZ,Z803F
      CALL Z01C0
      LD HL,Z83FA
      LD DE,Z83F9
      LD A,(DE)
      LD (HL),A
      LD HL,Z83F9
      LD DE,Z83F8
      LD A,(DE)
      LD (HL),A
      LD HL,Z83FB
      LD A,48
      LD (HL),A
      LD HL,Z83F8
      LD A,0E
      LD (HL),A
      LD HL,Z83FC
      LD A,80
      OR (HL)
      LD (HL),A
      JP Z8000
Z8070:LD HL,Z82B3
      LD DE,Z82AF
      LD B,04
      XOR A
Z8079:LD A,(DE)
      SBC A,(HL)
      DAA
      LD (DE),A
      DEC HL
      DEC DE
      DEC B
      JP NZ,Z8079
      RET
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
Z8090:LD HL,Z82B5
      LD A,(HL)
      ADD A,01
      DAA
      LD (HL),A
      DEC HL
      LD A,(HL)
      ADC A,00
      DAA
      LD (HL),A
      RET
      NOP
Z80A0:LD B,03
      LD HL,Z82B3
      LD A,(HL)
      ADD A,02
      DAA
      LD (HL),A
Z80AA:RLA
      AND 01
      DEC HL
      ADD A,(HL)
      DAA
      LD (HL),A
      DEC B
      JP NZ,Z80AA
      RET

かなりプログラムらしくなってきました。
Z80逆アセンブラによって作成されたソースプログラムは、拡張子はDTXですが、中身はテキストファイルですからテキストエディタで編集することができます。

さっそく編集をしてみました。
編集作業の目的は、Z80逆アセンブラによって機械的につけられたラベル名を意味のあるラベル名に変更することです。
Z80逆アセンブラはプログラムの中で使っている変数や外部参照アドレスをプログラムの先頭にまとめて表示します。
そこを見れば、このプログラムで使っているワークエリアや外部サブルーチンのアドレスがわかります。

このプログラムでは、TK80モニタプログラムのサブルーチンを利用しています。
Z0216(アドレス0216)とZ01C0(アドレス01C0)です。
このようにZ80逆アセンブラはラベル名として、そのアドレスの前にZの文字をつけたものを生成します。
0216はキー入力ルーチン(KEYIN)です。
01C0はセグメント表示データ変換ルーチン(SEGCG)です。

またこのプログラムはTK80モニタプログラムのLED表示データエリアをアクセスしています。
83F4はLED表示用レジスタ1、83F6はLED表示用レジスタ3です。
それぞれLEDDP1、LEDDP3というラベルに変更します。

83F8〜83FCはLED桁表示レジスタ1〜5です。
それぞれLED1〜LED5に変更します。

このプログラムは計算用のワークエリアとして82AC〜82B5を使っているようです。
ここはプログラムの内容を解析しないと適切なラベル名はつけられません。
参照しているワークエリアのアドレスは、
82AC、82AF、82B3、82B4、82B5だけです。
仮にそれぞれ、DATA1、DATA4、DATA8、DATA9、DATA10としておきます。

Z80逆アセンブラはプログラム内でCALLしているサブルーチンやジャンプ先のアドレスにもラベルをつけて示します。
ここもプログラムを解析しないと意味の有るラベル名はつけられません。
ここはとりあえずは、そのままにしておくことにします。

ラベル名の変更はテキストエディタの文字列変換機能を使って一括変換をすれば簡単に置き換えることができます。

●編集したソースプログラムリストです

;;; root program for ND80Z3
; 2010/11/08
;
      ORG $8000
;
      SEGCG=$01C0
      KEYIN=$0216
;
      LEDDP1=$83F4
      LEDDP3=$83F6
;
      LED1=$83F8
      LED2=$83F9
      LED3=$83FA
      LED4=$83FB
      LED5=$83FC
;
      DATA1=$82AC
      DATA4=$82AF
      DATA8=$82B3
      DATA9=$82B4
      DATA10=$82B5
;
Z8000:LD B,0A
      LD HL,DATA1
      XOR A
Z8006:LD (HL),A
      INC HL
      DEC B
      JP NZ,Z8006
      CALL KEYIN
      RLCA
      RLCA
      RLCA
      RLCA
      LD HL,DATA1
      LD (HL),A
      PUSH HL
      CALL KEYIN
      POP HL
      ADD A,(HL)
      LD (HL),A
      LD A,(HL)
      LD DE,LEDDP1
      LD (DE),A
      LD A,01
      LD (DATA8),A
Z8028:CALL Z8070
      JP C,Z8037
      CALL Z8090
      CALL Z80A0
      JP Z8028
Z8037:LD HL,DATA9
      LD B,02
      LD DE,LEDDP3
Z803F:LD A,(HL)
      LD (DE),A
      INC HL
      INC DE
      DEC B
      JP NZ,Z803F
      CALL SEGCG
      LD HL,LED3
      LD DE,LED2
      LD A,(DE)
      LD (HL),A
      LD HL,LED2
      LD DE,LED1
      LD A,(DE)
      LD (HL),A
      LD HL,LED4
      LD A,48
      LD (HL),A
      LD HL,LED1
      LD A,0E
      LD (HL),A
      LD HL,LED5
      LD A,80
      OR (HL)
      LD (HL),A
      JP Z8000
Z8070:LD HL,DATA8
      LD DE,DATA4
      LD B,04
      XOR A
Z8079:LD A,(DE)
      SBC A,(HL)
      DAA
      LD (DE),A
      DEC HL
      DEC DE
      DEC B
      JP NZ,Z8079
      RET
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
Z8090:LD HL,DATA10
      LD A,(HL)
      ADD A,01
      DAA
      LD (HL),A
      DEC HL
      LD A,(HL)
      ADC A,00
      DAA
      LD (HL),A
      RET
      NOP
Z80A0:LD B,03
      LD HL,DATA8
      LD A,(HL)
      ADD A,02
      DAA
      LD (HL),A
Z80AA:RLA
      AND 01
      DEC HL
      ADD A,(HL)
      DAA
      LD (HL),A
      DEC B
      JP NZ,Z80AA
      RET

●編集したソースプログラムをZ80アセンブラにかけてみました

上のようにして編集作成したソースプログラムをZ80アセンブラにかけてみました。
Z80アセンブラもND80ZV組立キットに付属しています。
DOSプロンプトで
ZASM ROOT.TXT
と入力するだけです。
実に簡単です。



Z80アセンブラによって作成されたアセンブルリストです。

2010/11/8  23:33  root.txt
END=80B5
              ;;; root program for ND80Z3
              ; 2010/11/08
              ;
                    ORG $8000
              ;
                    SEGCG=$01C0
                    KEYIN=$0216
              ;
                    LEDDP1=$83F4
                    LEDDP3=$83F6
              ;
                    LED1=$83F8
                    LED2=$83F9
                    LED3=$83FA
                    LED4=$83FB
                    LED5=$83FC
              ;
                    DATA1=$82AC
                    DATA4=$82AF
                    DATA8=$82B3
                    DATA9=$82B4
                    DATA10=$82B5
              ;
8000 060A     Z8000:LD B,0A
8002 21AC82         LD HL,DATA1
8005 AF             XOR A
8006 77       Z8006:LD (HL),A
8007 23             INC HL
8008 05             DEC B
8009 C20680         JP NZ,Z8006
800C CD1602         CALL KEYIN
800F 07             RLCA
8010 07             RLCA
8011 07             RLCA
8012 07             RLCA
8013 21AC82         LD HL,DATA1
8016 77             LD (HL),A
8017 E5             PUSH HL
8018 CD1602         CALL KEYIN
801B E1             POP HL
801C 86             ADD A,(HL)
801D 77             LD (HL),A
801E 7E             LD A,(HL)
801F 11F483         LD DE,LEDDP1
8022 12             LD (DE),A
8023 3E01           LD A,01
8025 32B382         LD (DATA8),A
8028 CD7080   Z8028:CALL Z8070
802B DA3780         JP C,Z8037
802E CD9080         CALL Z8090
8031 CDA080         CALL Z80A0
8034 C32880         JP Z8028
8037 21B482   Z8037:LD HL,DATA9
803A 0602           LD B,02
803C 11F683         LD DE,LEDDP3
803F 7E       Z803F:LD A,(HL)
8040 12             LD (DE),A
8041 23             INC HL
8042 13             INC DE
8043 05             DEC B
8044 C23F80         JP NZ,Z803F
8047 CDC001         CALL SEGCG
804A 21FA83         LD HL,LED3
804D 11F983         LD DE,LED2
8050 1A             LD A,(DE)
8051 77             LD (HL),A
8052 21F983         LD HL,LED2
8055 11F883         LD DE,LED1
8058 1A             LD A,(DE)
8059 77             LD (HL),A
805A 21FB83         LD HL,LED4
805D 3E48           LD A,48
805F 77             LD (HL),A
8060 21F883         LD HL,LED1
8063 3E0E           LD A,0E
8065 77             LD (HL),A
8066 21FC83         LD HL,LED5
8069 3E80           LD A,80
806B B6             OR (HL)
806C 77             LD (HL),A
806D C30080         JP Z8000
8070 21B382   Z8070:LD HL,DATA8
8073 11AF82         LD DE,DATA4
8076 0604           LD B,04
8078 AF             XOR A
8079 1A       Z8079:LD A,(DE)
807A 9E             SBC A,(HL)
807B 27             DAA
807C 12             LD (DE),A
807D 2B             DEC HL
807E 1B             DEC DE
807F 05             DEC B
8080 C27980         JP NZ,Z8079
8083 C9             RET
8084 00             NOP
8085 00             NOP
8086 00             NOP
8087 00             NOP
8088 00             NOP
8089 00             NOP
808A 00             NOP
808B 00             NOP
808C 00             NOP
808D 00             NOP
808E 00             NOP
808F 00             NOP
8090 21B582   Z8090:LD HL,DATA10
8093 7E             LD A,(HL)
8094 C601           ADD A,01
8096 27             DAA
8097 77             LD (HL),A
8098 2B             DEC HL
8099 7E             LD A,(HL)
809A CE00           ADC A,00
809C 27             DAA
809D 77             LD (HL),A
809E C9             RET
809F 00             NOP
80A0 0603     Z80A0:LD B,03
80A2 21B382         LD HL,DATA8
80A5 7E             LD A,(HL)
80A6 C602           ADD A,02
80A8 27             DAA
80A9 77             LD (HL),A
80AA 17       Z80AA:RLA
80AB E601           AND 01
80AD 2B             DEC HL
80AE 86             ADD A,(HL)
80AF 27             DAA
80B0 77             LD (HL),A
80B1 05             DEC B
80B2 C2AA80         JP NZ,Z80AA
80B5 C9             RET
DATA1        =82AC  DATA10       =82B5  DATA4        =82AF  
DATA8        =82B3  DATA9        =82B4  KEYIN        =0216  
LED1         =83F8  LED2         =83F9  LED3         =83FA  
LED4         =83FB  LED5         =83FC  LEDDP1       =83F4  
LEDDP3       =83F6  SEGCG        =01C0  Z8000        =8000  
Z8006        =8006  Z8028        =8028  Z8037        =8037  
Z803F        =803F  Z8070        =8070  Z8079        =8079  
Z8090        =8090  Z80A0        =80A0  Z80AA        =80AA  

いかがでしょう。
これなら、何をやっているか、読めるような気がしませんでしょうか?
CPUをつくろう!第655回(2010.11.8upload)を再編集

ワンボードマイコンをつくろう![第114回]
2011.7.7upload

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