ラベル 6502 の投稿を表示しています。 すべての投稿を表示
ラベル 6502 の投稿を表示しています。 すべての投稿を表示

2021年11月17日水曜日

6502の逆アセンブラを制作する(その3)

 6502の逆アセンブラを制作する過程の紹介の続きです


W65C816ボード


制作過程(6)--- pass2

pass2では再びデータの先頭から1文字ずつ読みながらアセンブルリストを作成し、ListリストとAssembleリストボックスに書き込んでいきます。その書式は次のようです。
Listリストボックスには
 行番号 アドレス オペコード オペランド ラベル ニーモニック オペランド
Assembleリストボックスには
 ラベル ニーモニック オペランド (アセンブラプログラムにかけられる形式です。)

そのアドレスにラベルがついている場合はラベルも表示し、オペランドがアドレスである場合は即値をラベルに置き換えて表示します。
該当する命令がない場合はオペコードを ?-xx- のように表示し、ニーモニック欄はそのアスキーコードを'a'のように表示します。

【ここまでの結果】 ... 06Coding-pass2

制作過程(7)

作成された逆アセンブルリストを保存します。
ListリストはLSTファイルとして、AssembleリストはASMファイルとして保存します。

【ここまでの結果】 ... 07Coding-savefile

制作過程(8)

最後に細部の見直しをして完成です。

【11月18日追加】下の2ファイルは適宜見直して差し替えることがあります。

【完成版】 ... 08Coding-complete  

完成版の中の実行ファイルのみ ... 6502DAsmWin

最後に

10年ほど前に制作した6800用の逆アセンブラの制作過程をほとんど忘れてしまっていたので、それを復習するためもあって今回、6502の逆アセンブラの制作に取り組んでみました。
自分の場合は、ソースが公開されていてもあまりに長いとなかなか読み切れないことが多いので、いくつかに分割して紹介してみましたがどうだったでしょうか。

手持ちに6502のバイナリがないので十分に動作確認ができてはいないのですが、とりあえずelectrelicさんのUniversal Monitor 6502版が正常に逆アセンブルできることは確認してあります。

6502の命令コードの解釈やその他の誤り・勘違いなどがありましたらお知らせいただけるとありがたいです。






 

6502の逆アセンブラを制作する(その2)

 6502の逆アセンブラを制作する過程の紹介の続きです


W65C816ボード

制作過程(5)--- pass1

いよいよここからが逆アセンブラの本体作成となりますが、まず検討すべきは命令の分類です。RockwellのデータシートによるとR65C02の命令は次の16通りに分類できるようです。

 0:(no opcode)
 1:Absolute 1:a
 2:Absolute Indexed Indirect 2:(a,x)
 3:Absolute Indexed with X 3:a,x
 4:Absolute Indexed with Y 4:a,y
 5:Absolute Indirect 5:(a)
 6:Accumulator 6:A
 7:Immediate 7:#
 8:Implied 8:i
 9:Program Counter Relative  9:r
10:Zero page Relative 10:zp,r
11:Zero page 11:zp
12:Zero page Indexed Indirect 12:(zp,x)
13:Zero page Indexed with X 13:zp,x
14:Zero page Indexed with Y 14:zp,y
15:Zero Page Indirect 15:(zp)
16:Zero Page Indirect Indexed with Y 16:(zp),y

これを元にして、オペコード、ニーモニック、命令長、命令タイプの表を作成しました。
それが下に示すファイルR65C02dopcode.hです。

         
 
pass1はデータファイルを1文字ずつ読みながら、スキップ範囲指定されていなければR65C02dopcode.hを参照して該当するopcodeを見つけ、そのオペランドがアドレスであったらL_xxxx(xxxxはアドレス)というラベル名でラベルテーブルに格納するという作業を繰り返します。(スキップ範囲指定されている場合は下記の処理をします。)
従って、上記のaやzpはそのアドレスにラベルが付き、rは相対アドレスを絶対アドレスに変換したアドレスにラベルが付くことになります。
該当する命令が存在しない場合はエラーにはせずにそのコードをスキップします。(pass2で処理します。)

スキップ範囲の処理
スキップ範囲に指定したデータの扱いですが、範囲の先頭の1バイトの値がアスキー表示可能($20~$7F)ならその範囲全体をFCC /abc.../のように表示し、そうでない場合はFCB $xx,$yy,$zz,...のように表示します。

