doc drawn up: 2003-05-25 .. 2006-03-25

DOS に関する覚え書き

MS-DOS 7.1 の HD 起動環境のための設定

(2006-03-25)

MS-DOS 7.1 とは Windows 98 から抜き出した DOS のこと。この MS-DOS 7.1 だけで構成した起動環境を HD (FD ではない)上に構築してみる。

DOS のシステムディスク(起動可能なディスク)を構成するために最低限必要なファイルは、io.sys、msdos.sys、command.com で、これに加えて sys コマンドによって IPL がディスクのセクタ 0 に適切に設定されているのが条件である。FD でも HD でも違いはない。

HD が FD の場合と違いが生じるのは、msdos.sys の内容についてである。

MS-DOS 7.1 の msdos.sys はかつての msdos.sys と違って、ほとんどプログラムとしての実体がない、単なるテキストの設定ファイルとなっている(詳細説明は割愛するが、MS-DOS は元々 io.sys と msdos.sys の 2 段構成で OS の中核を成していた)。

実際、FD 起動の場合、msdos.sys を 0 バイトの空のファイルにしても、MS-DOS を問題なく動作させることができる。

一方、HD 起動の場合は、そのままでは MS-DOS 7.1 が Win98 を起動しようとして FD の起動過程の場合と違いが生じるので、msdos.sys に設定を記述して多少は挙動を制御する必要がある。

例えば、msdos.sys が空ファイルの場合は、Win98 の起動ロゴが表示されてしまう。これを表示させないようにするには、[Options] という項目を設けて、Logo=0 というオプションを設定する必要がある。ところが、起動ロゴを非表示にすると、今度は、起動メニューの選択画面が表示されるようになる(実はこの画面は起動ロゴによって背後に隠されていただけで、元から表示されていたものである)。この起動メニューは Windows の GUI を起動するか、単に DOS の CUI を起動するか等を選択するためのものである。当然、MS-DOS 環境では DOS の CUI のみが必要なので、メニューを表示させるまでもない。このために BootGUI=0 を設定する。

他にもまだ多くの設定が可能だが(参照:AXCEL216 - MDGx Windows 95-98-ME Complete MSDOS.SYS Reference)、筆者の場合は、必要最低限だと思って設定しているのは以下のように 3 種類だけである。

[Options]
Logo=0
BootGUI=0
DisableLog=1

ちなみに、DisableLog=1 は起動過程を記録した BOOTLOG.TXT を作成しないようにするためのものである。必須の設定ではないが、これも Windows 環境のための機能であり、DOS 環境では不要である(FD 起動では元々作成されない)。

以上であり、msdos.sys の設定以外のことは FD 起動環境の場合と違いはないだろう。

jo.sys

(2004-01-28)

Win98 のインストール用起動 CD-ROM に含まれる、起動ディスクイメージを、diskcopy コマンドを利用するなどして FD 化して抽出してみた。すると、見慣れない jo.sys というファイルが存在することに気が付く。

この jo.sys は、インストール用起動 CD-ROM からブートする時に、最初に、そのまま CD-ROM からブートするか、それともハードディスク(C ドライブ)からブートするかを選択できる画面が表示されるが、その機能に関するもののようである。

通常の MS-DOS の起動プロセスでは io.sys が最初に読み込まれる仕様となっているが、この jo.sys は io.sys に先だって読まれるものなのかどうか、謎である。ただ、自分で El Torito 規格の起動 CD-ROM を作成する時に、利用する価値はあるかもしれない。

色々なパターンを組合せて調べてみたところ、io.sys を削除して FD の中に jo.sys だけが含まれるような状態にしても機能するので、jo.sys は io.sys に先だって読み込まれるものであることが判明した。そしてこれは jo.sys だけで実現されるものではなく、起動 CD-ROM から抽出した起動ディスクの IPL(セクタ 0 に存在する、最初に読み込まれる起動プログラム。通常はこのプログラムが io.sys を最初に読み込んで MS-DOS の起動プロセスを開始する)との共働によって実現されているらしいこともわかった。普通の起動ディスクに jo.sys をコピーしても jo.sys は無視されるからだ。つまり、この特殊な IPL を有する起動ディスクを作成した上で、jo.sys を含めなければならない。

