XMS ドライバ

KusaReMKN

そもそも XMS とは

XMS とは Exteneded Memory Specification の略称であり、MS-DOS 上でメモリを扱う規格のひとつです。

そもそも、Intel 8086 CPU はセグメント方式によるメモリ管理の制約により、1 MB ほどの領域しか扱うことができませんでした。 この領域には VRAM や BIOS のコードも配置されており、一般に利用可能なメモリ領域は 640 kB でした (この領域をコンベンショナルメモリといいます)。 MS-DOS の本体や各種デバイスドライバ、更には FEP などをこの領域に配置していたのではメモリ不足でアプリケーションを実行できなくなってしまいます。 そのため、コンベンショナルメモリ以外の領域にそれらを配置してやる必要がありました。 XMS は i386 以降の CPU で利用可能な 1 MB 以降のメモリを扱うものです。

XMS は HMAEMBUMB の領域からなります。

HMA

High Memory Area の略称であり、0FFFF:0010 (100000H) から 0FFFF:0FFFF (10FFEFH) のメモリ領域を指します。

この領域はリアルモードでアクセス可能な 1 MiB 以上の領域です。 しかし、アドレスのセグメント部は 0FFFFH に固定されており、複数のプログラムでこの領域を利用するには不都合です。 通常は CONFIG.SYS に記述される DOS=HIGH の設定によって MS-DOS の本体が常駐します。

EMB

Extended Memory Block の略称であり、10FFF0H 以降のメモリ領域を指します。

XMS ドライバを利用してコンベンショナルメモリとの間でデータを転送し合うことができます。

UMB

Upper Memory Block の略称であり、0A0000H や 0C0000H から 0FFFFFH の VRAM や BIOS などが利用しているメモリ領域を指します。

この領域の未使用域を RAM として利用できます。 CONFIG.SYS に記述される DOS=HIGH,UMB の設定によって UMB を利用可能にすると、DEVICEHIGH コマンドや INSTALLHIGH コマンドによってデバイスドライバや常駐プログラムを UMB に組み込めるようになります。 COMMAND.COM の内部コマンド LOADHIGH (LH) を利用することでも UMB を利用できます。

利用開始手続き

まず MS-DOS のファンクションコール INT 2Fh を利用して XMS ドライバの有無とコール先を取得します。

XMS ドライバの機能を利用するには、ここで得られる値 XMS_CALLCALL far します。

ソースコード

このサブルーチンは XMS ドライバをチェックし、成功すれば XMS_CALL にコール先をストアし、失敗すれば CF を立てます。

CHK_XMSDRV:
    MOV AX,4300h
    INT 2Fh
    CMP AL,80h
    JZ  CHK_XMSDRV_OK
    STC
    RET
CHK_XMSDRV_OK:
    MOV AX,4310h
    INT 2Fh
    MOV [XMS_CALL+0],BX
    MOV [XMS_CALL+2],ES
    CLC
    RET
XMS_CALL:
    DW  ?,?

XMS バージョンの取得

利用可能な機能を確認するためにバージョン情報を確認する必要があります。

パラメータ

レジスタ
AH 00h

戻り値

レジスタ
AX XMS のバージョン
BX ドライバのリビジョンナンバ
DX 0000h: HMA が存在する
  0001h: HMA が存在しない

例えば、Version 1.23 なら AX=0123h のようになります。 リビジョンナンバは通常利用しません。

HMA の要求

HMA を利用するには A20 ラインがグローバルに有効にされている必要があります。

パラメータ

レジスタ
AH 01h
DX 常駐プログラムやデバイスドライバの場合: 必要な容量 [kBytes]
  アプリケーションプログラムの場合: 0FFFFh

戻り値

レジスタ
AX 0001h: 成功 割り当てられた
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  90h: HMA が存在していない
  91h: HMA はすでに利用されている
  92h: DX で指定された値は /HMAMIN= より小さい

BL=92h は CONFIG.SYS 内で設定される値 /HMAMIN= (HMA 利用最小サイズ) によって発生します。

HMA の解放

パラメータ

レジスタ
AH 02h

戻り値

レジスタ
AX 0001h: 成功 解放した
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  90h: HMA が存在していない
  93h: HMA は割り当てられていない

A20 ラインのグローバルな有効化

パラメータ

レジスタ
AH 03h

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  82h: A20 のエラー

A20 ラインのグローバルな無効化

パラメータ

レジスタ
AH 04h

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  82h: A20 のエラー
  94h: A20 が有効化されていない

A20 ラインのローカルな有効化

パラメータ

レジスタ
AH 05h

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  82h: A20 のエラー