【ここまでの結果】 ... 05Coding-pass1

6502の逆アセンブラを制作する(その1)

 6502の逆アセンブラを制作する過程を紹介します

6502CPUには触れたことがなかったのですが、最近W65C02やW65C816用のボードを製作した(2021年5月20日のブログ「W65C816も動作する6502基板を製作してみました」)こともあって、6502のアセンブラプログラミングに取り組んでみようと思っています。

W65C816ボード


必要になるのはアセンブラですが、何しろ全く知識のないCPUですので、まず逆アセンブラを制作することで6502の命令体系に慣れ、それからアセンブラを制作することにしました。

なお、ここで制作するのはオリジナルの6502ではなく、Rockwell のR65C02ですので、オリジナルよりも命令が拡張されています。(オリジナルの6502のデータシートが入手できなかったため)

完成した逆アセンブラの動作画面を紹介します。

R65C02用逆アセンブラ

以前制作した6800や6809用の逆アセンブラをベースにしていますので、画面や操作性はほとんど同じです。

この逆アセンブラを制作する過程を順に紹介し、ソースプログラムも公開しようと思いますが、アセンブラや逆アセンブラの構造などについて全く知識のない素人が自己流で制作したものですので、知識のある方から見ると何だこれはと思われるかもしれませんが、私が調べた限りではアセンブラや逆アセンブラを作成するために役立つ情報はほとんど見当たらないようです。(専門家から見ると簡単すぎるので解説する気にもならないということなのでしょう。)

全体の構想

(1)操作性を考えてFormアプリとし、使い慣れているVC++で作成する。

(2)自動的にラベルを付けることができること。

(3)データ部分を指定できること。

(4)変換結果が画面で確認できること。

(5)作成されたアセンブラリストはそのままでアセンブラにかけられること。

上記を目標に制作した結果、上記画面のような構成となりました。


制作の過程

次のような段階で進めていきます。

(1)必要なFormをVisual Studio 2010のC++で作成します。

(2)作成したFormをVisual Studio 2019のC++に移行します。 

(3)処理ファイルを読み込む処理をします。

(4)オプションの処理をします。

  オフセットアドレスやスキップアドレス範囲などの設定をします。

(5)pass1の処理をします。

  ラベルの作成・登録をします。

(6)pass2の処理をします。

  アセンブルリストを作成します。

(7)処理結果を保存する処理をします。

  アセンブルリストを2つの形式(リスト形式、アセンブラ形式)で保存します。

(8)最終確認をして仕上げます。


入力データはファイルメニューから選択するか、あるいは直接ファイル名ボックスにドラッグ&ドロップします。スタートアドレスはBINの場合は$0000に、HEXやMOTの場合はその先頭アドレスになります。オフセットアドレスを設定するとアセンブル開始アドレスを変更することができます。

データ範囲はスキップアドレス範囲として設定します。もちろん複数範囲を指定できます。それらの範囲はFCBあるいはFCC疑似命令となります。

処理結果はListリストボックスやAssemblerリストボックスに表示されますが、変換中も表示させるようにすると時間がかかるので、処理終了後に表示されるように設定しています。

制作過程(1)

まずはFormの作成ですが、最近使用しているVisual Studio 2019(フリー版)ではC++のFormアプリは作成できないようですので、昔使っていたVisual Studio 2010で元のFormを作成し、それを2019で扱うことにします。

必要なメインForm、OffsetInForm、SkipAreaInForm、HelpFormの4つを作ります。

【ここまでの結果】... 01OriginalForm_byVC2010 (OneDriveで公開。以下同様)

制作過程(2)

(1)で作成したものを2019で読み込み、OffsetInForm、SkipAreaInForm、HelpFormをProjectに設定し、さらにメニューの項目を設定します。

【ここまでの結果】 ... 02SetForm_byVC2019

制作過程(3)

逆アセンブルすべきファイルを読み込む処理をします。BINファイルのみでなく、HEX,MOTファイルも読み込めます。

スタートアドレスはBINでは$0000、HEX,MOTでは設定されている先頭アドレスになります。アドレスが不連続の場合はその空白区間は$00になります。

(とりあえず、逆アセンブル実行ボタンを押すと読み込んだデータを表示するようにしてありますが、先頭アドレスから読み込んだ数だけ表示しますので、アドレスが連続していない場合は正常に表示されません。)