特殊な IPL は、抽出した特殊な IPL を持つ起動ディスクを diskcopy コマンドでディスクイメージ丸ごとコピーするか(単に xcopy コマンド等でファイル構成をコピーしても IPL はコピーされないので無効である)、この特殊な IPL で起動された MS-DOS 下で sys コマンドでシステムファイル転送を行うか、同じくこの特殊な IPL で起動された MS-DOS 下で format /s(/s オプション付きの format)コマンドを使ってディスクをフォーマットするかすれば、これ(特殊な IPL)を持った新しいディスクを作成することができるものと思われる。

jo.sys によって表示された選択画面による選択が行われた後は、通常と同様に io.sys に制御が渡って起動プロセスが続けられるようだ。

jo_sys.exe (pass: ****): jo.sys を含む最小限の構成からなる特殊 IPL を持った起動 FD の自己解凍型イメージファイル(※自分個人で利用するためのファイルなので、パスワードがかかっていますので、他の人は利用できません。あしからず)。起動順にファイルを書き込んである(jo.sys, io.sys, msdos.sys, command.com の順)。また、jo.sys の属性は Archive/System/Hidden/Readonly に、command.com の属性は Archive/Readonly に設定。

xcopy.exe と xcopy32.exe

Win98 の xcopy.exe と xcopy32.exe には違いがないらしい。共に、Long File Name 対応(ただし、Windows 下の DOS 窓において。Native DOS 下では共に非対応)で、いずれも xcopy32.mod というファイルへの中継機能しかないようである。噂によると、xcopy32.mod の拡張子を .exe にすれば、単体で xcopy32(または xcopy)として動作する、という話もあったので実際に試してみたが確かにその通りのようだ。

なぜこのような無駄なことになっているのかと言うと、Microsoft は Win95 OSR2 で Long File Name 対応版の xcopy としてそれまでの xcopy はそのまま残して、xcopy32 をわざわざ別個に加えたことによるみたいである。結局、Win98 では Long File Name 対応は標準的なものとなり、xcopy の方も Long File Name 対応版、すなわち xcopy32 そのものと同じになったのだが、xcopy32 を前提にしてアプリケーションを作成しているユーザの存在を考慮して、xcopy/xcopy32 どちらのコマンドでも有効なようにこのような仕様にしただけのことのようである。

つまり、xcopy を使うために、xcopy.exe, xcopy32.exe, xcopy32.mod の 3 つのファイルを常にセットにして用意する必要はないわけである。

xcopy.exe のコマンドオプション

Win98(SE) の xcopy.exe のオプションは、ヘルプ情報によると以下の通り。ただしこれは、Windows の DOS 窓から xcopy を使った場合のもので、Native の MS-DOS 下で xcopy を使った場合は、一部のオプション([/A | /M] [/D:日付] [/P] [/S [/E]] [/V] [/W])しか使えない(/V オプションはコピー先の新ファイルが読み取り可能かどうかをベリファイするオプション)。:

XCOPY 送り側 [受け側] [/A | /M] [/D:日付] [/P] [/S [/E]] [/W] [/C] [/I] [/Q] [/F] [/L] [/H] [/R] [/T] [/U] [/K] [/N]

