このページはOS-Wikiのページのコピーです。

OSを作るときによく使うBIOSファンクション (AT互換機)

  • まあOSの完成度が上がってきて32bitモードになったらもはや不要なものが大半になってしまうと思いますが、ブートセクタやOS作り始めのときは使うかなあというものを。

INT(0x10); ビデオ関係

  • ビデオモード設定
    • AH = 0x00;
    • AL = モード: (マイナーな画面モードは省略しています)
      • 0x03:16色テキスト、80x25
      • 0x12:VGAグラフィックス、640x480x4bitカラー、独自プレーンアクセス
      • 0x13:VGAグラフィックス、320x200x8bitカラー、パックドピクセル
      • 0x6a:拡張VGAグラフィックス、800x600x4bitカラー、独自プレーンアクセス(ビデオカードによってはサポートされない)
    • 戻り値:なし
  • カーソル形状設定
    • AH = 0x01;
    • CH = 開始ライン;
    • CL = 終了ライン;
      • CH < CLだと1つの部分からなる普通のカーソル
      • CH > CLだと2つの部分からなるカーソル
      • CH == 0x20だとカーソルは表示されない
    • 戻り値:なし
  • カーソル位置指定
    • AH = 0x02;
    • BH = 0;
    • DL = x座標;
    • DH = y座標;
    • 戻り値:なし
  • 1ドット書き込み
    • (速度のことを考えると、これを使うくらいなら自分でVRAMアクセスするほうがはるかにマシ)
    • AH = 0x0c;
    • AL = カラーコード;
    • CX = x座標;
    • DX = y座標;
    • 戻り値:なし
  • 一文字表示
    • AH = 0x0e;
    • AL = キャラクターコード;
    • BH = 0;
    • BL = カラーコード;
    • 戻り値:なし
    • 註:ビープ、バックスペース、CR、LFは制御コードとして認識される
  • カラーコードとパレット番号の対応づけみたいなやつ
    • 16色モードのときに使われる。256色モードのときはこの設定は関係ない。
    • AX = 0x1000;
    • BL = カラーコード; (0~15)
    • BH = パレットコード; (0~63)
    • 註:EGA時代との互換の関係でこのファンクションが必要になっています。
    • 結構混乱すると思いますので、とにかく最初にカラーコード0~15がそれぞれパレットコード0~15になるように設定してしまうのが、ややこしくなくていいと思います。
    • そうなってしまえば、カラーコード==パレットコードになって変なことで悩まなくて済みます。
  • パレット設定
    • AX = 0x1010;
    • BX = パレット番号; (0~255)
    • DH = Red; (0~0x3f)
    • CH = Green; (0~0x3f)
    • CL = Blue; (0~0x3f)
    • 戻り値:なし
  • 文字列表示
    • AH = 0x13;
    • AL = オプション:
      • 0x00:文字列のカラーはBLで指定、カーソル位置は変化しない
      • 0x01:文字列のカラーはBLで指定、カーソル位置は進む
      • 0x02:文字列中にカラー属性が書き込まれている、カーソル位置は変化しない
      • 0x03:文字列中にカラー属性が書き込まれている、カーソル位置は進む
      • [文字コード] [カラーコード] [文字コード] [カラーコード]...みたいな感じ
    • BH = 0;
    • BL = カラーコード; (オプションが0x00、0x01の場合のみ)
    • CX = 文字列の長さ;
    • DL = x座標;
    • DH = y座標;
    • ES:BP = 文字列のアドレス;
    • 戻り値:なし
  • おまけ:一番簡単な画面モード0x13の使い方
    • このモードは解像度が荒いですが、パックドピクセルなのでとても簡単に扱えます。まず画面モードを切り替えて、そんでもってパレットを設定してしまいましょう。
    • VRAMは0xa0000~0xaffffの64KBです。厳密に言うと、320x200=64000なので、62.5KBですが。1ドット==1バイトですので、がしがしライトしてください。リードもOKです。たるいBIOSで1点ずつ描いていく必要はありません。以上!

INT(0x11); 周辺機器リストの取得

  • 周辺機器リストの取得
    • 呼び出しパラメータ不要
    • 戻り値:
    • AX == 周辺機器リスト
      • 多分使う人いないと思うので、詳細省略。

