16bitなら簡単そうで、そこらじゅうにソースが転がってもよさそうですが、なぜかこの類の私が手を出せそうなフリーソフトは見当たりませんでした。
でもよく考えたら、windowsがコンソール上でMS-DOSをエミュレートしてくれるので、わざわざ作る必要も確かになさそうですが…
私は初めてのパソコンがwindowsの世代なので、ms-dosの事は正直よくわかりません。
とりあえずCPU固有の命令(mov ax,10とか)以外はint 0x21でのシステムコール系統を何とかすればいいかなぁ、と楽観視しています。
でも、そもそもシステムコールは文字の出入力とファイル操作以外に何をするのかわからない、とかいうレベルです。
開発方針としては、naskを使ってmov ax,bxとかがどんなコードに変換されているのか地道に調べるところから始めようかと…。
手元にwindowsのコンソールというmicrosoft公認(?)のms-dosエミュレータが有るので、これを積極的に活用していくつもりです。
ちなみに、最終的にはこの計画で調べた機械語を基にして、16bitのみ対応の超小型アセンブラを作るつもりです。
とはいっても、今のところ絵に描いた餅ですが…。
(サイズはnaskの1/2、機能はnaskの1/10みたいな感じで…。)
私自身がこれまでにエミュレータを作ったことは有りませんし、ソースを眺めたこともないので、一般的なエミュレータとはかけ離れたものになると思います。
一応の方針としては、当たり前かもしれませんが「ファイル読み込み--->エミュレート--->終了」という感じでしょうか?
私の知る限りでは.comはorg 0x100固定なので、16bitで扱える最大のメモリー容量の1MBの配列を用意して、0x100番目からファイルから読み込んだプログラムを代入していけばいいか、と考えています。
レジスタはG01Main関数で全てint型の変数として宣言して、ax、al、ahはそれぞれ別の変数として扱います。
時折ax = ah * 0x100 + alの公式に当てはめて値を合わせれば問題ないかと…
よく考えたら機械語うんぬんかんぬん以前に、レジスタについて理解していないことが多すぎたので、そこの辺の詳しい挙動を調べてみます。
これにはwindowsコンソールのdebug機能が便利そうなので使ってみました。
(microsoftが作ってるので結果の信憑性も高そうですし。)
実験その一/alやahに0x100以上を入れてみる
当たり前ですが無理でした。
mov al,0x100ぐらいは値がahに繰り上がってah=0x01、al=0x00になるかも…と思ってやってみただけなので。
実験その二/alに0xffを入れた後inc alしてみる
結果はax=0x0000でした。
これも同じくahへの繰り上がりシステムを恐れてやってみましたが、以外とalとahは疎遠のようです。
実験その三/alに0xffを入れた後al+=1してみる
もしかしたらax=0x0100にならないのはincだからでは?と思ったのでadd al,0x01を一応やってみました。
結果は杞憂でした。
実験その四/alに0xffを入れた後al+=0xffしてみる
結果はax=0x00feでした。
やはり、ahの値はalの計算だけでは変化しないようです。
実験その五/ax=0x0000のとき、ax--してみる
ax=0x0000になれば話は早かったのですが、ax=0xffffでした。
そういえばchar a=0xff;って-1になる事もあるような…
実験その六/ax=0x0000のとき、ax-- ax--してみる
結果はax=0xfffeでした。
ax=0xffffになった後の挙動は普通のようです。
実験その七/ax=0x0000のとき、ax-- ax++してみる
結果はax=0x0000でした。
どうやら0x0000と0xffffはトランプのAとK(1と13)の関係にあるようです。
実験その八/ax=0x0000のとき、ah--とal--してみる
結果はそれぞれax=0xff00とax=00ffでした。
alとahはaxの一部ではなく、常にax=ah*0x100+alという式が成り立ってるだけの別のレジスタと考えた方がいいかもしれません。
実験その九/axの実験をaddやsubを使ってやってみる
incとdecを使った実験と結果は同じでした。
と、いうか、違ってたら困るのですが…
今回の計画ではnaskとwindowsに思いっきり頼ることになりそうですが、そもそもK-tanさんはどこで機械語を習得したのでしょう?
asukaやcc1は自分では機械語を生成しないのでアセンブリの知識が有れば出来るような気がしますが、さすがにnaskは機械語を知っていなければ無理だと思います。
そもそも、私にnaskを読む力が有れば一個一個アセンブルしたファイルをのぞいて機械語を調べる、という非効率的な事をしなくても済むのですが、残念ながら出来ないので、K-tanさんが使ったと思われる機械語の対応表みたいなものをご存知の方は、お教えいただけると助かります。
そういえば、話はそれますが、アセンブルしたファイルをのぞくのはK-tanさんがGUIGUI01memoシリーズでおつくりになったバイナリビュアーが便利そうです。
K-tanさんのソフトには色々とお世話になります。m(_ _)m
stardosというのはいま考えたエミュレータの名称です。
starは私の名前の「星野」から、dosは「ma-dos」からとってきました。(安易すぎ?)
正式名称を付けた方がかっこいいかもしれないので、気が向いたら考えておきます。
それまではstardosはSTARDOSの略称とでもしておきます。
さて、くだらない話はここまでにして置き、肝心の中身ですが、汎用レジスタへの代入しかサポートしません。
よって、実用性は全くありません。
万が一stardos 0.1が公開されていても、使用目的でダウンロードしないのが推奨です。
ただ、機械語を一個一個調べていくのは大変そうなので、開発は今週いっぱいは最低でもかかると思います。
プログラミング技術のない未熟者の工作ですので、期待しないでください。
mov命令の構造が意外と簡単だったことが判明したため、popやpushなどのスタック関係も実装しようと画策しています。
しかし、spの初期値が分からずに困っています。
windowsのdebug機能ではsp=0xffeeと表示されるのですが、
cmp sp,0xffee je YES mov ah,0x02 mov dl,'n' int 0x21 int 0x20 YES: mov ah,0x02 mov dl,'y' int 0x21 int 0x20
というようなプログラムを実行してみても「n」と表示されました。
色々試したところ、最初のcmpをcmp sp,0xfffeとすると「y」と表示されました。
しかし、これはあくまで私の環境でしか通用しないことかもしれませんので、どなたか上記のプログラムをcmpを変更した物を実行してみていただける方を募集いたします。
とりあえずは情報が有るまでは.comでのspの初期値は0xfffeと仮定して開発をしていきます。