30年前のMS-DOSのソースコードがコンピューター歴史博物館に寄贈され、公開された。現在のPC隆盛の礎となったソースコードを見に行こう。
2014年3月、MicrosoftはMS-DOS 1.25とMS-DOS 2.11、およびMicrosoft Word for Windows 1.1aのソースコードをコンピューター歴史博物館(米カリフォルニア州マウンテンビュー)に寄贈し、公開した。商用利用は不可だが、リサーチや教育などに限れば自由に参照・利用できる。
MS-DOSといえば、Microsoftおよび現在のパーソナルコンピューター発展の礎となった歴史的なソフトウェアであり、それが公開されているのだから、ちょっと見物しておきたい(とは思わないだろうか?)。もちろんいまさら30年も昔のMS-DOSのソースコードに実用的な価値があるわけではないが、現在のWindowsでもまだあの黒い画面(通称「DOS窓」)が残っている。人にもよるだろうが、この「黒い画面」には、まだ当分お世話になりそうだ(後述するが、正確にはDOS窓はMS-DOSそのものではない)。
なお、このコンピューター歴史博物館には、物理的なコンピューターシステムだけでなく、このような歴史的に重要な意味を持つソフトウェアも多数アーカイブされている。例えば初代MacintoshのQuickDrawやMacPaint、Photoshopのソースコードなども公開されている。将来的にはWindows 3.1やWindows 95のソースコードなども公開されるのだろうか、ちょっと期待したい。
「MS-DOSとは懐かしい!」という筆者と同年代の人はともかく、「それ、何?」という平成生まれの人もいるかもしれないので説明しよう。「MS-DOS(Microsoft Disk Operating System)」とは、IBMが1981年に販売を開始したパソコン「IBM-PC」向けに作られたOSである。OSといっても、現在のOSのような高度な機能は何も備えておらず、基本的には、フロッピーディスク上に保存されているプログラムをメモリへロードして起動するという機能ぐらいしか持っていない。だからDOSと呼ばれていた。マルチタスクでもないし、「行儀の悪い」プログラム(人様のメモリ領域をぶっ壊すとか)があると、簡単にシステムがハングアップしたり、再起動したりしてしまうようなものであった。ハードウェア(CPU)にプロセスやメモリの保護機能がないのだから当然だが、それでもその当時広く使われていた8bitのコンピューターよりは、かなり性能が高く、約1Mbytesという当時としては「広大な」メモリ空間が(理論上)使えるので、主にBASICしか使えない8bit機に代わって急速に普及したのは必然だった。
MS-DOSのオリジナルコードは、Seattle Computer Products(SCP)社のTim Patersonが、自社で販売していたS-100バスシステム用の8086ボード(「First Advertisement for the 8086 Computer - Nov」参照)のために作成したものである。SCPでは、当時出回り始めていたIntelの8086 CPUを使ったボードを販売するためにOSを求めていた。そしてDigital ResearchのCP/M-86という16bit DOSとともに販売する予定だったが、CP/M-86がなかなか完成しないため、CP/M(8bit DOS)のAPI仕様を参考にして、「QDOS(Quick and Dirty OS)」もしくは「86-DOS」と呼ばれるDOSを作った。後にこれをMicrosoft社が買い取り、MS-DOSとして(IBM向けには「PC-DOS」として)販売することになる。このような事情のため、ソースコードにはTim Patersonの名前が何カ所かに出てくる。
Tim Patersonはその後Microsoft社に雇われてMS-DOSなどの開発を担当したが、現在はPaterson Technologyを経営している。MS-DOS/86-DOSの情報はそのサイトが詳しい。
86-DOSは、8bitシステム向けのDOSであるCP/MのAPI仕様やコマンドなどを「参考に」しているため、類似している部分も多いが(ファイル名が8.3形式、コマンド名が似ているなど)、オリジナルの改良部分も少なくない。例えばCP/Mでは、ファイルサイズは128bytes単位だが、MS-DOSでは1byte単位で可変長だし、ファイルシステムもFAT方式でCP/Mとは互換性はない。プログラマーの視点から見ると、DOSの機能を呼び出すシステムコール(ファンクションリクエストともいう)の番号や呼び出し方式などもCP/Mと酷似していて、CP/M(もしくはCP/M-86)での開発経験があれば、容易にMS-DOSでのプログラム開発もできるようになっている。
コマンドも、例えばdirやera、ren、typeといったコマンド名は似ているが、引数の並びは異なっている。あとCP/MにはPIP(コピーコマンド)やED(「文字」指向のラインエディター)などというコマンドがあるが、これらは恐ろしく使いづらい。MS-DOSのEDLIN(ラインエディター)や[Fn]キーによる入力行編集機能が使えるだけでも、CP/Mでなくてよかったと当時は思ったものだ(もっとも普通は何らかのスクリーンエディターを別途導入したが)。ちなみにMS-DOSはCP/Mを大いに参考にしているものの、そのCP/M(のコマンドラインインタフェースなど)はDEC社のミニコンPDPシリーズのOS(RT-11)などを参考にして作られており(オプションが「/」文字で始まる点や、PIPコマンドなど)、分かりづらいコマンドも少なくない。
以下に主要なMS-DOSのバージョンを示しておく。
製品 | 内容 |
---|---|
PC DOS 1.x | IBM-PC向けの最初のDOS |
MS-DOS 1.25 | OEM向けの最初のMS-DOS |
MS-DOS/PC DOS 2.x | 階層ファイルシステムやインストーラブルデバイスドライバー、ローカライズ版などのサポート |
MS-DOS/PC DOS 3.x | IBM-PC/ATに対応。大容量ディスク対応(FAT16)やネットワーク関連の機能を強化 |
MS-DOS/PC DOS 4.x | DOS Shellによる擬似的なマルチタスクが可能。高機能化した分、メモリ消費量が大きい |
MS-DOS/PC DOS 5.x | メモリ管理機能を強化し、OSの占有メモリサイズを大幅に抑制 |
MS-DOS/PC DOS 6.x | ディスク圧縮機能などを追加。MS-DOSのほぼ最終形態の製品 |
MS-DOS 7.x | Windows 9xの内部に含まれるMS-DOSバージョン |
MS-DOS 8.x | Windows Meの内部に含まれるMS-DOSバージョン |
PC DOS 7 | IBM版のみ。REXXスクリプトなどを採用 |
さて公開されたMS-DOSのソースコードには、以下の4つのフォルダーツリーがある。
公開されたアーカイブファイルにはMS-DOS本体のソースコードが含まれているが(MS-DOS 2.11の方には外部コマンドのソースコードもある)、機種依存部分(IO.SYSなど)に関するファイルが不足していたり、ソースコードの書式などが統一されたりしていないので(MicrosoftのMASM用とSCPのASM用が混在)、これを使って完全なMS-DOSを再ビルドすることはできないようだ(ブートセクター用のコードやイメージもない)。Microsoft社内で利用している完全なビルド用ソースコード環境ではないし、OEMベンダー向けのカスタマイズキット(各ベンダーは、機種に依存する部分のみを独自に作成/カスタマイズして、自社ブランドのMS-DOSとして出荷する)でもなく、いくつかのバージョンのソースコードなどが混ざっているようだ。
なお、ソースコードは全て8086のアセンブリ言語で記述されている(以後のMS-DOSもほとんど全てアセンブリ言語で記述されている)。以下に、MS-DOS 1.25フォルダーに含まれているファイルの一覧を示しておく。ちなみにアセンブリ言語とは、CPUの命令セットと一対一に対応する極めて原始的なプログラムコードのことだ。いまでこそC#やらRubyやらと高級な言語が当たり前になっているが、当時はまだ16bitシステム用のC言語なども利用できず、メモリサイズに制約のあるPC向けにOSを書くとなると、アセンブリ言語以外の選択肢はほとんどなかったのだろう。
c:\Prj\msdos\v11source>dir
ドライブ C のボリューム ラベルは WIN7X64 です
ボリューム シリアル番号は 2C9F-4796 です
c:\Prj\msdos\v11source のディレクトリ
2014/04/11 09:30 <DIR> .
2014/04/11 09:30 <DIR> ..
1983/05/09 09:59 63,781 ASM.ASM …8086アセンブラ(SCPのASM書式)
1983/05/17 18:19 67,064 COMMAND.ASM …コマンドラインシェル
1982/07/02 11:33 3,625 HEX2BIN.ASM …バイナリコンバータ
1982/08/03 00:29 36,882 IO.ASM …機種依存部
1983/05/17 18:15 114,253 MSDOS.ASM …MS-DOS本体
1983/05/17 18:20 649 STDDOS.ASM …カスタマイズ部分
2013/12/19 15:15 1,121 Tim_Paterson_16Dec2013_email.txt …ソースコードに関するコメント
1982/07/01 23:54 16,223 TRANS.ASM …Z80→8086トランスレータ
8 個のファイル 303,598 バイト
2 個のディレクトリ 542,581,415,936 バイトの空き領域
c:\Prj\msdos\v11source>
見ての通り非常にシンプルで、MS-DOSのカーネル部分が「MSDOS.ASM」、コマンドプロンプト(シェル)のプログラムが「COMMAND.ASM」である。
MS-DOS 1.25は機能が単純でサポートされているシステムコールも少ないため(50個弱)、MS-DOSのカーネル(MSDOS.ASM)は4000行ほどしかない(バイナリサイズは8Kbytesほど)。たったこれだけのものでも、他の開発者やコンピューターメーカーなどがそう簡単に作れなかったのかと思うと感慨深い。全部アセンブリ言語で記述されているのでちょっと圧倒されるが、各システムコールの処理ルーチンはそれぞれ数十行ずつしかなく、大して長くない。読むには苦労しないレベルだろう。
v20sourceフォルダーの方には、MS-DOS 2.11のソースコードが含まれているが、DOSの機能は増えているし(特に階層フォルダーサポート)、システムコールの数はほぼ倍に増えているので、かなり複雑化している。ソースコードが複数に分割されているので分かりづらいがMS-DOSカーネルだけでも2万行以上あるようだ。中を見ると、MS-DOS 1.25のコードがいくらか残っているが、全体的にかなり大幅に追加、修正が施されている。すでにアセンブリ言語での開発は限界を超えていると思われるが(鑑賞するのもつらいレベル)、まだメモリも潤沢ではなかった当時のPC事情を考えると(MS-DOS 2.xはMS-DOS 1.25の約2年後、1983年にリリースされている)、アセンブリ言語を使って可能な限りコンパクトにまとめる必要があったのだろう(もっとも、途中で高級言語での開発に切り替えるのは無理だろうが)。
ここでMS-DOSの内部構造やメモリマップについて補足しておこう。初代IBM-PCはCPUは8088(8086の8bitバス版)を使っているため、論理的なアドレス空間は1Mbytesもあったが(8bit機の16倍も広い)、実際のメモリ(RAM)は16Kbytesか64Kbytesモデルしかなかった(最大限拡張しても256Kbytes。フロッピー1枚にも満たない)。たったこれだけのメモリで動作しなければならないので、DOSの機能が制限されるのは当然として、DOSが占有するメモリを極力少なくするための工夫も用意されていた。
メモリ空間の下位から順にデバイスドライバー(IO.SYS)とMS-DOSの本体(MSDOS.SYS)などが置かれ、その次にCOMMAND.COM(CUIシェル)の常駐部分が配置されている。その後はユーザープログラム領域(TPA:Transient Program Area)があり、アドレス空間の最後にCOMMAND.COMの非常駐部がある。COMMAND.COMの役割は、ユーザープログラムを空きメモリ空間にロードして起動することである。ユーザープログラムがメモリ空間を最後まで使うと非常駐部分は破壊されるが、その場合は自動的に再ロードされるので問題ない。この仕組みにより、COMMAND.COMの占有する部分のメモリもユーザー空間として利用可能にしている。
MS-DOSやWindows OSのメモリ空間などについては、以下の記事も参照していただきたい。
MS-DOS 2.11のソースコードには、所々に「IF KANJI 〜〜 ENDIF」というコードブロックがある。これは「KANJI(漢字)」というシンボルが定義されていると、その部分のコードを有効にする、という意味だ。コードを見ると、Shift-JISコードに対する判定や処理などが追加されている(日本語文字は2bytesを常にペアで扱うようにしないと不具合が生じる)。このような漢字対応はMS-DOSのカーネル部分だけでなく、各種ツールのソースの中にもいくらか入っていて、このような実装をする人の苦労が忍ばれる。だがKANJI以外の2bytes文字への対応はないようなので、単なる一国向けの対応がOSのマスターコードの中にしっかりと入っていていいのか、という気がしないでもないが。ちなみに、この「ファイル名の先頭バイトが0xe5なら、実ディスク上には0x05に変換して書き込む」というのは、今ではFATファイルシステムの「仕様」となっている。
英語以外の言語に対するサポート、つまり国際化対応はMS-DOS 2.01で始まったが(通貨記号や日付フォーマットなどの情報をOSから取得できる)、公開されたソースコードでは英語以外のメッセージは何も含まれていない。現在なら言語別にリソースを分離するところだろうが、当時はまだソースコード中にしっかりと埋め込んでいて、言語別にファイルを切り替える(作り替える)、というような対応が普通であった。MS-DOS 2.11のソースコードでは、文字列部分は全て「〜MES.ASM」という名前のファイルに分離するように変更されている。
ソースコード解説を長々とやっても退屈だと思われるので(特に8086のアセンブリ言語が分からない人には)、あと1つだけ鑑賞ポイントを紹介して終わりたい。
MS-DOSに限らず、Microsoftの製品には「アンドキュメンティッド」な機能がある、とよくいわれていた(実際のところ、多数存在する)。MS-DOSの場合は、例えばCONFIG.SYSのSWITCHARやAVAILDEVオプション、INT 2EHによるコマンド実行機能などは、MS-DOS 2.xがリリースされた当初は公開されていなかった。今回のソースコードを見るとそのような機能が実装されていることが分かる(付属のOEMベンダー向けドキュメントファイルCONFIG.TXTにも書かれている)。
「SWITCHAR」とは、MS-DOS 2.xにおいて、コマンドなどのオプションを表す文字を切り替える機能(Switch Character)のことである。MS-DOSでは通常は「/」文字でオプションを表す。「dir /w」や「chkdsk /v」などだ。これをUNIXのコマンド風に「-」文字をオプション指定文字にしたければ、CONFIG.SYSファイルに「SWITCHAR=-」と書き込んでMS-DOSを起動すればよい。
SWITCHARを設定するとオプション指定文字が「-」に切り替わり、さらに階層パスの区切り文字として「\」ではなく、UNIXなどと同様に「/」が使えるようになる。つまり「type \folder\file.txt」ではなく、「type /folder/file.txt」とできるようになる。UNIXの操作に慣れたユーザーなら、この方が便利だろう。
MS-DOS 2.0で導入された階層フォルダー機能はもともとはUNIXの機能なので、UNIXと同様に「/」をパス区切り文字にするのが望ましいはずである。だがMS-DOSではそのような案は採用せず、「/」に似た(英語の)文字として逆方向のバックスラッシュをパス区切り文字として採用した。日本語では「\」になる。
新しいMS-DOSではパス区切り文字として「/」を使い、この文字を避けるためにオプション指定文字を「-」に変更するという方法もあったはずだが、すでに従来のMS-DOS 1.xの操作に慣れたユーザーの利便性などを考え、結局はパス区切り文字を「\」にした。これにはIBMの強い意向も働いている。操作方法が変わると困るだけでなく、MS-DOS 1.xの時から使っているバッチファイル(やドキュメント)なども影響を受けるからだ。
というわけで、公式にはパス区切り文字として「\」を採用したが、隠し機能として「/」をパス区切りに使えるようにする秘密の機能が用意された。それがSWITCHAR機能である。オプション文字切り替え機能と称しているが、実際にはパス区切り文字を「/」にするための機能だ。
ただこのオプションはいつでも使えるわけではない。コマンドによってはこの切り替え機能に対応していないものもあるし(そもそもアンドキュメントな仕様なので、対応している方が変なのだが)、ユーザーが作ったアプリケーションでも切り替えできないものがほとんどである。
というわけで、この機能は結局はあまり使われず、MS-DOS 3以降では削除されることとなった。ちなみにMS-DOSシステムの内部では、パス区切り文字としては、「/」と「\」のどちらでも使うことができる(例:「A:\folder\file1」と「A:/folder/file1」のどちらでもよい)。例えばプログラム内からファイルをオープンするシステムコールを呼び出す場合、(SWITCHAR設定には関係なく)パラメータとしてどちらの形式のパスを渡しても構わない。
なお階層フォルダーのことをUNIXの機能と記したが、MicrosoftではUNIXをベースにしたXenixを販売していた。そのためMS-DOSのソースコードでは「XENIX.ASM」「XENIX2.ASM」というファイル名になっている。
MS-DOSは、単体の製品パッケージとしてはMS-DOS 6.2(IBM版はPC DOS 7/PC DOS 2000)で終了し、表向きはすでに消えてしまったように見えるが、実際にはまだWindows OSの中に生き残っている。
Windows 9x/Me系列の場合は、ブート時に最初に起動するのはMS-DOSシステムであり、その後Windows OSの本体を実行するようになっている。
Windows NT系列(Windows NT/2000/XP/7/8など)の場合は、「コマンド プロンプト」プログラムを起動すると、黒い窓が表示されてMS-DOSが実行されているように見えるが、あれはMS-DOSとその上で動作するCOMMAND.COMではなく、COMMAND.COMの動作を再現・拡張したCUIのシェル(cmd.exe)である。しかしユーザーが16bit Windowsアプリケーション(Win16プログラム)を起動したり、MS-DOSの.COMや.EXEプログラムを起動しようとすると、自動的に「NTVDM(Windows NT Virtual DOS Machine)」というプロセスが起動し、その中で実行される。NTVDMは、MS-DOS(Ver.5ぐらいに相当)と16bit版Windows(Ver.3.11ぐらいに相当)を実行する仮想マシン(WOW:Windows on Windows)だ。ただしこれが利用できるのはx86向けの32bit版のWindows OSのみであり、64bit版のWindows OSでは利用できない。またWindows 8ではNTVDMはユーザーが許可しない限り実行できないし、Windows 8.1ではNTVDM機能を追加インストールしない限り実行できないので、そろそろ本当にMS-DOSが終了するのかもしれない。
以上、MS-DOSのソースコードが公開されたと聞き、ついうっかり昔とったきねづかで解説をしてしまった。その昔、『標準MS-DOSハンドブック』(1984年、アスキー発行)という解説本の一部を執筆させていただいたので、MS-DOSにはちょっと思い入れがあったからだ。あのときはDEBUG.COMや逆アセンブルでMS-DOSの内部を覗かせていただいたりもしたが、それがソースコードレベルで見られるようになるとは、思いも寄らなかった。
さてMS-DOSはこのたび正式に「博物館入り=過去の遺物」となったわけだが、このような原始的なプログラムが現在の高度なコンピューティングの礎になっている。私たちがいま注目しているネットやスマートフォンやクラウドとは異次元の話であり、MS-DOSのソースを見たところで実用的な何かが得られるわけではないだろう。だが読者がコンピューティングの内側を知る必要に迫られるITエンジニアなのであれば、今に通じるコンピューターの原点を感じたり、どうがんばっても共通の話題を見つけられないような年配エンジニアとの話題にしたりするために、貴重な記録となることだろう。
Copyright© Digital Advantage Corp. All Rights Reserved.