前述のように、MSXではプログラムが異なったスロットに分かれているため、現在選択されているスロット上にないプログラムが必要になることもあります。これは主に以下のような場合が考えられます。
- MSX-DOSの環境から、MAIN ROMにあるBIOSを呼び出す。
- BASICの環境から、SUB ROMにあるBIOSを呼び出す(MSX2以降)。
- カートリッジソフトから、MAIN ROMあるいはSUB ROMのBIOSを呼び出す。
これらの作業を行う際スロット切り換えが簡単かつ安全に行えるように、インタースロットコールという一群のBIOSルーチンが存在し、どのスロットに存在するルーチンでも呼び出せるようになっています。本説では、このインタースロットコールの使用法を説明しましょう。
例えば、MSX-DOSからMAIN ROM上のBIOSを呼び出す場合、スロットの状態の遷移は以下に示すとおりです。
- 初めはMSX-DOSモードなので64Kのアドレス空間すべてにRAMが選択されており、このままではBASIC-ROMをアクセスできない(図5.6-1)。
- ROMのBIOSを呼び出すためにページ0をBASICのMAIN ROMに切り換え、アクセス可能な状態にする。そしてBIOSを呼びだす(図5.6-2)。
- BIOSの処理が終わったら再び元の状態に戻し、初めに呼ばれたアドレスにリターンする。
このとき、MSX-DOS側のプログラムが、ページ0以外に存在するならば話は簡単なのですが、呼びだす側のプログラムが呼びだされる側のBIOSと同じページ0に存在しているときは、非常に複雑になります。呼び出す方のプログラムがページ0を切り換えたとたんに自分自身がいなくなって暴走してしまう、ということのないように配慮しなければいけません。
インタースロットコールでは、いったんページ3へ分岐してから実際のスロット切り換えを行うという方法で、この問題を解決しています。
このような複雑な状況をインタースロットコールはサポートするので、ユーザーは簡単に他のスロットのプログラムを呼び出すことができます。
インタースロットコールは、以下に述べるいくつかの方法で行うことができます。これらはBIOSとしてMAIN ROM内に含まれているものですが、その中のいくつかはMSX-DOSの環境下においてもまったく同一のものが用意され、MSX-DOS使用時のインタースロットコールを可能としています(「2.2.2 MSX-DOSのインタースロットコール」参照)。
- RDSLT(000CH/MAIN)
| A | スロット指定(図5.5と同じフォーマット) |
| HL | 読み出すアドレス |
| 指定したスロットの指定したアドレスの内容を読み出し、Aレジスタに格納します。スロットの指定はAレジスタによって図5.5の形式で行います。このとき、目的のスロットが基本スロットならば、上位6ビットはすべて「0」に設定し、下位2ビットでスロット#0〜#3を決めます。もし拡張スロットを指定するならば、同様にビット0とビット1で基本スロットを指定し、その基本スロットに接続されるどの拡張スロットかということをビット2とビット3で指定、さらにビット7を「1」にします。 |
- WRSLT(0014H/MAIN)
| A | スロット指定(図5.5と同じフォーマット) |
| HL | 書き込むアドレス |
| E | 書き込む値 |
| Aレジスタで指定したスロット(指定の形式は図5.5と同じ)のHLレジスタで指定したアドレスに、Eレジスタの値を書き込みます。 |
- CALSLT(001CH/MAIN)
| IY | 上位8ビット | スロット(図5.5と同じフォーマット) |
| IX | | コールするアドレス |
| IYレジスタの上位8ビットで指定したスロット(指定の形式は図5.5と同じ)の、IXレジスタで指定するアドレスに存在するルーチンをコールします。 |
- ENASLT(0024H/MAIN)
| A | スロット(図5.5と同じフォーマット) |
| HL | 上位2ビットでスロット切り換えを行うページを指定する |
| HLレジスタの上位2ビットで指定したページを、Aレジスタで指定したスロットに切り換えます。 |
- CALLF(0030H/MAIN)
| インラインパラメータ形式でスロットとアドレスを指定する |
| 指定したスロットの、指定したアドレスをコールしますが、前述のCALSLTと異なり、スロットおよびアドレスの指定は次に示すように、インラインパラメータ形式で行います。すなわち、このCALLFを呼びだす命令の直後にスロットを指定する値1バイト(RDSLTと同じフォーマット)を置き、その次にアドレスを指定する数値2バイトを置くという形でパラメータを渡します。「CALL 0030H」の代わりに「RST 30H」というRST(リスタート)命令を使ってもかまいません。その場合、4バイトでインタースロットコールが実現可能になります。 |
rst 30h ;interslot call
db 00000000b ;select slot#0
dw 006ch ;call address = 006ch
- RSLREG(0138H/MAIN)
| 基本スロット選択レジスタの内容を読み出し、Aレジスタに入れます。 |
- WSLREG(013BH/MAIN)
| 基本スロット選択レジスタにAレジスタの値を書き込み、スロットを選択します。 |
- SUBROM(015CH/MAIN)
| IX | コールするアドレス、PUSH IX (「A.1.2 SUB ROM」参照) |
| BASICのSUB ROMを呼びだすためのルーチンです。SUB ROMの存在するスロットはBIOSが自動的に調べます。普通は、次のEXTROMを使います。 |
- EXTROM(015FH/MAIN)
| BASICのSUB ROMを呼び出すためのルーチンです。上記のSUB ROMとこのEXTROMとは、IXレジスタの値をpushするか否かという点だけが異なります。 |
MSX-DOSでは、以下に示す5種類のインタースロットコールが用意され、MSX-DOSジャンプベクタにそのエントリアドレスが定義してあります。これらはBIOS内の同名のルーチンとまったく同じものですから、機能や使用法に関しては、前述のBIOSをご覧下さい。
なお、MSX-DOSからSUB ROM内のルーチンを呼びだす場合は、これらのルーチンは使用せず、「2.2.3 MSX-DOSからのSUB ROMコール」の方法を使います。
| RDSLT(000CH) | 指定スロットの指定アドレスから値を読み出す |
| WRSLT(0014h) | 指定スロットの指定アドレスに値を書き込む |
| CALSLT(001Ch) | 指定スロットの指定アドレスを呼び出す |
| ENASLT(0024h) | 指定スロットを使用可能な状態にする |
| CALLF(0030H) | 指定スロットの指定アドレスを呼び出す |
リスト5.2 MSX-DOSからBIOSを呼び出す
calslt equ 001ch ; inter slot call
exptbl equ 0fcc1h ; slot address of MAIN ROM
ld iy,(exptbl-1) ; load slot address of the MAIN ROM
; in high byte of IY
ld ix,address of the BIOS jump table
call calslt
MSX-DOSの環境からSUB ROMを呼ぶ場合は、以下のような特別な配慮が必要です
- CALSUBのエントリ条件は、IXにアドレスを入れるだけです。
- スタックはページ0以外でなければなりません。
- 割り込み禁止は必要ありません。
- 終了後、NMIフックの解除は必要ありません。
ここで問題となるのは、EXTROMに必要なIXレジスタの値が渡せないことです。したがって、BIOS ROMが呼び出された後にIXがセットされ、EXTROMにジャンプする必要があります。
具体的には、スタック上に次のようなルーチンを用意し、NMIのフックからジャンプさせるようにしておきます。次に、BIOSのNMIエントリ(フックは用意されているが使用されない)をインタースロットコールします。リスト5.3を参照して下さい。
リスト5.3 DOSからのSUB ROMコール
; +0 inc sp
; +1 inc sp
; +2 ld ix,<sub-ROM entry>
; +6 nop
; +7 jp extrom
calslt equ 001ch
extrom equ 015fh ; Non-maskable interrupt
nmi equ 0066h ; Hook for NMI
exptbl equ 0fcc1h
;
_calsub::
exx ; Save argument registers over setup
ex af,af'
ld hl,extrom
push hl
ld hl,0c300h ; jp xxxx, nop
push hl
push ix ; SUB ROM entry
ld hl,021ddh ; ld ix,xxxx
push hl
ld hl,03333h ; inc sp, inc sp
push hl
ld hl,0
add hl,sp
ld a,0c3h
ld (h.nmi),a
ld (h.nmi+1),hl
ex af,af' ; Restore registers
exx
;
ld ix,nmi
ld iy,(exptbl-1)
call calslt
ei
;
ld hl,10 ; Throw away the interface routine
add hl,sp
ld sp,hl
ret
end
スロットに関するワークエリアには、以下のものがあります。
【EXBRSA(FAF8H,1)】SUB ROMのスロットアドレス
図5.7 SUB ROMのスロットアドレス
【EXPTBL(FCC1H,4)】基本スロットの拡張の有無
図5.8 基本スロットの選択
【SLTTBL(FCC5H,4)】拡張スロット選択レジスタ値の保存エリア
図5.9 拡張スロットの選択
【SLTATR(FCC9H,64)】各スロット、ページにおけるアプリケーションの有無
図5.10 アプリケーションの有無
【SLTWRK(FD09H,128)】アプリケーション用ワークエリア
図5.11 アプリケーション用ワークエリア