送り側
コピーするファイル(複数可)を指定。
受け側
新しいファイルの場所と名前を指定。
/A
アーカイブ属性のファイル(のみ)をコピーする。(送り側の)アーカイブ属性は解除されない。
/M
アーカイブ属性のファイル(のみ)をコピーする。(送り側の)アーカイブ属性は解除される。
/D:日付
指定された日付以降に変更されたファイルをコピーする。日付を指定しない場合は、送り側が受け側より新しいファイルだけがコピーされる。
/P
受け側のファイルを作成する前にプロンプトを表示する。
/S
空のディレクトリを除いて、サブディレクトリもコピーする。
/E
空のディレクトリも含めて、すべてのサブディレクトリをコピーする。/S /E と同じ意味。/T と同時に指定できる。
/W
コピーを開始する前に確認キーを入力するためのプロンプトを表示する。
/C
エラーが起きてもコピーを続ける。
/I
送り側のファイル・パス指定に該当するのが複数のファイルであり、受け側の指定に該当するファイル・パスが存在しない場合、受け側の指定をディレクトリへのパスとして解釈するのか、ワイルドカード指定されたファイルとして解釈するのかという問題が生じるので、通常はプロンプトで尋ねられる。このオプションを指定すると、常にディレクトリへのパス指定として解釈してコピーする。
/Q
コピー中にファイル名を表示しない。
/F
コピー中に受け側と送り側のパスおよびファイル名を表示する。
/L
コピーするファイルを表示する。
/H
隠し属性およびシステム属性のファイルもコピーする。
/R
受け側の同じファイルが書き込み禁止属性であっても上書きする。
/T
ディレクトリだけ作成してファイルはコピーしない(ディレクトリ・ツリーだけをコピーするために用いる)。空のディレクトリは作成されない。/T /E を指定すると、空のディレクトリも作成される。
/U
受け側に存在しているファイル(のみ)を更新する。
/K
属性をコピーする(このオプションを指定しない通常のコピーでは、受け側のファイルでは書き込み禁止属性が解除されたり、アーカイブ属性が追加されたりする)
/Y
確認のプロンプトを表示せずにファイルを上書きする。
/-Y
ファイルを上書きするか確認するためのプロンプトを表示する(デフォルトだが、環境変数の設定によってデフォルトが変更されているような場合において、明示的に指定するために用いる)。
/N
短いファイル名を使ってコピーする(長いファイル名未対応の古いDOSとの互換用)。

他、参考サイト:ニフティ・フォーラム『DOS/Vコマンド・リファレンス』

DOS の起動過程

OS も当然ながら、一種のプログラムである。そのプログラムは、データとして、HD、FD、CD-ROM 等のいずれかのディスクドライブ上に格納されている。OS を起動するには、コンピュータは、まず最初に OS の格納されているディスクドライブの特定の場所にアクセスし、OS のプログラムデータを読み込み、それをプログラムとして実行しなければならない。一旦、OS が読み込まれ実行されてしまえば、それ以降の制御の問題は、OS の設計の問題になる。

この OS プログラムデータを探し当てて読み込み、それを実行するまでの過程もまた、プログラムの実行によってなされる。それが M/B(マザーボード)の BIOS-ROM に記録されている BIOS プログラムの果たす役割である。

FD から OS を起動する場合、BIOS プログラムは、第 0 番目の FDD(すなわち A ドライブ)の FD の先頭すなわち第 0 番地セクタからプログラムデータを読み込み、実行して、以降の制御を委ねる(BIOS プログラムはここでその役目を終える)。この第 0 番地から始まるプログラムデータのことをブートプログラムと呼ぶ。ブートプログラムは厳密には OS そのものではないが、BIOS 側から見れば OS 側の管轄に所属するデータである。すなわち、ディスク上に記録されている OS が MS-DOS であれば MS-DOS 用のブートプログラムが、Win9x であれば Win9x 用のブートプログラムが、WinNT/2000/XP であれば WinNT/2000/XP 用のブートプログラムが、Linux であれば Linux 用のブートプログラムが、それぞれそのディスクの第 0 番地から始まる場所に記録・格納されているわけである。各 OS 本体は、それらの自分専用のブートプログラムによって起動され、常駐プログラムとして機能することになる。ブートプログラム自身は、BIOS プログラム同様に、OS の起動過程が終れば、その役割を果たし終ってメモリから姿を消し、常駐しない。そういう意味で、OS の管轄に所属するプログラムでありながら、OS 本体とは区別されているのである。

このブートプログラムは、一旦 OS が起動してしまってからは、見ることができない領域として扱われるのが(少なくとも Microsoft の OS では)普通である。ファイルシステムによってアクセス可能な領域は、第 0 番地から始まる一連のブートプログラムの領域の直後から始まっている。だから通常のファイルシステムを使ったファイルのコピー機能等によってはこのブートプログラムを抜き出したりすることはできない。MS-DOS の場合、format /s コマンドや、sys コマンドが、ブートプログラムのコピーのために用意されている。

format や sys を使う場合に注意しなければならないのは、format と sys は必ず同じバージョンの OS に添付された format.com や sys.com をセットで使わなくてはならないという点である。例えば、MS-DOS 6.2 で format した FD なり HD に、Win98 の sys.com でブートプログラムをコピーしても正常に機能しない可能性があるのである。同じバージョンの OS で format と sys を用いるか、format /s で format と sys を同時に行うかする必要があるのである。

