標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第564回]
●ZDAS.COM(Z80逆アセンブラ)
[第558回]で8080アセンブラを改良しました、という説明を致しました。
8080アセンブラはMYCPU80組立キットのために新しく作ったアセンブラです。
ND80ZVのCPUはZ80ですが、Z80はマシン語コードレベルでは8080の命令をそのまま実行できますから、8080アセンブラも利用することは可能です。
ND80ZVは、TK80と同じ動作をさせるためのTK80モニタプログラムを実装しています。
その昔のTK80のために書かれたプログラムなどを参考にしてプログラムを作ってみたい、という場合などですと、そこで書かれているのは8080ニーモニックのプログラムのはずですから、8080アセンブラが使えると便利です。
しかし8080アセンブラではZ80固有の命令を使うことはできません。
ND80ZVはTK80モニタプログラムのほかに、ND80Zモニタプログラムも搭載しています。こちらはZ80CPUのためのモニタプログラムです。
Z80CPUの機能を有効に使うにはやっぱりZ80アセンブラが必要です。
というわけで、ND80ZV組立キットには附属ソフトウェアとして、8080アセンブラとZ80アセンブラの両方をCDROMで供給する予定です。
[第558回]では8080アセンブラについて説明を致しましたけれど、Z80アセンブラについてもご説明申し上げなくては片手落ちということになってしまいます。
そこで今回はZ80アセンブラについての説明、ということになるのですが、それについてはちょいとした趣向を考えました。
で、見出しの「Z80逆アセンブラ」について、まず先に説明をすることになります。
普通のアセンブラというのは、プログラムを人間が理解しやすいニーモニック命令で書いたものを、CPUが実行できるマシン語コードに翻訳するプログラムのことをいいます。
逆アセンブラというのは、その名前の通り、アセンブラの逆の働きをするプログラムです。
マシン語のプログラムを読み込んで、ニーモニック表現のプログラムに翻訳します。
たとえばソースプログラムが無くなってしまったがマシン語のプログラムだけは残っている、とかあるいはどなたか他の方が書かれたプログラムなのでマシン語のプログラムしかないけれども、それをなんとか解読してみたい、というような場合に、これがあると便利です。
Z80逆アセンブラですから、Z80のマシン語プログラムからZ80のニーモニックで書かれたソースプログラムを逆作成することができます。
プログラム名は、ZDAS.COMです。
このZDAS.COMもND80ZVの附属ソフトウェアとしてCDROMに入れて供給する予定です。
Z80逆アセンブラで何を始めるつもりなのでしょう?
実はちょいと面白いことを思いつきましたので、それをやってみよう、というわけです。
そのためにはちょいと前準備が必要です。
新しいフォルダを作って、そこにsound6.binをコピーして持ってきます。
sound6.binは[第558回]で8080アセンブラを使ってアセンブルして作ったマシン語のファイル(バイナリファイル)です。
新しいフォルダzdastestには、sound6.binしか入っていません。
dirコマンドでフォルダにあるファイルを表示させています。
そのsound6.binに対してzdas.comを実行しました。
zdas sound6.bin[Enter]と入力すると、
ENDと表示されました。
[第559回]で8080アセンブラ注記として書きましたように、8080アセンブラもZ80アセンブラも、そしてこのZ80逆アセンブラもWindowsパソコンのDOSプロンプトで実行しますが、Z80BASICと違って、ND80ZVをUSBで接続しておく必要はありません。
Z80BASICはND80ZVの上でZ80CPUがプログラムを実行しますから、USBでWindowsパソコンとND80ZVを接続しておく必要があるのですが、アセンブラや逆アセンブラはただの翻訳プログラムですから、パソコンの中だけで処理を行います。
zdas.comを実行した結果、どのようなファイルが作られたのか確認してみましょう。
さきほどと同じようにdirコマンドで確かめてみると、新たに、sound6.dtxとsound6.dlsという2つのファイルが作成されています。
それぞれのファイルの中身を見てみましょう。
まずは、sound6.dtxです。
ORG $0000 Z0247=$0247 Z8000=$8000 Z800E=$800E Z803F=$803F Z801F=$801F Z802D=$802D Z801A=$801A Z2C2F=$2C2F Z384B=$384B Z3720=$3720 CALL Z0247 INC A JP Z,Z8000 DEC A CALL Z800E JP Z8000 PUSH AF PUSH HL PUSH DE PUSH BC LD HL,Z803F ADD A,L LD L,A LD B,(HL) LD E,1A LD D,B LD A,EF OUT (98),A PUSH HL PUSH HL POP HL POP HL NOP DEC D JP NZ,Z801F LD D,B LD A,CF OUT (98),A PUSH HL PUSH HL POP HL POP HL NOP DEC D JP NZ,Z802D DEC E JP NZ,Z801A POP BC POP DE POP HL POP AF RET LD A,A LD (HL),A LD (HL),C LD L,D LD E,A LD E,C LD D,H LD C,A LD B,A LD B,E CCF DEC SP DEC (HL) LD (Z2C2F),A DEC H DAA LD HL,(Z384B) LD H,H INC HL LD HL,Z3720
このZDAS.COMはかなり以前に作ったソフトで、早い話が、使えればそれでよい、というモロ実用本位で作ったものですから、タイトルの表示もタイムスタンプもまるでありません。
でもしっかりとZ80ニーモニックに翻訳しています。
ところで、上にも書きましたように、このsound6.binは、8080ニーモニックで書いたソースプログラムを8080アセンブラでマシン語に翻訳して作ったバイナリファイルだったはずでした([第558回])。
そうなのです。
8080のためのマシン語プログラムは、このようにZ80逆アセンブラを使うことで、Z80ニーモニックのソースプログラムに変換してしまうことができるのです。
このsound6.dtxは、このままZ80アセンブラにかけることができるソースプログラムになっています。
拡張子はzdasで作成したソースプログラム(txt)という意味でdtxにしてあります。
ソースプログラムはこのような形になりますが、もとのマシン語コードに対応した形のリストもあると、プログラムがより理解しやすくなります。
sound6.dlsの中身です。
0000 CD4702 CALL $0247 0003 3C INC A 0004 CA0080 JP Z,$8000 0007 3D DEC A 0008 CD0E80 CALL $800E 000B C30080 JP $8000 000E F5 PUSH AF 000F E5 PUSH HL 0010 D5 PUSH DE 0011 C5 PUSH BC 0012 213F80 LD HL,$803F 0015 85 ADD A,L 0016 6F LD L,A 0017 46 LD B,(HL) 0018 1E1A LD E,1A 001A 50 LD D,B 001B 3EEF LD A,EF 001D D398 OUT (98),A 001F E5 PUSH HL 0020 E5 PUSH HL 0021 E1 POP HL 0022 E1 POP HL 0023 00 NOP 0024 15 DEC D 0025 C21F80 JP NZ,$801F 0028 50 LD D,B 0029 3ECF LD A,CF 002B D398 OUT (98),A 002D E5 PUSH HL 002E E5 PUSH HL 002F E1 POP HL 0030 E1 POP HL 0031 00 NOP 0032 15 DEC D 0033 C22D80 JP NZ,$802D 0036 1D DEC E 0037 C21A80 JP NZ,$801A 003A C1 POP BC 003B D1 POP DE 003C E1 POP HL 003D F1 POP AF 003E C9 RET 003F 7F LD A,A 0040 77 LD (HL),A 0041 71 LD (HL),C 0042 6A LD L,D 0043 5F LD E,A 0044 59 LD E,C 0045 54 LD D,H 0046 4F LD C,A 0047 47 LD B,A 0048 43 LD B,E 0049 3F CCF 004A 3B DEC SP 004B 35 DEC (HL) 004C 322F2C LD ($2C2F),A 004F 25 DEC H 0050 27 DAA 0051 2A4B38 LD HL,($384B) 0054 64 LD H,H 0055 23 INC HL 0056 212037 LD HL,$3720
拡張子は、zdasで作られたリストファイル(lst)の意味で、dlsにしました。
では念の為に、8080アセンブラで作られた、sound6.lstと比較してみましょう。
そのリストは[第558回]にありますが、下に再掲いたします。
sound6.lstです。
2010/7/20 21:25 sound6.txt END=8056 ;;;SOUND6.TXT ;;; sound for ND80Z3 clock=6MHz ;;; 10/3/18 10/6/15 7/20 ;;; ORG $8000 ; KEY=$0247 ; 8000 CD4702 SND:CALL KEY 8003 3C INR A 8004 CA0080 JZ SND 8007 3D DCR A 8008 CD0E80 CALL SNDSB 800B C30080 JMP SND ; 800E F5 SNDSB:PUSH PSW 800F E5 PUSH H 8010 D5 PUSH D 8011 C5 PUSH B 8012 213F80 LXI H,SNDTBL 8015 85 ADD L 8016 6F MOV L,A 8017 46 MOV B,M 8018 1E1A MVI E,1A 801A 50 SNDS1:MOV D,B 801B 3EEF MVI A,EF;sp out=H,DMAoff 801D D398 OUT 98 801F E5 SNDS2:PUSH H;11--------- 8020 E5 PUSH H;11 | 11+11+10+10+4+4+10=60 8021 E1 POP H;10 | 60/6=10 8022 E1 POP H;10 | 8023 00 NOP;4; | 10microsec 8024 15 DCR D;4 | 8025 C21F80 JNZ SNDS2;10---- 8028 50 MOV D,B 8029 3ECF MVI A,CF;sp out=L,DMAoff 802B D398 OUT 98 802D E5 SNDS3:PUSH H;11--------- 802E E5 PUSH H;11 | 11+11+10+10+4+4+10=60 802F E1 POP H;10 | 60/6=10 8030 E1 POP H;10 | 8031 00 NOP;4; | 10microsec 8032 15 DCR D;4 | 8033 C22D80 JNZ SNDS3;10---- 8036 1D DCR E 8037 C21A80 JNZ SNDS1 803A C1 POP B 803B D1 POP D 803C E1 POP H 803D F1 POP PSW 803E C9 RET ; ; SOUND TABLE 803F 7F SNDTBL:DB 7F;so4 8040 77 DB 77;so#4 8041 71 DB 71;ra4 8042 6A DB 6A;ra#4 8043 5F DB 5F;do5 8044 59 DB 59;do#5 8045 54 DB 54;re5 8046 4F DB 4F;re#5 8047 47 DB 47;fa5 8048 43 DB 43;fa#5 8049 3F DB 3F;so5 804A 3B DB 3B;so#5 804B 35 DB 35;ra#5 804C 32 DB 32;si5 804D 2F DB 2F;do6 804E 2C DB 2C;do#6 804F 25 DB 25;mi6 8050 27 DB 27;re#6 8051 2A DB 2A;re6 8052 4B DB 4B;mi5 8053 38 DB 38;ra5 8054 64 DB 64;si4 8055 23 DB 23;fa6 8056 21 DB 21;fa#6 ;END KEY =0247 SND =8000 SNDS1 =801A SNDS2 =801F SNDS3 =802D SNDSB =800E SNDTBL =803F
リストが長いので、比較しづらいかも知れませんが、よく見ていただきますと、どこかがおかしいことに気が付きませんでしょうか?
そうです。
オリジナルのプログラムは、アドレスが8000番地からはじまっています。
ところがそのプログラムをもとにして逆作成したプログラムリストのアドレスは0000からはじまっています。
これでは使い物になりません(じつは、そんなことはないのですけれど…。それについては、のちほど説明いたします)。
逆アセンブラには、人間が判断して加えてやらなければならない情報があるのです。
それがアドレスの情報です。
asm80.com(8080アセンブラ)やzasm.com(z80アセンブラ)で作られるバイナリファイルには、それがどのアドレスにloadされるべきかというアドレスの情報は含まれていません。
TK80モニタプログラムのLOAD、STOREで扱うシリアル入出力ファイルは、プログラムの先頭にそのアドレス情報が含まれています。
ND80ZVはその機能も使いますから、asm80.comやzasm.comではTK80モニタプログラムのためのバイナリファイルとして、通常のバイナリファイルの先頭にアドレス情報を付加したファイル(拡張子btk)も出力するようにしてあります。
しかしそのbtkファイルはあくまでTK80モニタプログラムのファイル形式です。
zdas.comはそのようなアドレス情報が含まれていない、つまりメモリの中から、任意のプログラム部分を切り取ってsaveしたバイナリコードだけのファイルを読み込むことを前提にしているのです。
当然のことながら、アドレスの情報がありませんから、0000からスタートする形で翻訳してしまうことになります。
なお、参考までに、オリジナルのsound6.binがND80ZVで実行されるときに、メモリの中にどのように読み込まれているのかをお見せすることにいたします。
>dm 8000,8056 8000 CD 47 02 3C CA 00 80 3D CD 0E 80 C3 00 80 F5 E5 ヘG.<ハ..=ヘ..テ.... 8010 D5 C5 21 3F 80 85 6F 46 1E 1A 50 3E EF D3 98 E5 ユナ!?..oF..P>.モ.. 8020 E5 E1 E1 00 15 C2 1F 80 50 3E CF D3 98 E5 E5 E1 .....ツ..P>マモ.... 8030 E1 00 15 C2 2D 80 1D C2 1A 80 C1 D1 E1 F1 C9 7F ...ツ-..ツ..チム..ノ 8040 77 71 6A 5F 59 54 4F 47 43 3F 3B 35 32 2F 2C 25 wqj_YTOGC?;52/,% 8050 27 2A 4B 38 64 23 21 CB 7F 0D 14 00 08 F2 24 00 '*K8d#!ヒ.....$.
sound6.binは上のメモリダンプリストの中の、バイナリデータの部分、CD 47 02 3C …というデータだけが記録されているファイルなのです。
ダンプリストの左にある8000、8010、…というアドレス情報は含まれていません。
それでは正しいリストにするにはどうすればよいのでしょうか?
それをこれからお見せするために、まずはさきほど作成されたファイルがもう一度zdas.comを実行することで上書きされてしまわないように、名前を変更しておきます。
実は、どうせ先に作成したファイルは使い物になりませんから(早トチリでした。決して使い物にならないわけではありませんでした。そのことにつきましては後ほどまたご説明いたします)、新しいファイルで上書きしてしまっても構わないのですけれど、そうするとこの説明で利用するつもりの材料が上書きされてしまって、都合が悪い、というだけの理由でした。
ren(rename)コマンドでファイル名を変更します。
念の為にdirコマンドで確認しました。
今度はzdas.comにアドレス情報をつけて再実行します。
zdas sound6.bin,8000[Enter]と入力しました。
そのように、プログラムが開始されるアドレスをパラメータとして与えることによって正しい逆アセンブルリスト、ソースプログラムファイルが作成されます。
それでは新しく作成されたファイルの中身を見てみましょう。
sound6.dtxです。
ORG $8000 Z0247=$0247 Z2C2F=$2C2F Z384B=$384B ZFFD8=$FFD8 Z8000:CALL Z0247 INC A JP Z,Z8000 DEC A CALL Z800E JP Z8000 Z800E:PUSH AF PUSH HL PUSH DE PUSH BC LD HL,Z803F ADD A,L LD L,A LD B,(HL) LD E,1A Z801A:LD D,B LD A,EF OUT (98),A Z801F:PUSH HL PUSH HL POP HL POP HL NOP DEC D JP NZ,Z801F LD D,B LD A,CF OUT (98),A Z802D:PUSH HL PUSH HL POP HL POP HL NOP DEC D JP NZ,Z802D DEC E JP NZ,Z801A POP BC POP DE POP HL POP AF RET Z803F:LD A,A LD (HL),A LD (HL),C LD L,D LD E,A LD E,C LD D,H LD C,A LD B,A LD B,E CCF DEC SP DEC (HL) LD (Z2C2F),A DEC H DAA LD HL,(Z384B) LD H,H INC HL LD HL,ZFFD8
今度はうまく出来たようです。
sound6.dlsです。
8000 CD4702 CALL $0247 8003 3C INC A 8004 CA0080 JP Z,$8000 8007 3D DEC A 8008 CD0E80 CALL $800E 800B C30080 JP $8000 800E F5 PUSH AF 800F E5 PUSH HL 8010 D5 PUSH DE 8011 C5 PUSH BC 8012 213F80 LD HL,$803F 8015 85 ADD A,L 8016 6F LD L,A 8017 46 LD B,(HL) 8018 1E1A LD E,1A 801A 50 LD D,B 801B 3EEF LD A,EF 801D D398 OUT (98),A 801F E5 PUSH HL 8020 E5 PUSH HL 8021 E1 POP HL 8022 E1 POP HL 8023 00 NOP 8024 15 DEC D 8025 C21F80 JP NZ,$801F 8028 50 LD D,B 8029 3ECF LD A,CF 802B D398 OUT (98),A 802D E5 PUSH HL 802E E5 PUSH HL 802F E1 POP HL 8030 E1 POP HL 8031 00 NOP 8032 15 DEC D 8033 C22D80 JP NZ,$802D 8036 1D DEC E 8037 C21A80 JP NZ,$801A 803A C1 POP BC 803B D1 POP DE 803C E1 POP HL 803D F1 POP AF 803E C9 RET 803F 7F LD A,A 8040 77 LD (HL),A 8041 71 LD (HL),C 8042 6A LD L,D 8043 5F LD E,A 8044 59 LD E,C 8045 54 LD D,H 8046 4F LD C,A 8047 47 LD B,A 8048 43 LD B,E 8049 3F CCF 804A 3B DEC SP 804B 35 DEC (HL) 804C 322F2C LD ($2C2F),A 804F 25 DEC H 8050 27 DAA 8051 2A4B38 LD HL,($384B) 8054 64 LD H,H 8055 23 INC HL 8056 21D8FF LD HL,$FFD8
今回作成された2つのリストを、さきほどお見せしたオリジナルのsound6.lstと比べてみてください。
注目していただきたい点が2つあります。
sound6.dtxでは、ジャンプ命令やコール命令の飛び先のアドレス位置にラベルが置かれています。
それからワークアドレスと思われるアドレスやこのプログラム範囲の外のアドレスをアクセスしているところも、ラベル、変数としてプログラムの先頭に列記しています。
もちろん人間がつけるような意味を含んだラベルをつけることはできませんから、アドレスの前にZを付加しただけのラベルにしています。
でもなかなかに賢いプログラムだとは思いませんでしょうか?
さて、もう1点は、プログラムの後半の部分です。
アドレス803Fから後ろの部分です。
ここには音階テーブルデータが置かれています。
マシン語の命令コードではありません。
でも逆アセンブラプログラムにはそんなことは判断できません。
データであろうと、なんであろうと、ひたすらZ80のマシン語命令コードだと解釈して無理やりニーモニックに翻訳してしまいます。
その結果はご覧のように、一応Z80の命令が並んでいますけれど、当然意味不明のデタラメなプログラムになってしまっています。
果たして、こんなプログラムがZ80アセンブラのソースプログラムとして通用するのでしょうか?
というところで本日は時間がなくなってしまいましたので、この続きは次回にすることに致します。
2010.7.26upload
前へ
次へ
ホームページトップへ戻る