Windows95と地上の星
この記事は、数年前に私がブログに書いた記事ですが、最近、私が連載しているメルマガ「週刊 Life is beautiful」で Microsoft のアプリの互換性に対する姿勢に関する話題が出たので、再度 note の記事として公開することにしました。ソフトウェア・エンジニアとはどんな仕事をしている人たちなのかを理解するには、良い資料だと思います。ソフトウェアを勉強している学生さんたちには、ぜひとも読んでいただきたい文章です。
Windows95の開発の総責任者であるDavid Coleから開発の主要メンバーに緊急召集がかけられたのは、Windows95の開発も大詰めを迎えた1994年末のことである。
Shell(デスクトップ、エクスプローラ、スタートメニューなどのユーザーインターフェイス)の開発を担当していたSatoshiは、いままでの経験からこの手の緊急招集が良い知らせでないことはないことは知っていた。
David Coleが深刻な顔をして緊急招集の理由を説明し始める。Windows95そのものの開発は順調に進んでいるが、Windows3.1との互換性の維持が思うように進んでいないのである。
「このままだと、95年中にリリースすることはできない」
深刻な問題である。既に当初の予定より1年以上遅れているWindows95のリリースをさらに遅らせて95年のクリスマスシーズンを逃すことはOffice95を同時にリリースして一気に32ビットOSでの主導権を握ろうとしているMicrosoftの戦略上許されることではない。しかし、かといってWindows3.1との互換性をないがしろにすることは、絶対にできない。ユーザーが持っているWindows3.1用のアプリをそのまま走らせることが出来るからこそ、Windows95への移行がスムーズに進むのだ。互換性が維持できなければ、AppleやIBMに付け入るスキを与えてしまう。
「この状態を打開するために、各部署から人を出してスワットチームを作って欲しい。3ヶ月以内に、市場に出ている売れ筋のWindows3.1用のアプリ全てがWindows95上できちんと走るようにして欲しい。どんな手段を使っても良いからかならずそれを実現するのが君らの役目だ」
そう言いながらDavid Coleが我々に渡した資料には、ゲーム、教育、ビジネス、などの各ジャンルの売れ筋のソフトのリストが書かれており、Windows95上でちゃんと動作しないものに印がしてある。その数が異常に多い。事態はかなり深刻だ。
Shellの開発が既に一段落していた私は、すぐにスワットチームに加わる。たまたま、息子たちの幼稚園で使っていたという理由で、Learning Companyの教育ソフトの互換性を担当することにする。Learning Companyは、このジャンルでは常にベストセラーランキングに名を連ねるソフトを何本も持つ、教育ソフトの大手である。その会社のソフトがどれもWindows95で動かないのだ。
さっそく調査を始める。確かにどのソフトもWindows95上ではちゃんと動かない。調べてみると、Windows3.1用のソフトであるにも関わらず、32ビットのレジスタを使ったインストラクションを使っており、それが32ビットレジスタの上位16ビットが全て0に初期化されていることを前提にしているため、システムが32ビット全てを使うWindows95上で走らせると、暴走してしまうのだ。
その情報を持って、Kernel(メモリやプログラムを管理する部分)を担当するKevinに話に行く。「16ビットのソフトを起動する前に、全てのレジスタの上位16ビットを0にしてくれれば互換性が高まるはず」というSatoshiの説を訴える。最初はKevinも難色を示すが、結局のところ「それで互換性が高まるのであれば」と納得してもらう。
変更を加えてもらったKernelでWindowsを立ち上げ、問題のソフトの一つ、Reader Rabbitを走らせてみる。先ほどよりは少し先に進めるが、やはり途中で暴走してしまう。別の問題があるのかも知れない。
さらに解析を進めると、先ほどと同じような症状だが、今度はシステムコールをした後のレジスタの上位16ビットが0でないことに起因している。再度Kevinに相談に行く。
「これは完全にアプリ側のバグだよ。システムコールを呼ぶと幾つかのレジスタの内容が破壊されるのはWindowsの仕様だよ。それをちゃんと理解せずに、システムコールの後もレジスタの上位16ビットが0のままであることを前提にしているプログラムを作る方が悪いんだよ」とKevinは言う。
「しかし、そうは言っても、Windows3.1との互換性のためには出来る限りのことをするのが僕らの仕事ではないのか。」と食い下がるSatoshi。
結局、Learning Companyのアプリが呼び出しているシステムコールのうち、問題となるものを見つけ出し、そこで破壊されては困るレジスタの値だけを保存するようにシステム側を変更することで合意する。
しかし、実際にその作業を開始したSatoshiは、すぐにそれが気の遠くなるような作業であることに気が付く。システム側に20箇所ほど変更を加えても、まだReader Rabbit一つ完璧に動かすことができない。こんな場当たり的な方法では効率が悪すぎる。
時間はどんどんと過ぎて行く。スワットチームのどのメンバーたちも似たような壁にあたっており、「Windows95上で動かないソフトのリスト」は一向に短くならない。
そんな作業を繰り返しながら、Satoshiは問題を起こすLearning Companyのプログラムにある一定のパターンがあることに気が付く。たぶん、彼らの使っているコンパイラが32-bitのデータを扱う時に生成するコードなのだろう。
そこで、パターンをアプリ全体から探しだす作業をしてみた。アプリ一つあたり、数箇所から数十箇所に、そのパターンが現れる。アプリがそのコードを実行する前に、レジスタの上位ビットが全てゼロにしてなっていないと暴走するのだ。
それを検証するために、Satoshiはメモリ上に展開されたReader Rabbitに変更を加えてみることにした。問題となるパターンの部分のコードを効率化してプログラムサイズを少し小さくし、あまったスペースに問題となるレジスタを0にしてしまうインストラクションを挿入したのだ。
そうやって変更を加えた状態で走らせると、すべてがキチンと動作する。やはり予想通り、このパターンのコードが問題なのだ。
Windows95上で初めてキチンと走るReader Rabbitを見ているSatoshiの頭に、突然一つのワイルドなアイデアが浮かぶ。急いでKevinのオフィスに走る。
「Kevin、Kernelがアプリをロードするとき、それがあるソフトの特定のバージョンだっていうことは判別できるものなの?」
「簡単だよ。モジュール名、日付、コードのチェックサムを見れば、すぐに判定できる。」
「だったら、ある特定のアプリのコードをメモリーにロードした時に、指定した場所に変更を加えてから実行させるってことも出来る?」
「もちろん、技術的には可能だよ。でもサードパーティのプログラムを実行時に勝手に変更するっていうのはまずいんじゃない?」
「David Coleが『どんな手段を使っても』って言ってたじゃないか。やるしかないよ。」
そこからSatoshiとKevinの共同作業が始まる。Windows3.1用に作られたサードパーティのプログラムをロード時にダイナミックに変更して、Windows95で動くようにしてしまうというウルトラCだ。SatoshiがReader Rabbitに加えるべき変更点をデータ化し、Kevinがそのデータを読み込んでパッチをあてる様にKernelのローダーを変更する。Reader Rabbitが新しいKernelの元で動くようになった時には、既に朝であった。
その週のスワットチームのミーティングで、SatoshiとKevinはLerning Company製のソフト全てをWindows95上で動かすことに成功したこと、そして、その仕組みはLearning Company製のソフトに限らず、他のメーカーのソフトにも適用可能なことを発表する。
スワットチームの何人かが、サードパーティのプログラムに勝手にパッチをあてることに懸念を示す。話し合いの結果、互換性問題の具体的な内容をそのアプリのメーカーに開示し、ダイナミックにプログラムに変更を加えることに対して文書で許可をもらえばOK、ということになる。
スワットチームの他のメンバーもこの仕組みにすぐに飛びつく。この方法を使えば、「アプリ側のバグ」のためにWindows95上で動かなくなってしまったアプリを救うことが出来るのだ。
…
翌年7月。予定通りの日付にWindows95をリリースした開発チームにDavid Coleが感謝の言葉を述べ、テーブルの上のシーツを取り除く。ドンペリが50本あらわれる。「優勝した野球チームがビールをかけ合うのであれば、Windowsチームはドンペリだ。」という彼の約束どおりである。皆、一本ずつドンペリを手に持ち、頭から掛け合い、ラッパのみをする。シャンパンまみれになったSatoshiとKevinががっちりと握手をする。