Microsoft の OS の場合、ブートプログラムは、単なるプログラム本体だけでなくディスクパラメータ情報も含有する形で記録されている。プログラム本体を IPL (Initial Program Loader) と呼び、ディスクパラメータ情報部分を BPB (BIOS Parameter Block) と呼んで、区別することがある。sys コマンドがコピーするのは、ブートプログラム全体ではなく、このうちのプログラム本体すなわち IPL だけなのである。だから、MS-DOS 6.2 用にフォーマットされたファイルシステムを読み込んで OS を起動するには、MS-DOS 6.2 用の IPL が必要であり、Win98 用にフォーマットされたファイルシステムを読み込んで OS を起動するには Win98 用の IPL がそれぞれ必要なのである。sys コマンドを BPB と無関係に使ってしまうと、いくら IPL を書き直しても OS が起動しないという現象に陥る可能性があるのである。

Win2000 と Win98、MS-DOS 6.2 をマルチブート環境で使用していた人が、Win2000 のスキャンディスクによって Win98 と MS-DOS 6.2 のパーティションの BPB を書き換えられてしまい、Win98 と MS-DOS 6.2 が起動しなくなったというケースがインターネット上に報告されていた。その人は、一所懸命 sys コマンドを使って IPL さえ書き換えれば復旧するはずと信じて試行錯誤したらしいが、いかんせん BPB が Win2000 用のものに書き換えられているので、format しない限り、Win98 や MS-DOS 6.2 用の BPB に戻らないので、どうやっても上手く行かない。かといって format すれば、Win98 や MS-DOS 6.2 の環境全体が消失することになるので、format するわけにもいかないわけである。最終的には、BPB を直接いじって復旧したようである。(参照:どるこむ「DOSパーティションのIPLについて質問」)

さて、ブートプログラムによって最初に読み込まれ起動するプログラムは MS-DOS の場合、io.sys である。このプログラムから、ファイルシステムによって認識可能なれっきとしたファイルとしてアクセスすることのできるデータとして存在することになる。ブートプログラムの場合は、第 0 番地からの一連の場所に存在しなければならなかったが、この io.sys 以降の OS のシステムファイルは、あくまでも一個のファイルなので、そのデータの物理的な存在場所は FAT (File Allocation Table) によって管理され、我々ユーザにとっては「第何番地に存在するかどうか」ということは気にする必要がない。ファイル名さえ把握できればちゃんと機能するようになっている。sys コマンドは、先述のように IPL をコピーする以外にも、io.sys や msdos.sys、command.com のようなシステムファイルもついでにコピーしてくれるが、これらのコピーはユーザが行う通常のコピーと何ら違いはない。sys コマンドを使わずに、一つ一つのファイルをユーザが好きな順番でコピーしても同じことである。

ブートプログラムは、io.sys の次に msdos.sys を読み込む。基本的に io.sys と msdos.sys が一体となって、OS 本体すなわち「中核カーネル」として機能する。2 つのファイルに分けずに、最初から 1 つのファイル構成にしても構わないのだが、なぜ、io.sys → msdos.sys という 2 段構造になっているのだろうか。おそらく、元々 io.sys は昔の IBM-PC や NEC PC-9801 のように異なる複数の機種のハードウェア仕様に応じて別々に用意する必要があったからである。一方、msdos.sys は機種の違いとは関係がない共通のデータで、単に、MS-DOS 自身のヴァージョンの違いなどによって変更されることのあるファイルである。つまり、Microsoft では、機種特有の問題に関しては io.sys をバリエーションさせることによって対応し、MS-DOS 自体の改良は msdos.sys の改変によって対応するという風に区別することができるという、開発者側の便宜上の理由だったのだろう。だから結局は、Win98 の DOS においては、もはやそのような 2 分割の意義も薄れ、msdos.sys のデータ内容のほとんどが io.sys に併合され、msdos.sys 自体はほとんど空っぽの小さなテキストファイルと化している。

OS 本体(io.sys + msdos.sys からなるカーネル)の次に読み込まれるのは、config.sys である。config.sys は configuration すなわち OS の設定情報を記述したテキストファイルであり、メモリ管理等の OS の細かい挙動を設定し、ハードウェアのドライバ等を設定して組み込むために利用する。現在の Windows で言えば system.ini や win.ini のような役割を果たすものである。