【ここまでの結果】 ... 03Coding-inputfile

制作過程(4)

オフセットアドレスやスキップアドレス範囲などのオプションの処理をします。

【ここまでの結果】 ... 04Coding-setoption



2021年3月10日水曜日

ドータボード上の6502でAppleⅡのBASIC Subsetが動作

 ようやくAppleⅡのBASIC Subset を走らせることができました


他の方が努力して実現されたものを後追いしているだけなので、何の意味もないと思いますが、それなりに苦労しましたので、これからやってみようと思う方に多少なりとも参考になればと思いまして、その経過をここに残しておきます。


6502を装着した6802ボード


ハードですが、下のメモリーマップにありますように64KB(32KBx2)のRAMを実装していますが、$F000~の4KBにROMが、さらに$F080からの128byteがI/O領域となっています。


SBC6802のメモリマップ


これは6809ボードを製作した時にRAM領域をできる限り広くしたかったのと、モニタとしてASSIST09を使用するために$F000~をROMにする必要があったためで、その配置をそのまま踏襲しています。


6502については何も知識がありませんので、夢七さんのブログを見ながら、そのまま移植してみることにしました。


(1)Woz MonitorとApple1 BASIC の移植

まず最初に「SBC6800に6502を載せてApple1を体験する」を元にして、Woz MonitorとApple1のBASICを移植してみました。

幸い、Woz Monitorはメイン部が$FF00~に、$F000~$F036にI/Oルーチンが配置されていたので、ACIAのアドレスを変更するだけで済みました。

また、Apple1 BASICについては上位の32KBのRAMをROMに置き換えて、その$E000~に配置しました。


A1BASICとWoz Monitor


ソースのアセンブルですが、オリジナルのソースを夢七さんがArcpitのX6502でアセンブルできるように改変してくださっているので、

>MSDOS X6502 /H A1BASIC-WOZV1.ASM,A1BASIC-WOZV1.HEX,A1BASIC-WOZV1.LST

でアセンブルできました。

動作している様子を示します。


Apple1 BASICの動作画面


(2)AppleⅡ BASIC Subset の移植

続いて「SBC6800に6502を載せてAppleⅡBASIC Subsetを走らせる」を元にして、AppleⅡ BASICの移植に取り掛かりました。

BASICのサイズが大きいので、ブログのように$E000からアセンブルすると$F080からのI/O領域まで入ってきます。そこで、$F080~$F0FFをスキップするようにORG命令を挿入してみたのですが、そうすると$E000~$FFFFにBASICとWoz Monitorが収まりませんでした。

次に、BASICを$D000からに配置するようにアセンブルしてみました。結果、BASICは$D000~$EE46に収まりました。Woz Montitorは先のA1BASICの場合と同じように$F000~にI/O、$FF00~にWoz Monitorを配置しました。

ところが、アセンブルした結果をROMに焼いて走らせてみましたが、正常に動作しません。

何回見直してもソースやアセンブル手順に間違いはありません。6502の知識が全くないのでほとんどお手上げ状態でしたが、ソースをじっくり眺めているうちに、FDB命令がコメントアウトされて、その後ろにbyte命令でバイト列が並んでいるという形があちこちにあるのに気づきました。

試しに、FDB命令を元に戻し、byte命令をコメントアウトしてアセンブルしてみるとbyte命令のバイト列と同じようなコードが生成されましたが、よく見ると2バイトコードの上位下位が入れ替わっています。

つまり、夢七さんが改変されたソースはX6502でアセンブルするために、元のソースで使われている.addrのようなX6502では対応していない命令をFDBに置き換えるという対処をしているのですが、FDBではアドレスの上位下位が自動では入れ替わらないために、アセンブルしたコードのうちのアドレスの上位下位を入れ替える必要がある部分をbyte命令で直接記述していることが分かりました。ということで、このソースは$E000からアセンブルすることを決め打ちしているので、$D000からに変更してアセンブルしても正常に動作しないわけでした。

そこで、まずソースのFDB命令を元に戻して$D000からアセンブルし、得られたコードのアドレス部の上位下位を入れ替えてbyte命令に並べ、FDB命令を再度コメントアウトするという操作を加えることで、X6502でアセンブルできるソースができあがりました。

そのソースを改めてアセンブルし、得られたバイナリをROMに焼いて走らせてみたところ、今度は正常に動作しました。