INT(0x12); 使用可能メモリのサイズ取得

  • 使用可能メモリのサイズ取得
    • 呼び出しパラメータ不要
    • 戻り値:
    • AX == メモリサイズ (KB単位)

INT(0x13); ディスク関係

  • システムのリセット
    • AH = 0x00;
    • DL = ドライブ番号; (0x00~0x7f:FDD、0x80~0xff:HDD)
    • 戻り値:
    • FLAGS.CF == 0 : エラーなし
    • FLAGS.CF == 1 : エラーあり、AHにエラーコード
      • エラーコード (FDDでもHDDでも発生しうるもの)
      • 0x01:無効なコマンド
      • 0x02:アドレスマークが見付からない
      • 0x04:セクタが見付からない
      • 0x09:DMAが64KB境界を越えた
      • 0x10:データエラー
      • 0x20:コントローラ異常
      • 0x40:シーク失敗
      • 0x80:タイムアウト
      • エラーコード (FDDでのみ発生しうるもの)
      • 0x03:ライトプロテクト書き込みエラー
      • 0x06:ディスクが入ってない
      • 0x08:DMAオーバーフロー
      • エラーコード (HDDのみで発生しうるもの)
      • 0x05:リセット失敗
      • 0x07:パラメータテーブルが不正
      • 0x0a:セクタフラグが不正
      • 0x11:ECCデータエラー
      • 0xaa:ドライブの準備ができていない
      • 0xbb:未定義エラー
      • 0xcc:書き込みエラー
      • 0xe0:ステータスエラー
  • ディスクからの読み込み、ディスクへの書き込み、セクタのベリファイ、およびシーク
    • AH = 0x02; (読み込み時)
    • AH = 0x03; (書き込み時)
    • AH = 0x04; (ベリファイ時)
    • AH = 0x0c; (シーク時)
    • AL = 処理するセクタ数; (連続したセクタを処理できる)
    • CH = シリンダ番号 & 0xff;
    • CL = セクタ番号(bit0-5) | (シリンダ番号 & 0x300) >> 2;
    • DH = ヘッド番号;
    • DL = ドライブ番号;
    • ES:BX = バッファアドレス; (ベリファイ時、シーク時にはこれは参照しない)
    • 戻り値:
    • FLAGS.CF == 0 : エラーなし、AH == 0
    • FLAGS.CF == 1 : エラーあり、AHにエラーコード(リセットファンクションと同じ)
    • 補足:
      • 処理するセクタ数は0x01~0xffの範囲で指定 (0x02以上を指定するときは、連続処理できる条件があるかもしれないので注意 -- FDの場合は、たぶん、複数のトラックにはまたがれないし、64KB境界をこえてもいけない、だと思います)
      • セクタ番号は0x01~0xffの範囲で指定 (FDの場合は0x01~0x12)
      • シリンダ番号は0x000~0x3ffの範囲で指定 (FDの場合は0x00~0x4f)
      • ヘッド番号は0x00~0xffの範囲で指定 (FDの場合は0x00~0x01)
      • シークしてからアクセスしなければいけないというわけではない
      • HDDへのアクセスの場合、BIOSはパーティションを理解せず、ハード的に1台のデバイスを1ドライブとして扱う事に注意すること。パーティション処理が必要なら自分でやるのだ。
      • BIOSのせいだったかどうか忘れましたが、FDDのブートセクタをリードするとなぜか0x03~0x0aの8バイトの内容だけが正しく読み込まれません(変なごみが入っている)。I/Oを自分で制御してFDCをコントロールしたときはこんな変なことは起きません。
  • ドライブパラメータ取得
    • AH = 0x08;
    • DL = ドライブ番号;
    • 戻り値:
    • AX == 0, BH == 0
    • BL == ドライブタイプ
    • CH == 指定可能な最大シリンダ番号 & 0xff
    • CL == 指定可能な最大セクタ番号(bit0-5) | (指定可能な最大シリンダ番号 & 0x300) >> 2
    • DH == 指定可能な最大ヘッド番号
    • DL == インストールされているドライブ数
    • ES:DI == FDDパラメータテーブルのアドレス (これはなに?)
    • 補足:LBA == (Sec - 1) + Hed * Max_Sec + Cyl * (Max_Hed + 1) * Max_Sec
      • 変則的なジオメトリを指定している場合はこの限りではないが
    • 補足:BIOSによっては、戻り値のAX == 0を保証しない
  • HDDパラメータテーブルの初期化 (ってなに?)
    • AH = 0x09;
    • 戻り値:なし
  • ドライブレディーのテスト
    • AH = 0x10;
    • DL = ドライブ番号;
    • 戻り値:
    • AH == ステータス (エラーコードと同じ?)
  • ドライブの正規化 (seek cylinder zeroってことかな?)
    • AH = 0x11;
    • DL = ドライブ番号;
    • 戻り値:
    • AH == ステータス
  • コントローラの診断
    • AH = 0x14;
    • 戻り値:
    • AH == ステータス
  • ディスクタイプ取得
    • AH = 0x15;
    • DL = ドライブ番号;
    • 戻り値:
    • AH == ドライブタイプコード:
      • 0x00:ドライブは全く存在しない
      • 0x01:メディア交換検出不能なFDD
      • 0x02:メディア交換検出可能なFDD
      • 0x03:HDD
    • (HDDの場合のみ)CX:DX == 総セクタ数
  • FDの交換チェック
    • AH = 0x16;
    • DL = ドライブ番号;
    • 戻り値:
    • AH == 0x00 : 交換されてない
    • AH == 0x06 : 交換された
  • FDのディスクタイプの設定
    • AH = 0x17;
    • DL = ドライブ番号;
    • AL = タイプコード;
    • 戻り値:なし
  • FDの物理フォーマット
    • AH = 0x05;
    • AL = 0x12;
    • CH = シリンダ;
    • DH = ヘッド;
    • DL = ドライブ番号;
    • ES:BX = バッファアドレス;
    • バッファは72バイトで、次の内容にする(4バイトx18個)
      • [シリンダ ヘッド 0x01 0x02] [シリンダ ヘッド 0x02 0x02] [シリンダ ヘッド 0x03 0x02] ... [シリンダ ヘッド 0x12 0x02]
    • 戻り値:
    • FLAGS.CF == 0 : エラーなし、AH == 0
    • FLAGS.CF == 1 : エラーあり、AHにエラーコード
    • 補足:この機能によって1トラックだけフォーマットされる。ということで、実際のフォーマットでは、シリンダとヘッダを変化させつつ(だからその都度バッファも作り直して)、合計160トラックをフォーマットしなければいけない。
  • 拡張INT13Hの存在確認
    • AH = 0x41;
    • DL = ドライブ番号;
      • 拡張INT13Hで使えるドライブ番号は0x80~0xffのみ
    • BX = 0x55aa;
    • 戻り値:
    • FLAGS.CF == 0 : 拡張INT13Hに対応している
    • FLAGS.CF == 1 : 拡張INT13Hに対応していない
    • (対応している場合)BX == 0xaa55 : 拡張IN13Hはインストールされている
    • (対応している場合)BX != 0xaa55 : 拡張IN13Hはインストールされていない
    • (対応している場合)CL.bit0 == 1 : 拡張ディスクアクセスをサポートしている
    • (対応している場合)CL.bit0 == 0 : 拡張ディスクアクセスをサポートしていない
  • 拡張ディスクリード
    • AH = 0x42;
    • DL = ドライブ番号;
    • DS:SI = 以下の構造体へのポインタ
      オフセット長さ内容
      +0x00w0x0010 (構造体の長さ)
      +0x02wリードするセクタ数(1~)
      +0x04wバッファのオフセット
      +0x06wバッファのセグメントセレクタ
      +0x088bytes64bit-LBA
    • 戻り値:
    • FLAGS.CF == 0 : エラーなし
    • FLAGS.CF == 1 : エラーあり
  • 拡張ディスクライト
    • AH = 0x43;
  • 拡張ディスクベリファイ
    • AH = 0x44;
  • 拡張ドライブロック制御
    • AH = 0x45;
  • 拡張メディアイジェクト制御
    • AH = 0x46;
  • 拡張シーク
    • AH = 0x47;
  • 拡張ドライブパラメータ
    • AH = 0x48;
    • DL = ドライブ番号;
    • DS:SI = 以下の構造体を格納するためのポインタ
      オフセット長さ内容
      +0x00w構造体の長さ 0x1a以上(呼び出し時には受け取れる最大サイズを書いておく)
      +0x02wフラグ
      +0x04d物理シリンダ数
      +0x08d物理ヘッド数
      +0x0cd物理セクタ数
      +0x108bytes総セクタ数
      +0x18wセクタ長
      • フラグbit0:DMA境界エラーが発生するかどうか
      • フラグbit1:物理シリンダ数、物理ヘッド数、物理セクタ数、セクタ長の情報が有効かどうか
      • フラグbit2:リムーバブルドライブかどうか
      • フラグbit3:ベリファイ付きライトをサポートしているかどうか
    • 戻り値:
    • FLAGS.CF == 0 : エラーなし
    • FLAGS.CF == 1 : エラーあり
  • 拡張ディスク交換
    • AH = 0x49;
  • 起動可能CD-ROMのディスクエミュレーション開始
    • AH = 0x4a;
  • 起動可能CD-ROMのディスクエミュレーション終了
    • AH = 0x4b;
  • 起動可能CD-ROMのステータス読み込み
    • AH = 0x4b;
  • 起動可能CD-ROMのディスクエミュレーション開始と起動
    • AH = 0x4c;
  • 起動可能CD-ROMのブート一覧の取得
    • AH = 0x4d;