ハードウェアのドライバというのは、TSR(常駐プログラム)として実行される(すなわち OS の機能の一端を担う)ことによって、その機能を実現するもののようである。config.sys に device / devicehigh として組み込むやり方と、autoexec.bat で load / loadhigh で組み込むやり方の 2 通りが考えられる。ユーザが取り組むことになるドライバは、メモリ管理用のドライバ、日本語キーボードを扱うためのドライバや、日本語表示用のディスプレイドライバ、マウスドライバ、サウンドカード用のドライバ、CD-ROM ドライブを扱うためのドライバといったようなところだろう(他にも、プリンタや、ネットワークも考えられる)。

config.sys の読み込みが終わると、次に OS 本体は、シェルプログラムとして command.com を読み込む(もちろん、 config.sys でシェルプログラムを別のプログラムに設定していたら、そのプログラムをシェルプログラムとして読み込むことになる)。そしてその command.com は、最初に(それが存在すれば)autoexec.bat を実行する。

autoexec.bat にも TSR として機能するようなドライバ関係のコマンドを記述することがある。例えば、mscdex.exe のような CD-ROM ドライバである(古いバージョンの MS-DOS では config.sys でも mscdex.exe を組み込むことができたらしいが、Win98 の MS-DOS では無理なようである)。

参考:Nobusan's Square「ブートの仕組み

(※)以下のファイルは自分個人で利用するためのファイルなので、パスワードがかかっていますので、他の人は利用できません。あしからず。

メモリ

DOS の初心者が最初に頭を悩ます種が、メモリ関連の設定ではないだろうか。メモリ、すなわち、コンベンショナル・メモリの問題である。

なぜ、DOS のメモリの問題が複雑なのかということには、IBM-PC の開発における歴史的な経緯が絡んでおり、そのことと併せて見ていかないと、単に現状のあるままを理解しようとしても「何でそのような仕組みにわざわざする必要があったのか」理解に苦しみ、さじを投げたくなっても不思議ではない気がする。かく言う僕も理解が十分とは言えないので本格的な解説は他の情報源に譲りたいところだが、乱暴に断じるとするならば、ともかく昔のメモリにはハードウェア的な容量に関する設計上の制限があり、さらにそのハードウェア的な制限を前提にして MS-DOS が設計されたため、ハード・ソフト両面の設計から生じる二重の制限が存在していたということなのである。それゆえコンベンショナル・メモリと呼ばれる、固定された容量のメモリの枠内に、プログラムを収めて実行する必要があったのだ。

そのようなコンベンショナル・メモリという制限を打破するための試みがハードウェア的な設計上の制限に対するアプローチ、ソフトウェア的な OS の設計上の制限に対するアプローチがそれぞれなされていって、段階的に改善されていったわけである。そのようにその経緯は段階的なものであったため、単にメモリの制限を打破すると言っても、やれ XMS だ EMS だ、HMA だとかメモリの領域についても色んな呼び方で区別されたり、hymem.sys や emm386.exe といったように複数のメモリマネージャを組み合わせて用いたりする必要があるのである。

まず、ハードウェア的なメモリの限界を解決するためには、himem.sys というメモリドライバを利用する。これによって一応、拡張された物理メモリにアクセス可能な状態となるが、リアルモードと呼ばれる古い MS-DOS の仕様に従って作成されたプログラムは拡張されたメモリ領域(メモリアドレス)に対応していないので、その場所にあるプログラムやデータを見ることができない。プロテクトモード対応か、EMS (Expanded Memory System)拡張メモリシステム 対応のプログラムでないと、拡張メモリを利用する大きなサイズのプログラムは実行不可能なのである。ちなみに EMS 対応プログラムを利用するには、himem.sys の他にさらに emm386.exe をメモリドライバとして組み込むことによって EMS を有効にする必要がある。