A20 ラインのローカルな無効化

パラメータ

レジスタ
AH 06h

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  82h: A20 のエラー
  94h: A20 が有効化されていない

A20 ラインの状態を取得

パラメータ

レジスタ
AH 07h

戻り値

レジスタ
AX 0000h: 無効
  0001h: 有効
BL 00h: 成功
  80h: この機能は実装されていない

EMB の空き容量を取得

パラメータ

レジスタ
AH 08h

戻り値

レジスタ
AX 最大連続空き容量
DX 合計空き容量
BL (AX=DX=0 のとき) 80h: この機能は実装されていない
  0A0h: EMB の空き容量はない

EMB の割り当て

EMB を利用するには A20 ラインがローカルに有効にされている必要があります。

パラメータ

レジスタ
AH 09h
DX サイズ (kBytes)

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
DX ハンドル (失敗時は 0000h)
BL (失敗時) 80h: この機能は実装されていない
  0A0h: EMB の空き容量はない
  0A1h: ハンドル数が足りない

EMB の解放

パラメータ

レジスタ
AH 0Ah
DX ハンドル

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
DX ハンドル (失敗時は 0000h)
BL (失敗時) 80h: この機能は実装されていない
  0A2h: ハンドルは無効
  0A3h: EMB がロックされている

EMB のコピー

パラメータ

レジスタ
AH 0Bh
DS:SI コピーパラメータを格納しているアドレス

コピーパラメータ

名前データサイズ内容
LengthDWORDコピーするバイト数
SourceHandleWORDコピー元ハンドル
SourceOffsetDWORDコピー元オフセット
DestHandleWORDコピー先ハンドル
DestOffsetDWORDコピー先オフセット

戻り値

レジスタ
AH 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  82h: A20 のエラー
  0A3h: SourceHandle が無効
  0A4h: SourceOffset が無効
  0A5h: DestHandle が無効
  0A6h: DestOffset が無効
  0A7h: Length が無効
  0A8h: 無効な重複部分がある
  0A9h: パリティエラー

偶数番地→偶数番地 (偶数バイト) だと高速に処理されるかもしれません。 x386 以降では四倍数番地→四倍数番地だと高速に処理されるかもしれません。

下位から上位に向かってコピーされます。 コピー元とコピー先が重複する領域にある場合は注意が必要です。

コンベンショナルメモリのハンドル番号は 0000h です。

EMB のロック

パラメータ

レジスタ
AH 0Ch
DX ハンドル

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
DX:BX ロックされた EMB の絶対アドレス
BL (失敗時) 80h: この機能は実装されていない
  0A2h: ハンドルは無効
  0ACh: ロックされている EMB が多すぎる
  0ADh: その他の理由でロックできない

ロックできる EMB の数には限りがあります。 ロックは最小限に抑え、早めに解除してください。

EMB のアンロック

パラメータ

レジスタ
AH 0Dh
DX ハンドル

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  0A2h: ハンドルは無効
  0AAh: EMB はロックされていない

EMB の情報取得

パラメータ

レジスタ
AH 0Eh
DX ハンドル

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (成功時) EMB のロックカウント
BH EMB の空きハンドル数
DX 指定 EMB のサイズ (kBytes)
BL (失敗時) 80h: この機能は実装されていない
  0A2h: ハンドルは無効

EMB の再割り当て

パラメータ

レジスタ
AH 0Fh
BX 新しいサイズ (kBytes)
DX ハンドル

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  0A1h: ハンドル数が足りない
  0A2h: ハンドルは無効
  0ABh: EMB はロックされている

再割り当て時に一時的にハンドルを確保するので余裕が必要です。 容量を減らした場合には、上位アドレスの情報が切り捨てられます。

UMB の割り当て

パラメータ

レジスタ
AH 10h
DX サイズ (×16 Bytes)

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BX (成功時) 割り当てられたセグメントアドレス
DX 割り当てられた UMB のサイズ (×16 Bytes)
BL (失敗時) 80h: この機能は実装されていない
  0B0h: UMB の空き容量はない
  0B1h: 利用可能な UMB がない
DX 利用可能な UMB の最大サイズ (×16 Bytes)

INT 21h のファンクションコールと混在利用してはいけません。

利用可能な最大 UMB サイズは DX=0FFFFh を指定して失敗することで求められます。

UMB の解放

パラメータ

レジスタ
AH 11h
DX 解放したい UMB のセグメントアドレス

戻り値

レジスタ
AX 0001h: 成功
  0000h: 失敗 BL に理由を示す値がある
BL (失敗時) 80h: この機能は実装されていない
  0B2h: セグメントアドレスは無効

参考