INT(0x14); シリアルポート

  • ポートの初期化
    • AH = 0x00;
    • AL = BBBPPSCC:
      • BBBの部分(ボーレイト):111=9600bps, 110=4800bps, 101=2400bps, 100=1200bps, 011=600bps, 010=300bps, 001=150bps, 000=110bps
      • PPの部分(パリティ):00=なし, 01=奇数, 10=なし, 11=偶数
      • Sの部分(ストップビット):0=ストップビット1bit, 1=ストップビット2bit
      • CCの部分(キャラクターサイズ):10=7bit, 11=8bit
    • DX = ポート番号; (たとえば0)
    • 戻り値:なし
  • 一文字送信
    • AH = 0x01;
    • AL = 送信する文字;
    • DX = ポート番号;
    • 戻り値:
    • AH == 0ならエラーなし
  • 一文字受信
    • AH = 0x02;
    • DX = ポート番号;
    • 戻り値:
    • AH == 0ならエラーなし。
    • AL == 受信した文字。
  • ステータス取得
    • AH = 0x03;
    • DX = ポート番号;
    • 戻り値:
    • AX == ステータス;

INT(0x15); その他のサービス

  • カセットモータをON
    • AH = 0x00;
    • この機能は誰も使わないと思うので詳細省略。
  • カセットモータをOFF
    • AH = 0x01;
    • この機能は誰も使わないと思うので詳細省略。
  • カセットからデータの読み出し
    • AH = 0x02;
    • この機能は誰も使わないと思うので詳細省略。
  • カセットへのデータの書き込み
    • AH = 0x03;
    • この機能は誰も使わないと思うので詳細省略。
  • APM制御
    • AH = 0x53;
    • 詳細はAPMのページへ。

