Skip to content

DOS Functions

Masakazu Yonehara edited this page Aug 24, 2026 · 5 revisions

DOS ファンクション (INT 21h)

ファイルの読み書き、画面出力、日付の取得などは INT 21h で行います。 AH に機能番号を入れて呼び出します。

このページの内容は FreeDOS(98) と NEC MS-DOS 6.20 の両方で実測し、 違いがあるものは明記しています。

基本

  • 機能番号は AH に入れます
  • 成否は キャリーフラグ (CF) で判断します。 CF = 1 なら失敗で、AX にエラーコードが入ります
  • ファイル名は 0 で終わる文字列を DS:DX で渡します
  • 開いたファイルは ハンドル(AH=0x3C や AH=0x3D が AX に返す値)で指し、 以降の読み書きでは BX に入れて渡します

前提条件

成功したとき、その機能が「返す」と決まっていないレジスタの中身は当てにできません。 実測では、同じ呼び出しでも FreeDOS と MS-DOS で違う値が残っていました。

呼び出し 成功後の AX(FreeDOS) 成功後の AX(MS-DOS)
AH=0x3E クローズ 0x3E10 0x3E05
AH=0x3E クローズ(2回目) 0x3E44 0x3E01
AH=0x41 削除 0x4102 0x0000

どちらも呼び出しは成功しています(CF = 0)。成否は CF だけで判断してください。

ファイルを作って書く

        mov     ah, 0x3C
        xor     cx, cx                  ; 属性=通常
        mov     dx, fname               ; DS:DX = ファイル名(0終端)
        int     0x21
        jc      .error                  ; CF=1 ならエラー。AX にエラーコード
        mov     bx, ax                  ; AX = ファイルハンドル

        mov     ah, 0x40
        mov     cx, 16                  ; 書くバイト数
        mov     dx, wbuf
        int     0x21
        jc      .error
        cmp     ax, 16                  ; 実際に書けた数を必ず確認する
        jne     .short_write

        mov     ah, 0x3E                ; 閉じる
        int     0x21
        jc      .error

AH=0x40 は 実際に書けたバイト数を AX に返します。 今回の測定では常に要求どおりの値でしたが、返り値である以上、 一致を確認しておくとディスクが足りない場合などに気づけます。

ファイルを読む

読み出しで開くときは AH=0x3D、AL=0x00(読み出しモード)です。

        mov     ah, 0x3D
        xor     al, al                  ; 0=読み出し
        mov     dx, fname
        int     0x21
        jc      .error
        mov     bx, ax

        mov     ah, 0x3F
        mov     cx, 16                  ; 読むバイト数
        mov     dx, rbuf
        int     0x21
        jc      .error
        ; AX = 実際に読めたバイト数。要求より少なければファイルの終わり

読み込み先のバッファは、あらかじめ目印になる値で埋めておくことをおすすめします。 0 で初期化してしまうと、「読まれなかった」のか「0 が読まれた」のか区別できません。

エラーの見分け方

CF = 1 のとき AX にエラーコードが入ります。実測で確認できたものです。

状況 AX
存在しないファイルを開いた 0x0002

DOS の種類とバージョンを調べる

AH = 0x30 を呼ぶと、バージョンと OEM 番号が返ります。

レジスタ 内容
AL メジャーバージョン
AH マイナーバージョン
BH OEM 番号

バージョン番号では FreeDOS(98) と NEC MS-DOS を区別できません。 実測では両方とも AL=0x06 AH=0x14(6.20)を返しました。

区別できるのは **BH(OEM 番号)**です。

DOS AX BH
FreeDOS(98) 0x1406(6.20) 0xFD
NEC MS-DOS 6.20 0x1406(6.20) 0xFF

FreeDOS(98) と NEC MS-DOS の違い

実測した範囲では、ファイル操作の挙動は一致しました。

項目 結果
ファイル作成 / 書き込み / クローズ / 読み出し / 削除 一致
書けた・読めたバイト数 一致
存在しないファイルを開いたときのエラーコード 一致(0x0002)
日付の取得 一致
OEM 番号 (AH=0x30 の BH) 違う(上記)
成功時の未定義な AX 違う(上記)

その他の呼び出し

AH 機能 返るもの
0x02 1文字出力 DL の文字を表示
0x09 文字列出力 DS:DX の文字列を $ まで表示
0x19 カレントドライブ AL(0 が A:)
0x2A 日付取得 CX=年 DH=月 DL=日 AL=曜日
0x4C 終了 AL が終了コード

よくある間違い

  • CF を見ずに AX の値だけでエラーを判断する。 成功時の AX には 定義されていない値が残っていることがあり、DOS によって中身が違います。
  • バージョン番号で FreeDOS と MS-DOS を見分けようとする。 どちらも 6.20 を返します。 BH(OEM 番号)を見てください。
  • 読み込みバッファを 0 で初期化する。 読まれなかったのか 0 が読まれたのか 区別できなくなります。0xCC などの目印で埋めてください。
  • 書けた・読めたバイト数を確認しない。 これらは戻り値なので、 要求どおりとは限らないという前提で書いておくのが安全です。
  • ファイル名の終端を忘れる。 $ ではなく 0 で終わる文字列です (AH=0x09 の文字列出力だけが $ 終端で、紛らわしいので注意)。

実機との差異

現時点で確認できているものはありません。 ただし このページの測定はすべて np2kai 上で行っています。 実機での確認は行っていません。

未検証

  • AH=0x40 / AH=0x3F が要求より少ない値を返す条件
  • 拡張エラー情報 (AH=0x59)
  • ディレクトリ操作、シーク (AH=0x42)、FCB を使う古い系統の呼び出し
  • AH=0x4C の終了コードが呼び出し元にどう見えるか
  • 日付・時刻の設定系
  • FreeDOS と MS-DOS の差が出るその他の領域(今回測ったのは上表の範囲だけ)

検証: 2026-08-24 / WebNP2 327d061 (np2kai) / FreeDOS(98)(同梱 fd98_2hd.xdf)と NEC MS-DOS 6.20 の両方で実行 / 再現: guest/probes/DOSFN.ASM(測定), guest/probes/WIKIEX4.ASM(上の使用例)

使用例は実行して RESULT=OK を確認し、さらに存在しないドライブを指すよう改変した版で RESULT=NG1 になることも確認しています(検査が失敗を検出できることの確認)。

Clone this wiki locally