私がMS-DOSでプログラムしていて出会った注意点など書いていこうと思います。
目次
タイマ値の取得について(AT)
AT互換機のBIOSには、毎秒18.2回カウントアップするカウンタ値の取得・設定のサービスがあります。シビアなスケジューリングを要求されないプログラムならば、タイムアウトに使うのに便利です。しかし、このコールをDOS上で使うのには注意が必要です。
MS-DOSでは起動時にRTCより日付・時間を読み取った後は、このBIOSが返すカウンタ値を基に自分で時間を算出します。パソコンのRTCとは無関係のようです。(RTCを見るのは最初だけ)
仮にこのカウンタ値を書き換えると、DOS上での時間はあっという間に狂ってしまいます。
この程度ならばカウンタ値の読出オンリーで使えば良いのではないか、ということになりますがそうもいきません。このBIOSコールでは、前回呼出してから日付を跨いでいると、あるフラグが立って返って来るようになっています。
MS-DOSはこのフラグを使って日付更新を行なっているのです。他のアプリケーションがBIOSコールすることを想定していません。他のソフトが日付をまたぐフラグを受け取ってしまうと、MS-DOSの日付が更新されない自体が起こってしまいます。
ですから、終日動かして日付情報を扱うプログラムは、このBIOSコールを使ってはいけません。
私は、18.2回/秒発生する INT 1Ch の割込をフックして自前のカウンタを動かすことで回避しました。
参考) BIOS 1Ah/ AH = 0x00 BC++) biostime()
CAPS,NUM,SCROLLのON/OFFについて(AT)
AT互換機のBIOSにはキーボードBIOS(16H)があり、左右のALT,CTRLの押下や、CAPS状態など読み出すことが出来ますが、CAPSを制御するファンクションは用意されていません。
linuxなどであればsetledsで設定する方法がすぐに見つかりましたが、DOSとなるとなかなか見つかりません。そこで海外サイトに目を向けて探してみたところ、いくつか見つかりました。
そのうちの一つを逆アセンブルしたところ、設定方法が分かりました。せっかくですので、ここに設定方法を書いておきます。
アドレス[0040:0017]の内容を下表に従ってでビット設定*1します。
bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
key | - | CAPS | NUM | SCROLL | - | - | - | - |
ちなみに、キーボードからは、CAPS押下とLED点灯は別になってるのが基本のようです(NUMやSCROLLも)。押下情報をBIOSが受け、LED点灯コマンドをキーボードへ送る、というようなやりとり。つまり、CAPSのON/OFFはBIOSで管理してるわけです。
ですので、上表のようにBIOSのワークエリアを直接書き換える必要があるのです。