INT(0x16); キーボード関係

  • 文字読み出し
    • AH = 0x00;
    • 戻り値:
    • AL == ASCIIコード, AH == キーボードスキャンコード
    • もしくは、AL == 0, AH == 拡張ASCIIコード
    • 註:キーバッファが空のときは、文字入力があるまで帰ってこない
  • キーバッファ状態チェック
    • AH = 0x01;
    • 戻り値:
    • FLAGS.ZF == 0:バッファに文字がある、1:バッファに文字がない
    • AL, AHには文字読み出しと同じコードが入る。しかし、この文字はまだバッファに残ったままになる。
    • 註:キーバッファが空でもすぐ帰ってくる。
  • キーロック&シフト状態取得
    • AH = 0x02;
    • 戻り値:
    • AL == 状態コード:
      • bit0:右シフト
      • bit1:左シフト
      • bit2:Ctrl
      • bit3:Alt
      • bit4:Scrollロック
      • bit5:Numロック
      • bit6:Capsロック
      • bit7:Insertモード

INT(0x17); パラレルポート

  • 1バイト出力
    • AH = 0x00;
    • AL = 出力データ;
    • DX = ポート番号;
    • 戻り値:
    • AH == ステータス:
      • bit0:タイムアウト
      • bit1:リザーブ
      • bit2:リザーブ
      • bit3:I/Oエラー
      • bit4:プリンタがセレクトされている
      • bit5:用紙切れ
      • bit6:アクノリッジ
      • bit7:ビジーフラグ(0:ビジー、1:ノットビジー)
  • ポート初期化
    • AH = 0x01;
    • DX = ポート番号;
    • 戻り値:
    • AH == ステータス
  • ステータス取得
    • AH = 0x02;
    • DX = ポート番号;
    • 戻り値:
    • AH == ステータス

