そもそも 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 は HMA、EMB、UMB の領域からなります。
- 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_CALL
を CALL 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 バージョンの取得
利用可能な機能を確認するためにバージョン情報を確認する必要があります。
戻り値
レジスタ |
値 |
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 の解放
戻り値
レジスタ |
値 |
AX |
0001h: 成功 解放した |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
90h: HMA が存在していない |
|
93h: HMA は割り当てられていない |
A20 ラインのグローバルな有効化
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
82h: A20 のエラー |
A20 ラインのグローバルな無効化
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
82h: A20 のエラー |
|
94h: A20 が有効化されていない |
A20 ラインのローカルな有効化
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
82h: A20 のエラー |
A20 ラインのローカルな無効化
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
82h: A20 のエラー |
|
94h: A20 が有効化されていない |
A20 ラインの状態を取得
戻り値
レジスタ |
値 |
AX |
0000h: 無効 |
|
0001h: 有効 |
BL |
00h: 成功 |
|
80h: この機能は実装されていない |
EMB の空き容量を取得
戻り値
レジスタ |
値 |
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 の解放
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
DX |
ハンドル (失敗時は 0000h) |
BL (失敗時) |
80h: この機能は実装されていない |
|
0A2h: ハンドルは無効 |
|
0A3h: EMB がロックされている |
EMB のコピー
パラメータ
レジスタ |
値 |
AH |
0Bh |
DS:SI |
コピーパラメータを格納しているアドレス |
コピーパラメータ
名前 | データサイズ | 内容 |
Length | DWORD | コピーするバイト数 |
SourceHandle | WORD | コピー元ハンドル |
SourceOffset | DWORD | コピー元オフセット |
DestHandle | WORD | コピー先ハンドル |
DestOffset | DWORD | コピー先オフセット |
戻り値
レジスタ |
値 |
AH |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
82h: A20 のエラー |
|
0A3h: SourceHandle が無効 |
|
0A4h: SourceOffset が無効 |
|
0A5h: DestHandle が無効 |
|
0A6h: DestOffset が無効 |
|
0A7h: Length が無効 |
|
0A8h: 無効な重複部分がある |
|
0A9h: パリティエラー |
偶数番地→偶数番地 (偶数バイト) だと高速に処理されるかもしれません。
x386 以降では四倍数番地→四倍数番地だと高速に処理されるかもしれません。
下位から上位に向かってコピーされます。
コピー元とコピー先が重複する領域にある場合は注意が必要です。
コンベンショナルメモリのハンドル番号は 0000h です。
EMB のロック
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
DX:BX |
ロックされた EMB の絶対アドレス |
BL (失敗時) |
80h: この機能は実装されていない |
|
0A2h: ハンドルは無効 |
|
0ACh: ロックされている EMB が多すぎる |
|
0ADh: その他の理由でロックできない |
ロックできる EMB の数には限りがあります。
ロックは最小限に抑え、早めに解除してください。
EMB のアンロック
戻り値
レジスタ |
値 |
AX |
0001h: 成功 |
|
0000h: 失敗 BL に理由を示す値がある |
BL (失敗時) |
80h: この機能は実装されていない |
|
0A2h: ハンドルは無効 |
|
0AAh: EMB はロックされていない |
EMB の情報取得
戻り値
レジスタ |
値 |
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: セグメントアドレスは無効 |