リアルモードプログラム用のメモリ、つまりコンベンショナル・メモリの空きをできるだけ多くするには、MS-DOS 本体やドライバをコンベンショナル・メモリ領域である 0-640KB の領域から追放する必要がある。とはいえ、これら MS-DOS 本体やドライバは、拡張メモリ領域には置くことは不可能で、あくまでも 1024KB のメモリ領域のうちの例外的な領域を利用することになる。その例外的な領域というのは、HMA (High Memory Area) と、UMB (Upper Memory Block) という 2 種類の領域である。HMA というのは 1024KB を超える拡張メモリの最初の領域にあり、これは拡張された物理メモリ上にありながら、例外的に CPU が物理的に(ハードウェアの設計上の機能として)以前から認識できたもの(単数)だが MS-DOS 側では元々タッチしなかったものである。次に、UMB というのは 640-1024KB の領域にあり、本来的にはビデオカードの VRAM 領域等に利用するために予約的に MS-DOS がタッチしないで確保しておいた領域であり、そのうち実際には使われずに遊んでいる部分(複数)である。これらの例外的な空き領域を利用可能な状態にして、そこに DOS 本体やドライバ等のメモリ常駐プログラムを退避することによって、できるだけコンベンショナル・メモリを大きく空けようとするわけである。HMA を利用可にするためには himem.sys が、UMB を利用可にするためには emm386.exe がドライバとしてあらかじめ組み込まれることが、それぞれ必要である。それらが組み込まれた後、DOS 本体は config.sys 内で dos=high,umb と記述することによって、ドライバは device= ではなく devicehigh= と記述することによって、HMA や UMB に退避させる。ちなみに、複数の UMB に効率よくドライバを詰め込むには、サイズの大きいドライバから順番に組み込む必要がある。つまり、ドライバのサイズを考慮して、devicehigh= を記述する順番を工夫する必要があるのである。

この himem.sys と emm386.exe に関しても、初心者からすると似たような機能のものがわざわざ 2 種類に分けて存在している感じがして違いがわかりにくいが、himem.sys は 1024KB 以降の拡張メモリ領域にアクセスするためのもの(すなわちメモリのアドレッシング自体を拡張する)、emm386.exe は 640-1024KB の領域にアクセスするためのものと考えればいいのではないかと思う。emm386.exe はその 640-1024KB にアクセスする結果として、UMB の利用と、EMS の実現という 2 つの効果をユーザにもたらす。よく、himem.sys を記述してから次に emm386.exe を記述しないといけないというような書き方がされているが、これは誤解があり、単に UMB の機能を利用するだけなら himem.sys なしに emm386.exe を単体で(もしくは himem.sys よりも先に)組み込んでも可能ではないかと思う。つまり、device=emm386.exe noems とする場合である。emm386.exe にとって himem.sys の組み込みが前提条件となるのは、emm386.exe を使って EMS を実現する場合だと思う。

ちなみに、EMS というのは UMB の一つを利用して、その窓を通じて、1024KB 以降の拡張メモリとの間にデータをスワップする方式である。プロテクトモードの場合はメモリのアドレス空間そのものが拡張されるが、EMS の場合はプログラム側から見たアドレス空間はリアルモードの範囲そのまま、アドレスに「ページ」という概念を併用することによって、UMB 内の窓となる部分に折りたたむような形で大きなデータを扱えるようにしている。つまりプログラム側から見たアドレスの範囲が、リアルモードの範囲のままで大きな容量のプログラムデータを利用することができるという話であり、ハードウェアや OS の性能の話というよりも、アプリケーションプログラムの動作方法を表す用語と言ったらいいだろうか。

要するに、EMS というものはコンベンショナル・メモリを大きくするというような MS-DOS の設定上のカスタマイズに属する話ではなく、EMS 対応で作成されたリアルモードのアプリケーションプログラムを用いる場合でない限り EMS 機能はまったく必要ないのである。コンベンショナル・メモリの確保が目的であれば EMS ドライバとしての emm386.exe は全く無視してよいわけで、あくまでも 640-1024KB の領域を可視化し、UMB の利用を可能にする UMB マネージャとしての機能面に限定して emm386.exe を扱い組み込めばいいのである。すなわち、noems オプション付きで使う場合の emm386.exe の用法だけを念頭に置けばいい。

config.sys の設定例:

device=A:\HIMEM.SYS
device=A:\EMM386.EXE noems highscan
dos=high,umb
devicehigh=
devicehigh=
(...)

参考


《以上》