INT(0x18); ROM-BASICを起動

  • パラメータなし。多分呼び出したら帰ってきません。
  • Kはブートに失敗したらこいつを呼び出すようにしています。
  • 実際のところ、最近のAT互換機はROM-BASICなんて持っていないわけで、これをやったら何が起こるのか、Kにもよくわかっていません(そんな認識のくせに使っていいのかよ!・・・苦笑)。
    • 後日談:Think Pad 770で試してみました。変な数字がでてハングアップするようです。

INT(0x19); 再起動

  • パラメータなし。多分呼び出したら帰ってきません。

INT(0x1a); 時間関係

  • クロックカウント読み出し
    • AH = 0x00;
    • 戻り値:
    • AL == 午前零時シグナル
    • CX:DX == カウント
    • (補足)
      • カウントは、54.95ミリ秒ごとに1づつ増えていきます。
      • 午前零時シグナルというのは、前回AH=0x00のINT(0x1a)をやってから午前零時をまたいだかどうかを知らせるためのもので、またいでいなかったら0、またいでいたら非零を返します。
  • クロックカウント設定
    • AH = 0x01;
    • CX:DX = カウント;
    • 戻り値:なし
  • リアルタイムクロック時刻読み出し
    • AH = 0x02;
    • 戻り値:
    • FLAGS.CF == 0:RTCは動作中、1:RTCは停止中
    • CH == 時(BCD)
    • CL == 分(BCD)
    • DH == 秒(BCD)
  • リアルタイムクロック時刻設定
    • AH = 0x03;
    • CH = 時(BCD)
    • CL = 分(BCD)
    • DH = 秒(BCD)
    • DL = 0x00:標準時
    • DL = 0x01:夏時間
    • 戻り値:なし
  • リアルタイムクロック日付読み出し
    • AH = 0x04;
    • 戻り値:
    • FLAGS.CF == 0:RTCは動作中、1:RTCは停止中
    • CH == 世紀(BCD)(0x19か0x20)
    • CL == 年(BCD)
    • DH == 月(BCD)
    • DL == 日(BCD)
  • リアルタイムクロック日付設定
    • AH = 0x05;
    • CH = 世紀(BCD)(0x19か0x20)
    • CL = 年(BCD)
    • DH = 月(BCD)
    • DL = 日(BCD)
    • 戻り値:なし

そのほかの代表的なベクタ

  • INT(0x1b); Ctrl-Breakハンドラ
  • INT(0x1c); タイマー割り込みハンドラ
  • INT(0x1d); ビデオパラメータのポインタ
  • INT(0x1e); ディスクパラメータのポインタ
  • INT(0x1f); グラフィックスキャラクタテーブル

