〜ソースコード公開を期にパソコン大衆化の原点を振り返る〜30年前のMS-DOSのソースコードがコンピューター歴史博物館に寄贈され、公開された。現在のPC隆盛の礎となったソースコードを見に行こう。1.1aのソースコードをコンピューター歴史博物館(米カリフォルニア州マウンテンビュー)に寄贈し、公開した。商用利用は不可だが、リサーチや教育などに限れば自由に参照・利用できる。Museum)MS-DOSといえば、Microsoftおよび現在のパーソナルコンピューター発展の礎となった歴史的なソフトウェアであり、それが公開されているのだから、ちょっと見物しておきたい(とは思わないだろうか?)。30年も昔のMS-DOSのソースコードに実用的な価値があるわけではないが、現在のWindowsでもまだあの黒い画面(通称「DOS窓」)が残っている。人にもよるだろうが、この「黒い画面」には、まだ当分お世話になりそうだ(後述するが、正確にはDOS窓はMS-DOSそのものではない)。このコンピューター歴史博物館には、物理的なコンピューターシステムだけでなく、このような歴史的に重要な意味を持つソフトウェアも多数アーカイブされている。初代MacintoshのQuickDrawやMacPaint、Photoshopのソースコードなども公開されている。95のソースコードなども公開されるのだろうか、ちょっと期待したい。MS-DOSとは「MS-DOSとは懐かしい!」という筆者と同年代の人はともかく、「それ、何?」という平成生まれの人もいるかもしれないので説明しよう。System)」とは、IBMが1981年に販売を開始したパソコン「IBM-PC」向けに作られたOSである。OSといっても、現在のOSのような高度な機能は何も備えておらず、基本的には、フロッピーディスク上に保存されているプログラムをメモリへロードして起動するという機能ぐらいしか持っていない。DOSと呼ばれていた。マルチタスクでもないし、「行儀の悪い」プログラム(人様のメモリ領域をぶっ壊すとか)があると、簡単にシステムがハングアップしたり、再起動したりしてしまうようなものであった。ハードウェア(CPU)にプロセスやメモリの保護機能がないのだから当然だが、それでもその当時広く使われていた8bitのコンピューターよりは、かなり性能が高く、約1Mbytesという当時としては「広大な」メモリ空間が(理論上)使えるので、主にBASICしか使えない8bit機に代わって急速に普及したのは必然だった。背景が黒で文字が白という(グリーンのディスプレイもあったが)、キャラクターベースのユーザーインターフェイスである。プロンプト」にもつながる。ユーザーはキーボードから「コマンド」を入力して操作する。マウスはまだなかった。初代IBM-PCはバッテリバックアップされたリアルタイムクロック(時刻情報チップ)を持たなかったため、起動後は最初に手動で日付を入力している。このシステムでは、全メモリが64Kbytesで、DOSの占有サイズが約13Kbytes、ユーザー領域が約51Kbytesとなっている。Nov」参照)のために作成したものである。CPUを使ったボードを販売するためにOSを求めていた。OS)」もしくは「86-DOS」と呼ばれるDOSを作った。後にこれをMicrosoft社が買い取り、MS-DOSとして(IBM向けには「PC-DOS」として)販売することになる。Patersonの名前が何カ所かに出てくる。Patersonであり、当初は「Q-DOS」や「86-DOS」と呼ばれていた。1.25のソースコード、MSDOS.ASMファイルの冒頭部分。半年ほどで86-DOSを作り上げたようだ。”High-performance”の文字がまぶしい。Technologyを経営している。MS-DOS/86-DOSの情報はそのサイトが詳しい。Technology)CP/Mを参考に開発された86-DOS86-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のバージョン以下に主要なMS-DOSのバージョンを示しておく。3.xIBM-PC/ATに対応。Shellによる擬似的なマルチタスクが可能。6.xディスク圧縮機能などを追加。DOSの主要なバージョンとその機能概要。DOSで、Microsoftやそれ以外のベンダーが出荷していたのがMS-DOS。全部アセンブリ言語で開発されているMS-DOSさて公開されたMS-DOSのソースコードには、以下の4つのフォルダーツリーがある。2.11の方には外部コマンドのソースコードもある)、機種依存部分(IO.SYSなど)に関するファイルが不足していたり、ソースコードの書式などが統一されたりしていないので(MicrosoftのMASM用とSCPのASM用が混在)、これを使って完全なMS-DOSを再ビルドすることはできないようだ(ブートセクター用のコードやイメージもない)。Microsoft社内で利用している完全なビルド用ソースコード環境ではないし、OEMベンダー向けのカスタマイズキット(各ベンダーは、機種に依存する部分のみを独自に作成/カスタマイズして、自社ブランドのMS-DOSとして出荷する)でもなく、いくつかのバージョンのソースコードなどが混ざっているようだ。ソースコードは全て8086のアセンブリ言語で記述されている(以後のMS-DOSもほとんど全てアセンブリ言語で記述されている)。1.25フォルダーに含まれているファイルの一覧を示しておく。ちなみにアセンブリ言語とは、CPUの命令セットと一対一に対応する極めて原始的なプログラムコードのことだ。いまでこそC#やらRubyやらと高級な言語が当たり前になっているが、当時はまだ16bitシステム用のC言語なども利用できず、メモリサイズに制約のあるPC向けにOSを書くとなると、アセンブリ言語以外の選択肢はほとんどなかったのだろう。バイトの空き領域c:\Prj\msdos\v11source>見ての通り非常にシンプルで、MS-DOSのカーネル部分が「MSDOS.ASM」、コマンドプロンプト(シェル)のプログラムが「COMMAND.ASM」である。1.25は機能が単純でサポートされているシステムコールも少ないため(50個弱)、MS-DOSのカーネル(MSDOS.ASM)は4000行ほどしかない(バイナリサイズは8Kbytesほど)。これだけのものでも、他の開発者やコンピューターメーカーなどがそう簡単に作れなかったのかと思うと感慨深い。全部アセンブリ言語で記述されているのでちょっと圧倒されるが、各システムコールの処理ルーチンはそれぞれ数十行ずつしかなく、大して長くない。読むには苦労しないレベルだろう。2.11のソースコードが含まれているが、DOSの機能は増えているし(特に階層フォルダーサポート)、システムコールの数はほぼ倍に増えているので、かなり複雑化している。ソースコードが複数に分割されているので分かりづらいがMS-DOSカーネルだけでも2万行以上あるようだ。1.25のコードがいくらか残っているが、全体的にかなり大幅に追加、修正が施されている。1.25の約2年後、1983年にリリースされている)、アセンブリ言語を使って可能な限りコンパクトにまとめる必要があったのだろう(もっとも、途中で高級言語での開発に切り替えるのは無理だろうが)。MS-DOSの内部構造とメモリマップここでMS-DOSの内部構造やメモリマップについて補足しておこう。初代IBM-PCはCPUは8088(8086の8bitバス版)を使っているため、論理的なアドレス空間は1Mbytesもあったが(8bit機の16倍も広い)、実際のメモリ(RAM)は16Kbytesか64Kbytesモデルしかなかった(最大限拡張しても256Kbytes。フロッピー1枚にも満たない)。これだけのメモリで動作しなければならないので、DOSの機能が制限されるのは当然として、DOSが占有するメモリを極力少なくするための工夫も用意されていた。MS-DOSのメモリマップ8086アーキテクチャのIBM-PC(互換機)では、全メモリ空間が1Mbytesあり、先頭から640KbytesまではRAMメモリ、そこから上がデバイス空間というのが一般的である。MS-DOSを起動すると、先頭にデバイスドライバー類(IO.SYSやIBMBIO.COM)、次にMS-DOSの本体(MSDOS.SYSやIBMDOS.COM)がロードされ、最後にCOMMAND.COMが置かれる。ユーザープログラムがメモリを最後尾まで使い切るとCOMMAND.COMの非常駐部は破壊されるが、再ロードされるので問題ない。メモリ空間の下位から順にデバイスドライバー(IO.SYS)とMS-DOSの本体(MSDOS.SYS)などが置かれ、その次にCOMMAND.COM(CUIシェル)の常駐部分が配置されている。Area)があり、アドレス空間の最後にCOMMAND.COMの非常駐部がある。COMMAND.COMの役割は、ユーザープログラムを空きメモリ空間にロードして起動することである。ユーザープログラムがメモリ空間を最後まで使うと非常駐部分は破壊されるが、その場合は自動的に再ロードされるので問題ない。この仕組みにより、COMMAND.COMの占有する部分のメモリもユーザー空間として利用可能にしている。OSのメモリ空間などについては、以下の記事も参照していただきたい。ENDIF」というコードブロックがある。これは「KANJI(漢字)」というシンボルが定義されていると、その部分のコードを有効にする、という意味だ。コードを見ると、Shift-JISコードに対する判定や処理などが追加されている(日本語文字は2bytesを常にペアで扱うようにしないと不具合が生じる)。このような漢字対応はMS-DOSのカーネル部分だけでなく、各種ツールのソースの中にもいくらか入っていて、このような実装をする人の苦労が忍ばれる。KANJI以外の2bytes文字への対応はないようなので、単なる一国向けの対応がOSのマスターコードの中にしっかりと入っていていいのか、という気がしないでもないが。ちなみに、この「ファイル名の先頭バイトが0xe5なら、実ディスク上には0x05に変換して書き込む」というのは、今ではFATファイルシステムの「仕様」となっている。KANJI」というブロックが多くのファイル中にある。他の言語を差し置いて(?)、日本語対応が行われている(実際には、他の言語にローカライズしたバージョンのソースコードもあるのだろうが)。2.0で追加された、ファイルハンドルを使ったファイルアクセスのオープン処理部分。ソースファイル名はXENIX.ASM。(1)「KANJI」変数を使った条件アセンブル指定。0以外ならこのブロックのコードが有効になる(2)FATディレクトリエントリの先頭バイトが0x05かどうかチェックしている。(3)0x05なら0xe5に置き換えている。FATファイルシステムでは、ファイルを削除すると先頭バイトに0xe5を書き込むが(先頭が0x00もしくは0xe5なら削除エントリを表す。新品の8インチフロッピーはデフォルトで0xe5というデータで初期化されていたので、こうしておくと空ディスクをファイルと間違わずに済む、というCP/Mの頃からの“遺産”)、Shift-JISでは0xe5は有効な漢字コードの第1バイトである。そのため、ファイル名の先頭が0xe5の場合は、ディスク上には0x05に変換して書き込んでいる。これは、それを元の0xe5に戻す処理。2.01で始まったが(通貨記号や日付フォーマットなどの情報をOSから取得できる)、公開されたソースコードでは英語以外のメッセージは何も含まれていない。現在なら言語別にリソースを分離するところだろうが、当時はまだソースコード中にしっかりと埋め込んでいて、言語別にファイルを切り替える(作り替える)、というような対応が普通であった。2.11のソースコードでは、文字列部分は全て「〜MES.ASM」という名前のファイルに分離するように変更されている。アンドキュメンティッドMS-DOSソースコード解説を長々とやっても退屈だと思われるので(特に8086のアセンブリ言語が分からない人には)、あと1つだけ鑑賞ポイントを紹介して終わりたい。MS-DOSに限らず、Microsoftの製品には「アンドキュメンティッド」な機能がある、とよくいわれていた(実際のところ、多数存在する)。2.xがリリースされた当初は公開されていなかった。今回のソースコードを見るとそのような機能が実装されていることが分かる(付属のOEMベンダー向けドキュメントファイルCONFIG.TXTにも書かれている)。2.xのリリース当初はこれらの機能は公開されていなかったが、現在ではほとんど全て解析され、情報が公開されている。これはファイルGETSET.ASM中のSwitcharなどのシステムコールを処理する「$Char_Oper」ルーチン。アンドキュメントな仕様でも逆アセンブルして見つけ出す開発者も少なくなかったが、やはりソースコードレベルで見ないと正式な名称などは分からないことが多い。(1)AHレジスターを0x37にしてMS-DOSを呼び出すと、SWITCHAR/AVAILDEVの設定や確認ができる。(2)SWITCHARフラグの設定、確認。(3)AVAILDEVフラグの設定、確認。Character)のことである。MS-DOSでは通常は「/」文字でオプションを表す。これをUNIXのコマンド風に「-」文字をオプション指定文字にしたければ、CONFIG.SYSファイルに「SWITCHAR=-」と書き込んでMS-DOSを起動すればよい。標準的なMS-DOSではオプション指定文字は「/」だが、CONFIG.SYSファイル中でSWITCHARを設定すると「-」に変更できる。(1)SWITCHARはCONFIG.SYSファイルで設定する。ここではCONFIG.SYSファイルの設定後、システムを再起動している。(2)オプション指定文字を「-」に変更している。(3)「-」をオプション指定として使う例。変更すると、「/」はオプション指定文字として使えなくなる。(5)エラーとなっている。SWITCHARを設定するとオプション指定文字が「-」に切り替わり、さらに階層パスの区切り文字として「\」ではなく、UNIXなどと同様に「/」が使えるようになる。/folder/file.txt」とできるようになる。UNIXの操作に慣れたユーザーなら、この方が便利だろう。「/」をパス区切り文字として利用する例SWITCHAR設定を変更すると、このようにパス区切り文字として「/」を利用できるようになる。コマンドやアプリケーションによってはSWITCHAR設定は無視されるが、少なくともMS-DOS内部では(システムコールを呼び出す場合のパラメーターとしては)、SWITCHAR設定の有無に関わらず、「\」でも「/」でもパス区切り文字として利用できる。(1)SWITCHARを「-」に設定してみた。(2)「/」をパス区切りとして利用できるようになる。(3)SWITCHARが変更されていても、このコマンドでは「\」をパス区切りとして利用できる(SWITCHAR設定に厳密に従うコマンドもあれば、そうでないコマンドもある。混乱しているようである)。(3)この方法でも正しく表示されている。2.0で導入された階層フォルダー機能はもともとはUNIXの機能なので、UNIXと同様に「/」をパス区切り文字にするのが望ましいはずである。MS-DOSではそのような案は採用せず、「/」に似た(英語の)文字として逆方向のバックスラッシュをパス区切り文字として採用した。日本語では「\」になる。1.xの操作に慣れたユーザーの利便性などを考え、結局はパス区切り文字を「\」にした。これにはIBMの強い意向も働いている。1.xの時から使っているバッチファイル(やドキュメント)なども影響を受けるからだ。いうわけで、公式にはパス区切り文字として「\」を採用したが、隠し機能として「/」をパス区切りに使えるようにする秘密の機能が用意された。それがSWITCHAR機能である。オプション文字切り替え機能と称しているが、実際にはパス区切り文字を「/」にするための機能だ。このオプションはいつでも使えるわけではない。コマンドによってはこの切り替え機能に対応していないものもあるし(そもそもアンドキュメントな仕様なので、対応している方が変なのだが)、ユーザーが作ったアプリケーションでも切り替えできないものがほとんどである。3以降では削除されることとなった。ちなみにMS-DOSシステムの内部では、パス区切り文字としては、「/」と「\」のどちらでも使うことができる(例:「A:\folder\file1」と「A:/folder/file1」のどちらでもよい)。プログラム内からファイルをオープンするシステムコールを呼び出す場合、(SWITCHAR設定には関係なく)パラメータとしてどちらの形式のパスを渡しても構わない。パス区切り文字の判定ルーチンMS-DOS内部では、パス名中の区切り文字はSWITCHAR設定に関係なく、常に「/」でも「\」でも構わない。これはファイルFCB.ASM内のPathChrCMPルーチン。(1)パス区切り文字かどうかはこのPathChrCMPで判定している。(2)「/」文字ならZeroフラグを立ててリターンする。SWITCHAR文字設定は参照しておらず、「/」文字はいつでもパス区切り文字として有効になっている。(3)「\」でも同じ処理をしている。(4)余談だが、ここにもKANJI処理がある。JISコードかどうかを判定しているが、081Hや09FH、0E0H、0FCHなどの数値がコード中に直書きされている。KANJI部分には、全ソース中でもほとんどコメントはない(もうちょっと何か書いておいた方がよくないですか)。階層フォルダーのことをUNIXの機能と記したが、MicrosoftではUNIXをベースにしたXenixを販売していた。そのためMS-DOSのソースコードでは「XENIX.ASM」「XENIX2.ASM」というファイル名になっている。OSの中に生き残っている。OSの本体を実行するようになっている。プロンプト」プログラムを起動すると、黒い窓が表示されてMS-DOSが実行されているように見えるが、あれはMS-DOSとその上で動作するCOMMAND.COMではなく、COMMAND.COMの動作を再現・拡張したCUIのシェル(cmd.exe)である。Machine)」というプロセスが起動し、その中で実行される。OSでは利用できない。8.1ではNTVDM機能を追加インストールしない限り実行できないので、そろそろ本当にMS-DOSが終了するのかもしれない。8.1上で従来のアプリケーションを起動したところ。Windows/MS-DOS互換環境を実行している(64bit版WindowsではNTVDMは利用できない)。Windows(Ver.3.x相当)のコードを仮想環境上に移植したものなので互換性は高い。NTVDMは必要になった場合に自動的にロードされ実行される。3.1のファイルマネージャー。3.1の時計アプリケーション。Windows環境を実現するNTVDM。Windowsアプリケーションは単一のNTVDM上で動作する。(4)MS-DOS用の.COMプログラムも実行できる。(5)MS-DOSの.EXEや.COMプログラムは、プログラムごとに1つずつNTVDMが起動する。8.1ではNTVDMはオプション機能。最初にDOSプログラムなどを起動したときに、NTVDMをインストールするかどうかを問い合わせてくる。8の場合は、デフォルトでインストールされてはいるが、無効化されている。最後に以上、MS-DOSのソースコードが公開されたと聞き、ついうっかり昔とったきねづかで解説をしてしまった。その昔、『標準MS-DOSハンドブック』(1984年、アスキー発行)という解説本の一部を執筆させていただいたので、MS-DOSにはちょっと思い入れがあったからだ。あのときはDEBUG.COMや逆アセンブルでMS-DOSの内部を覗かせていただいたりもしたが、それがソースコードレベルで見られるようになるとは、思いも寄らなかった。MS-DOSの黒い解説書「標準MS-DOSハンドブック」MS-DOSといえば黒い画面、黒い画面なら黒いデザインに、ということでできたこの本。500ページもあって当時としては画期的に分厚い本になり、製本が大変だと聞いた。MS-DOSはこのたび正式に「博物館入り=過去の遺物」となったわけだが、このような原始的なプログラムが現在の高度なコンピューティングの礎になっている。私たちがいま注目しているネットやスマートフォンやクラウドとは異次元の話であり、MS-DOSのソースを見たところで実用的な何かが得られるわけではないだろう。読者がコンピューティングの内側を知る必要に迫られるITエンジニアなのであれば、今に通じるコンピューターの原点を感じたり、どうがんばっても共通の話題を見つけられないような年配エンジニアとの話題にしたりするために、貴重な記録となることだろう。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。