CP/M-68Kを移植していく Part 3
アセンブラ
今回のマシンでは機械語モニタに Universal monitor を使っており、このモニタのビルドに、Macro Assembler AS を使っています。複数のクロスアセンブラを使い分けるのは面倒なので、BIOSを書くにも、このアセンブラをそのまま使うことにしてみます。
BIOS のソースコード
以前、CP/M-8000 を移植したときは、C言語で書かれたBIOSのソースコードをアセンブリ言語に翻訳して作ったのですが、幸いにも CP/M-68K には、DISK7の中に アセンブリ言語で書かれたソースコード ERGBIOS.S が入っているので、それを参考にします。
リンク方法の確認
コンソールの入出力だけできる最低限のBIOSを作って、BIOSのリンク方法が正しいのか確認してみました。
cpu 68000
org $1b000
trap3 equ $8c
_ccp equ $150bc
nfuncs equ 23
_init:
move.l #traphndl, trap3
clr.l d0
rts
traphndl:
cmpi #nfuncs, d0
bcc trapng
lsl #2, d0
lea.l biosbase, a0
movea.l (a0, d0), a0
jsr (a0)
trapng:
rte
biosbase:
dc.l _init
dc.l wboot
dc.l constat
dc.l conin
dc.l conout
:
dc.l setexc
wboot:
jmp _ccp
constat:
: 省略
rts
conin:
: 省略
rts
conout:
: 省略
rts
setexc:
andi #$ff, d1
cmpi #47,d1
beq noset
cmpi #9,d1
beq noset
lsl #2, d1
movea.l d1, a0
move.l (a0), d0
move.l d2, (a0)
noset:
rts
上のコードは、かなり省略したBIOSのアセンブリコードです。
BIOSのスタートアドレスは、
org $1b000
で指定しています。BIOSの開始は _init からで、trap 3 のベクタをtraphndl に設定します。BIOS ファンクションをコールをする場合、D0 にファンクション番号を入れて trap 3を実行すると traphndl に処理が移り、D0 の値をもとに biosbase からアドレスを引いて、それぞれのサブールチンをコールします。
もともとのERGBIOSのコードでは、biosbase からアドレスを引くのに movea.l 6(pc, d0), a0
が使われていたのですが、Macro Assembler As では、書き方を色々試したもののアセンブルできませんでした。上のコードでは、
lea.l biosbase, a0
movea.l (a0, d0), a0
の2命令に書き換えています。
wboot は、
jmp _ccp
で、CCPにジャンプするコードになっています。これで、CCP + BDOS とBIOS のリンクは大丈夫なはず。
動作を確認するため、にコンソール入出力 constat, conin, conout を書いています。この部分はマシンに依存するので省略します。
コンソール入出力を書いただけでは動作しないので、さらに、setexc を書いています。これは、BDOS をコールするための trap 2 のベクターを設定するために使われます。これは、ERGBIOSのコードそのままです。
CPM15000のバイナリを 0x15000 から、BIOS のバイナリを 0x1b000 から配置し、0x15000 から実行するとコマンドプロンプトが出て動作することが確認できます。
よくわからない Exception $03 が出ていますが、その後に、プロンプト A> が出ています。ディスク入出力のコードがまだ無いので、dir を入力しても何も起こりませんが、CCPがBISOを呼べておりリンクができていることを確認できました。