こめんと欄

  • 間違いを発見したり、補足することを見つけたら教えてください。 -- K 2003-06-29 (日) 15:33:45
  • もっと詳しいのはこっちかな。http://hp.vector.co.jp/authors/VA003720/lpproj/int10h/int10h.htm -- K 2003-06-29 (日) 16:26:04
  • まとめておいてあるのは嬉しいです。 -- ぐりぽん 2003-07-05 (土) 18:52:09
  • お役に立てば幸いです。 -- K 2003-07-05 (土) 19:45:05
  • INT18はINT19が失敗したときに呼び出されるので、例えばディスクレスマシンでフロッピーが入ってないときだけネットブートさせたいときに、EtherbootをINT18をフックするようにconfigして使う.のだと思う。 -- 通りすがり 2003-08-28 (木) 20:05:28
  • 情報ありがとうございます。ってことは、ブートに失敗したらINT(0x18);をやるっていう僕のブートセクタの方針は、悪くないのかもしれませんね。 -- K 2003-08-29 (金) 13:08:14
  • http://lrs.fmi.uni-passau.de/support/doc/interrupt-57/INT.HTM -- 2004-04-01 (木) 00:40:06
  • そうですね。僕もブートセクタでは失敗したらint 0x18です。また、VMWare(Trial)では、int 0x18を呼び出すと、"Operating System Not Found"(だったと思う)と表示されてVMWareの警告が表示されます。 -- ''SZ-09]]( http://riact.sourceforge.jp/ ) 2004-05-10 (月) 19:04:17
  • 情報ありがとうございます。 -- K 2004-05-10 (月) 21:20:28
  • BIOSでのマウス制御ってInt何hを使えばいいのでしょうか?又、その時のレジスタの内容等も教えていただければ幸いです。 -- MiSt 2004-08-23 (月) 15:41:23
  • 僕の記憶では、AT互換機のBIOSはマウスをサポートしていません。もしかしたら記憶違いかもしれませんが。 -- K 2004-08-23 (月) 20:51:10
  • そうなんですか。じゃあ、自分でドライヴァ書かなきゃ駄目か・・・ -- MiSt 2004-08-23 (月) 21:15:45
  • ご回答ありがとうございました。 -- MiSt 2004-08-23 (月) 21:16:04
  • http://gladir.multimania.com/ に PS/2 マウスのBIOSを使ったサンプルがあります。但しフランス語です・・・ -- 名無しさん 2004-09-01 (水) 14:30:03
  • 上は間違いです。すみません、正しくは http://membres.lycos.fr/gladir/asmmouse.htm -- 名無しさん 2004-09-01 (水) 14:50:27
  • どうもありがとうございます。フランス語でも見てみますw -- MiSt 2004-10-08 (金) 22:31:57
  • BIOSといえばココ! http://www.bioscentral.com/ -- 名無しさん 2004-11-05 (金) 12:35:55
  • INT 15h,function E820h:ACPI対応のメモリマップ取得関数、E801h/88h:昔のメモリサイズ取得関数 -- 名無しさん 2004-11-06 (土) 01:33:17
  • イーサネット -- 名無しさん 2004-12-14 (火) 10:05:47
  • Int16hのバッファチェックのFLAGS.ZFが逆じゃないですか? -- 名無しさん 2005-03-13 (日) 18:34:24
  • ごめんなさい。あってました。 -- 名無しさん 2005-03-13 (日) 18:54:07
  • INT13Hの使い方を調べていたらこのページにつきました。現在、OSを作っています? -- mac 2005-12-11 (日) 12:24:26
  • 今更ですが、mouse BIOS INT 15h CH=0C2h, CL=00h: en/dis, CL=01h: reset, CL=02:setSampleRate CL=03h:setResolution, CL=07:setUserHandler,,,,などなど。見にくくてすいません。 -- 名無しさん 2005-12-20 (火) 20:29:25
  • ThinkPad 770でINT18Hを使って出てきたのは多分"I999030?"だと思います。?は、1だったらHDDエラー、2だったら無効なHDDブートレコード、5だったら -- mac 2006-02-11 (土) 10:07:10
  • ブート不可能な装置です。間違えて区切ってしまいまいました。 -- mac 2006-02-11 (土) 10:09:21
  • あの・・・ディスク関係についてなんですけど、どうやったら、全体容量が分かるか教えていただけませんか? -- Clover 2006-06-07 (水) 15:23:19
  • 普通は各ファイルシステムに問い合わせます。BIOSとは無関係です。ハードウェア的な最大容量を調べたいときは、上記のドライブパラメータ取得を使います。 -- K 2006-06-08 (木) 12:43:38

[Reload]   [New] [Edit] [Freeze] [Diff] [Upload]   [Front page] [List of pages] [Search] [Recent changes] [Backup]   [RSS of recent changes]
Last-modified: 2006/08/10 (Thu) 22:43:00 (6629d)