メモリマップを示します。


AppleⅡBASICとWoz Monitor

動作している様子です。

AppleⅡの動作画面


(3)ASCIIART を走らせてみる

BASICが無事に走ったということで次はASCIIART.BASを走らせてみました。


ASCIIART結果

描画時間は手動計測ですが4分21秒程度でした。なお、システムクロックは2MHzです。

今回は元のソースに見慣れない疑似命令が使われていたために移植に手間取りましたが、それでも夢七さんがX6502でアセンブルできるように改変してくださったために、何とか移植ができました。夢七さんに感謝いたします。

移植に手間取っている間にMouserからW65C02S6とW65C816S6が届きました。このW65C02はもちろん正常に動作しました。W65C816を購入したのは、アキュムレータが1個しかない6502では6800よりもアセンブラでプログラミングしにくいと思うのですが、W65C816なら6800と同じような感じでプログラミングできるかもと思ったからです。

いつかはW65C816のシングルボードを作ろうと思っていますが、いつになりますやら。



2021年2月28日日曜日

6802ボードでドータボードを用いて6502を走らせる

 自作6802ボードでドータボード(ほうめいさんのPLDR6502)を用いて6502を走らせる


先日まごころせいじつ堂のほうめいさんから、電脳伝説さんのSBC6800ボードで6502を走らせるためのドータボードPLDR6502をいただきましたので、私の自作品で今は使用していない6802ボードでも走らせることができないものかと試みてみました。

私の6802ボードは水晶発振回路からの8MHzを6802のEXTAL端子に入力して、出力される2MHzのE信号で周辺回路を制御しているので、8MHzをそのまま入力するわけにはいきませんが、幸い、ACIA63B50に加える614KHzのクロック生成のために8MHzをLS161で13分周していますので、その途中から2MHzを取り出して、それを37ピンのPHI2Iに加えることで2MHzで動作させることができそうです。

ドータボードの修正としては、39ピンPHI2Oと37ピンPHI2Iを入れ替えることと7ピンSYNCをカットしてGNDに落とす(BAを常にLowに)だけで良さそうです。6502にはBA信号がないのでちょっと悩みましたが、常にLowにしておいても特に不都合はないようです。(本当は周辺ICのアクセスに不都合が生じる場合があるそうですが...)

問題はCPUで、eBayで調達したW65C02(5個)とR65C02(2個)のいずれも動作しませんでしたので、仕方なくオレンジピコさんからW65C02S6PTG-14を購入してようやく動作させることができました。動作しなかったW65C02はいずれもほうめいさんのブログで動作しなかったと報告されているものと同じ刻印でした...


ということで、動作している様子です。

残念ながらボード上のLS161から2MHzを引き出している線とBAをGNDに落とす線が見えていて見苦しいです...


自作6802ボード上に装着した


オレンジピコさんから購入したW65C02です。


ドータボードとW65C02



動作確認にはほうめいさんと同じように、ElectreilicさんのUniversal Monitorを使わせていただきました。モニターの開始アドレスとACIAのアドレスを変更するだけで、アセンブルしてROMライターで焼いて動作させることができました。


Universal Monitorが動作



動作しなかったW65C02とR65C02群です...



eBayでは時々こんなことが...


W65C02は全く無反応でしたが、R65C02の方は全くの無反応ではなくて画像のように意味のないデータが定期的に表示されており、一見何かの動作をしているように見えます。



もっと追求すれば何か分かるかも


ここまでくると、次はBASICを走らせてASCIIARTの描画速度を測定してみたいところですが、私の6802ボードはROMが$F000~$FFFFのみ(I/Oは$F080~$F0FF)ですのでBASICをROMに焼き込むことができません。
ですので、起動後にBASICをRAM中にLoadして走らせる必要がありますが、6502の機械語は全くいじったことがないので、Loaderを制作できるのはもう少し後になりそうです。

初めて触れた6502ですが、折角の機会なのでもう少しいじってみようと思いますので、W65C02と使いこなせるかどうかわかりませんがW65C816を追加注文したところです。

私は、今は6809と6802の両用ボードを使用していますので、6802ボードは眠っていたのですが、それを活用することができてありがたいです。
ドータボードPLDR6502を下さったほうめいさんとUniversal Monitorを制作して公開されているElectreilicさんに感謝いたします。ありがとうございました。