#navi_header|技術| "WindowsOS内部のアーキテクチャのすべて"の第1章~第3章の要約、読書メモとなります。 本記事では以降、"WindowsOS内部のアーキテクチャのすべて" を "Windows OS Internal Architecture" として "WOIA" と略します。 #amazon||> ||< #more|| #outline|| ---- * (1章) Intel 4004 (4bit時代, 1971 - ) 1969年、日本のビジコンという会社の電卓用カスタムLSIの開発以来を受け、米Intelは汎用LSIの開発を開始。2年後の1971年、Intelは4004という型番で完成させた。他にROM(4001),RAM(4002),I/O(4003)を含む、一連のファミリーとして販売された。 1971年の時点ではIBMのSystem/360やOS/360、後継のSystem/370, OS/370が存在し、UNIXも既に産声を上げていた。ベル研究所ではKen ThompsonとDennis Ritchieらが 1970年 にはPDP-11/20上で動作するUNIXを開発していた。当時はアセンブラで開発されていたが、1973年にはC言語に移植されることになる。 4004のスペック: | アドレスバス | 12bit/8bit | | 汎用レジスタ | 4bit | | 外部データバス | 4bit | | 内部データバス | 4bit | ※当時はまだレジスタに名前は付いておらず、4bit x 16個のレジスタに対して番号で指定する「インデックス・レジスタ」だった。 ※"WOIA"ではアドレスバス8bitとしているが、正確には ''プログラムROM(4001)のアドレス指定は12bit, RAM(4002)のアドレス指定は8bit'' として分かれていた。ROMのアドレス指定はA3(4bit) + A2(4bit) + A1(4bit)で12bitだった。 プログラムを格納するROM(4001)は8bit x 256。つまりアドレス範囲は丁度0h-FFhで8bit。つまり4001一つ分が、A2(4bit) + A1(4bit)で指定出来る範囲になる。アドレスバスは12bitなので4KBまで使える。つまりA3(4bit)で、最大16個の4001を切り替えることができた。 当時のジャンプ命令には、A3まで指定するジャンプと、A3を指定しない(A2 + A1の8bit指定)、同じ4001内でのジャンプ命令とで分かれていた。 RAM(4002)のアドレス指定は8bitだったが、先頭4bitはバンク切り替えなどで使われていた。 4004のアドレスバスを何bitと解釈するかは資料やWebサイトによって異なる。そもそも、まだアドレスバスという概念自体が確立していない時代のCPUである。次の資料では"4bit"という表記になっている。 - cpu-collection.de >> Intel >> 4004 -- http://www.cpu-collection.de/?tn=0&l0=co&l1=Intel&l2=4004 当時はまだアドレス専用のバスが存在していなかった為、4bitの内部データバスを使って 4bit x 2 or 4bit x 3 として読み取っていた。このため、データバス = アドレスバスと解釈すれば「アドレスバス = 4bit」という考え方も可能である。 また、当時はスタック領域がCPU内部に存在していた。4004では12bitのプログラムカウンタ + 3レベルの12bitスタックポインタで、計48bitの領域がCPU(4004)内部に確保されていた。 * (2章) Intel 8080 (8bit時代, 1974 - ) と BASIC, CP/M 8bitCPUとして広まった8080について見てみる。 ** 8008 (8bit, 1972 - ) 8080 に入る前に、1972年発表の 8008 を見ておく。 8008のスペック: | アドレスバス | 14bit/8bit | | 汎用レジスタ | 8bit | | 外部データバス | 8bit | | 内部データバス | 8bit | 8008の時点では、まだアドレスバスとデータバスは区別されていない。アドレス自体は 14bit (=16KB) まで指定できたが、データバスは8bitだったため、8bitを二回読み込み、先頭2bitを捨てて14bitとしていた。 汎用レジスタはこの時に A, B, C, D, E, H, L の7つが名付けられた。このうち、HとLレジスタはメモリアドレスの指定に使われた。実際にHとLが関係する命令を見てみる。 | Lr1r2 | 11 DDD SSS | 汎用レジスタSSSの値を汎用レジスタDDDに転送する。 | | LrM | 11 DDD 111 | メモリアドレス"M"の値を汎用レジスタDDDに転送する。 | | LMr | 11 111 SSS | 汎用レジスタSSSの値をメモリアドレス"M"に転送する。 | SSS : Source Index Register DDD : Destination Index Register A(000), B(001), C(010), D(011), E(100), H(101), L(110) 例えば LrM : 11 010 111 の場合は 汎用レジスタ H と L で指定されたアドレスの値を、汎用レジスタC(010)に転送する。 となる。 ここでHとLが以下の値になっていた場合は、Hの上位2bitが捨てられ、Hの6bit + Lの8bitで14bitのアドレス213Fhになる。 H: 1110 0001 : 71h L: 0011 1111 : 3Fh → 1110 0001 0011 1111 → 10 0001 0011 1111 (Hの上位2bitが落とされる) → アドレス:213Fh 4004の時と同様、14bitのプログラムカウンタ + 3レベルの14bitスタックポインタで、計52bitの領域がCPU(8008)内部に確保されていた。 8008は日本の精工舎から依頼を受けて、科学技術計算用のLSIとして開発された。4004と比べてCPUのクロックもあまり変わらず、周辺チップの開発も怠った為、後の8080のようにマイコン市場を作り上げるようなことは無かった。 ** 8080 (8bit, 1974 - ) 8080は1974年発表の8bitCPU。発表年については資料によりばらつきがあり、おおよそ1974年であるが、一部 1973年12月 と表記している資料もある(intel 8080 Microcomputer Systems User's Manual)。 8080のスペック: | アドレスバス | 16bit | | 汎用レジスタ | 8bit | | 外部データバス | 8bit | | 内部データバス | 8bit | 8080になり、"アドレスバス"がデータバスとは独立して登場し、16bit = 64KB までのメモリが扱えるようになった。 汎用レジスタは A, B, C, D, E, H, L, W, Z が導入されている。プログラムカウンタも16bitになっている。 なお8080のGND配線の設計ミスを修正した 8080 ''A'' という製品が発表されている。こちらの方がヒットしたため、"8080"と呼ぶ時に8080Aも含める場合もある。本記事もそれに従う。8080Aを設計した技術者が、後に独立し、ザイログ社を設立して互換CPU "Z80" を発表している。 ** 8080/Z80を搭載したマイコン製品とソフトウェア(BASIC, CP/M) : Altair8800 : 1975年、MITSにより発表された8080を搭載したシンプルなマイコンキット。これに使われた"S-100"バスは8080系のミニコン・マイコンで標準装備として広まっていった。 : Microsoft BASIC : 1975年、Microsoft創業。Altair8800用のBASICを発売。 : NEC TK-80 : 1977年発表のZ80搭載ワンボードマイコン。 : Tandy TRS-80 : 1977年発表のZ80搭載マイコン。 : NEC PC-8001 : 1979年発表のマイコン。PC-8801, PC-6001, PC-6601と続く。 : CP/M : #block||> "Control Program/Monitor", 後に "Control Program for Microcomputers" の略称となる。1973-1974年に Digital Research の Gary Kildall が開発したOS。CP/Mは後に幾つかのCPUに移植されることになり、8080用は"CP/M-80"と呼ばれるようになる。 CP/Mには"ASM.COM"というアセンブラが添付されているが、初代のCP/M自体はKildall自身が作成した"Programming Language for Microcomputers"(PL/M)で開発された。 ''アドレス100hから始まる ".COM" 実行ファイルフォーマットは、少なくとも初代CP/Mまで遡る事が出来る。'' ||< 8080/Z80で盛り上がったマイコン市場で、CP/Mもまた大いに広まった。CP/M上で動作するソフトウェアが開発され、Microsoftもまだこの時点ではCP/M上で動作するプログラミング言語(BASIC, COBOL, FORTRAN)の一ベンダでしかなかった。 ** CP/M-80の構造 MS-DOSの前身(DOS-86)の前身となったCP/Mの構造を俯瞰していく。 *** メモリレイアウト(BIOS,BDOS,CCP,TPA および 0h - 100h) CP/M-80が動作している状態のメモリレイアウトは次のようになっている。 #pre||> +------------------------------+ FFFFh | [BIOS] | | Basic Input/Output System | | (Hadrware Drivers for BDOS) | +------------------------------+ F200h | [BDOS] | | Basic Disk Operating System | | (Operating System Functions) | +------------------------------+ E400h | [CCP] | | Console Command Processor | | (Command Line Interpreter) | +------------------------------+ DC00h | [TPA] | | Transient Program Area | | (Free Memory for Programs) | +------------------------------+ 0100h | CP/M System Area | | (System Buffers, Parameters) | +------------------------------+ 0000h ||< : BDOS : CP/Mのカーネル部分。CP/Mが提供するサービスルーチンが格納されている。 : BIOS : ハードウェアを動作させる為のプログラムが格納されている。現在のBIOSとは別である。 : CCP : ユーザインターフェイスであるシェルプログラムが格納されている。(MS-DOSのCOMMAND.COMに相当) : TPA : ユーザープログラムがロードされる領域 : CP/M System Area : ブート用の機械語やBDOSのサービスルーチンを呼び出す為の一覧表(割り込みベクタテーブル)、カーネルの使うバッファ領域など。 "Basic Disk Operating System" の名前が示すとおり、CP/Mは基本的に磁気ディスクを使うOSだった。 bootには別途bootloaderを格納したROMが必要で、CPUは最初はそのROMの0000hから起動して周辺機器を初期化、続いて磁気ディスクの先頭を読み込み、上記で示した各CP/MのシステムをRAM上に展開していく。展開が終了するとRAM上の0000hの命令をフェッチするようになっており、この時点でF200hへのJMP命令、つまりBIOSへのJMP命令が格納されていた。これによりBIOSに制御が移り、CP/MのOSの世界へ切り替わる。 bootloaderを格納したROMが無い場合は、スイッチなどを操作して直接bootloaderに相当する機械語を打ち込んでCP/Mをロードさせていたようだ。 なお、"BIOS"/"BDOS"/"CCP"についてだが ''相当する物理的なファイルは存在しない。'' CP/Mをロードする過程で磁気ディスクから読み取ったシステムデータをメモリに展開する際に、機能上の理由でこの3種類のモジュールに分類しているだけである。 上の図では64KB全て搭載されている前提でアドレスを載せているが、実際のマシンでは32KBや48KBなど異なる場合があった。 CP/Mのドキュメントにはそれぞれのメモリレイアウトに応じて調整可能なbootloaderのアセンブラコードが掲載されており、自分のマシンとそれを見比べつつ、手動でbootloaderを組み上げていったものと思われる。 *** 0h - 100h の詳細と8080/Z80の割り込み機能 #pre||> +----------------------------+<- 0100h | File Buffer |<- 0080h - 00FFh +----------------------------+ | FCB: | | Default File Control Block |<- 0060h - +----------------------------+ | Unused (in CP/M 2.2) |<- 0050h - +----------------------------+ | BIOS Work Area |<- 0040h - +----------------------------+ | Restart Vector 7 |<- 0038h - 003Fh +----------------------------+ | Restart Vector 6 |<- 0030h - 0037h | Restart Vector 5 |<- 0028h - 002Fh | Restart Vector 4 |<- 0020h - 0027h | Restart Vector 3 |<- 0018h - 001Fh | Restart Vector 2 |<- 0010h - 0017h | Restart Vector 1 |<- 0008h - 000Fh +----------------------------+ | "JMP E400h" |<- 0005h - 0007h +----------------------------+ | Current Default Drive |<- 0004h +----------------------------+ | IO Byte |<- 0003h +----------------------------+ | "JMP F200h" |<- 0000h - 0002h +----------------------------+ ||< 最初の "JMP F200h" 命令はCPU初期化などで"0000h"の命令がフェッチされた場合に、BIOSコードを実行してメモリをリセットするためにある。 次のIO Byte, Current Default Drive についての説明は省略する。 0005hの "JMP E400h" 命令はBDOSコードの先頭へJMPする命令になり、これがOSの機能を呼び出す「システムコール」(DOSでは"ファンクションコール"とも呼ばれる)となる。 ユーザープログラムでは次のような手順で、0005hの "JMP E400h" 命令を通してOSの機能を呼ぶことが出来る。 例:"A"という文字を表示したい時 + 65(ASCIIコード"A")をAレジスタ(Z80のAccumulator)にセット + 02h(BDOSサービス番号で、文字の出力)をCレジスタにセット + "CALL 0005h"を実行 "Restart Vector 1 - 7"については、8080の割り込み機能と併せて簡単に紹介する。 8080における割り込みはハードウェアからのイベントによるハードウェア割り込みしか存在しなかった。 仕組みとしては、割り込み要求を出した装置がISR(Interrupt Service Routine)をコールする命令を返し、それをフェッチして実行することで割り込みハンドラを実行する仕組みになっていた。 この「ISRをコールする命令」が"RST"(ReSTart)命令で、実行する割り込みハンドラを8個選択出来るようになっていた。 "RST"(ReSTart) : 11 AAA 1111 この"AAA"の3bit、8つのISRを指すことが出来る。 ISRのアドレスは、アドレス0000hから始まる8バイトのブロック単位で指定可能になっていた。 つまり、割り込み要求を出した装置が 11 000 1111 を返すと、 0000h - 0007h に格納されたアドレスに飛ぶ。 8バイト毎に8つなので、以下のアドレスに飛び先、つまりISRのアドレスが格納出来る。 0000h - 0007h, 0008h - 000Fh, 0010h - 0017h, 0018h - 001Fh, 0020h - 0027h, 0028h - 002Fh, 0030h - 0037h, 0038h - 003Fh, このうち最初の 0000h - 0007h はCP/Mに割り込み以外の用途に使われ、最後の一つ0038hはデバッガ用に予約されていた。当時のマシンには「デバッグ」ボタンが存在し、ユーザーがこのボタンを押すとハードウェアで割り込みがかかり、 RST: 11 111 1111 が返されてデバッガが動作するようになっていたらしい。 残り6つについては、少なくとも初期のCP/Mでは使っていない。ユーザプログラム側で任意のISRアドレスを指定することが可能だった。 ちなみに8008の段階では割り込み機能は搭載されていない。8080と、同1974年リリースの4004強化版である"4040"において、Intel CPUで割り込み機能が搭載された。8080互換であるZ80は、さらに独自の割り込みモードを備え、8080互換(モード0)の他に2つの割り込みモードを使えるように拡張されていた。 OSが提供するサービス(ファンクション)を割り込み機能(あるいは "CALL 0005h" のような特定のゲートウェイ)を通じて呼ぶ仕組みは、x86のOSの歴史ではCP/Mで初登場となる。 + ユーザプログラムから "CALL 0005h" が呼ばれる、あるいはハードウェア割り込みが発生する。 + 0005h番地の "JMP E400h" 命令によりBDOSへジャンプする、あるいはISRを指定するRST命令をフェッチする。 + BDOSあるいはISRの処理が実行される。 #pre||> +------------------------------+ FFFFh | [BIOS] | +------------------------------+ F200h | [BDOS] (3)|<-----------+ +------------------------------+ E400h | | [CCP] | | +------------------------------+ DC00h | | [TPA] (1)|--------+ | +------------------------------+ 0100h | | | CALL 0005h, (2)+-<|<-------+ | | ResetVector 1 - 7 +->|>-----------+ +------------------------------+ 0000h ||< このようにユーザプログラムとOSの機能を分けた理由としては、当時はまだ細かいメモリレイアウトやハードウェアの仕様が共通化されて居らず、マイコン・ミニコン毎にROMやRAM、周辺機器の仕様が異なっており、それを全てユーザプログラムでカバーするのが不可能だったからであると考えられる。 OSの基本機能や周辺機器の差異はBDOS + BIOSが吸収することにより、ユーザプログラムの負担を低減出来る。ユーザプログラムは周辺機器の詳細を考えずに、単にOSのサービスを呼ぶだけでよい。 もちろんユーザプログラム自身が直接ハードウェアを制御したい場合もあり得るが、この構成にすることでハードウェア周りの処理の多くをOS側に委譲出来たのは確かである。 そしてこの割り込みを使った処理の分離が、その後のMS-DOSやWindowsまで連綿と引き継がれていくことになる。 *** 参考資料 - 基礎から学ぶコンピュータ -- http://rryu.sakura.ne.jp/compfund/ --- 「マイクロプロセッサ編」第38~第43号の割り込みの記事 - CP/M Main Page -- http://www.seasip.demon.co.uk/Cpm/ - The Unofficial CP/M Web Site -- http://www.cpm.z80.de/ - CP/M Internals -- http://www.dcast.vbox.co.uk/cpm.html --- 本章で使ったCP/Mのメモリレイアウトは、このページの図を参考にしました。 - Wikipedia -- http://en.wikipedia.org/wiki/CP/M -- http://ja.wikipedia.org/wiki/CP/M * (3章) Intel 8086/8088 (16bit時代, 1978 - ) と MS-DOS 8086(1978年)のスペック: | アドレスバス | 20bit | | 汎用レジスタ | 16bit | | 外部データバス | ''16bit'' | | 内部データバス | 16bit | 8088(1979年)のスペック: | アドレスバス | 20bit | | 汎用レジスタ | 16bit | | 外部データバス | ''8bit'' | | 内部データバス | 16bit | - 8086を発表するも、8080時代の外部データバス8bitに合わせた周辺機器がまだ多く出回っていた為、外部データバスを8bitにした8088を1979年に発表している。 - アドレスバスについては20bit、1MBまで指定出来るよう拡張されている。汎用レジスタや内部データバスも16bit化された。 - 8086/8088こそが、現代のx86(32bit)アーキテクチャの先祖である IBM PC 5150 で採用されたCPU(正確には8088)であり、MS-DOSやWindowsの起点である。 ** 8086/8088の概要 8086/8088のレジスタ構成、割り込み機能、想定するメモリレイアウトの順に簡単に紹介する。 *** レジスタ構成 8086/8088のレジスタ群(全て16bit, "xH", "xL"は上位/下位の8bitでアクセスする時のレジスタ名) #pre||> +---------+ +---------+ | AH | AL |=AX : ACCUMULATOR | S P | STACK POINTER +---------+ +---------+ | BH | BL |=BX : BASE | B P | BASE POINTER +---------+ +---------+ | CH | CL |=CX : COUNT | S I | SOURCE INDEX +---------+ +---------+ | DH | DL |=DX : DATA | D I | DESTINATION INDEX +---------+ +---------+ +---------+ +---------+ | C S | CODE SEGMENT | I P | INSTRUCTION POINTER +---------+ +---------+ | D S | DATA SEGMENT | FLAG | STATUS FLAGS +---------+ +---------+ | S S | STACK SEGMENT +---------+ | E S | EXTRA SEGMENT +---------+ ||< アドレスバスが20bitになったにも関わらず、IPやSPなどアドレスを指示するレジスタは16bitのままである。これは8086/8088で導入された「セグメント:オフセット」形式のアドレス換算により20bitに変換出来る。 8086/8088では、メモリアドレスを16bitのセグメントと、16bitのオフセットを使って指定する。20bitへの変換には、セグメントアドレスを4bit左にずらした上で、オフセットアドレスを加算する。 セグメント:1234h オフセット:5678h → 12340h + 5678h -------- 179B8h :これが物理メモリアドレスになる。 SPやIPなどはこのオフセットを指定する事になる。一方のセグメントを指定するのが、CS/DS/SS/ESとなる。種類を分け、命令やスタック領域用にセグメントを分けることが出来るようになっている。 CS : IP → 次にフェッチする機械語の物理メモリアドレス SS : SP → スタックポインタの物理メモリアドレス DSやESはその他の機械語命令で使われる。 一つのセグメントで指定可能な範囲はオフセットアドレス16bitの範囲内。 ''64KBの壁'' はこの時誕生した。 *** 割り込み機能 8080では割り込み要求を出した装置が"RST"(ReSTart)命令を返し、それをフェッチすることでISR(Interrupt Service Routine)を実行していた。また、RST命令ではISRを0-7の番号(3bit)で指定するようになっていて、物理アドレス0000hから8バイト毎に実際のISRのアドレスを格納する、間接的な指定方式を採っていた。 また、8080ではハードウェアによる割り込みのみ対応していた。 8086/8088になって、"INT"命令によるソフトウェア割り込みが可能になった。ISRの指定方式は8080を継承している。 ソフトウェア割り込みの場合は、8bitで指定出来る割り込み番号を4倍した値をメモリアドレスとして、そこに格納されている値をISRのアドレスとしてジャンプする。 ハードウェア割り込みの場合は、割り込みコントローラの返す割り込み番号を同様に4倍し、ソフトウェア割り込みと同様にISRのアドレスを割り出してジャンプする。 例:ハードウェア or ソフトウェア割り込みで割り込み番号が3だった時 3 x 4 = 12 → 0000Ch のアドレスに格納されている値を読み出し、そこにジャンプする。 一つの割り込み番号に対して4バイト確保されており、2バイトで分かれてCS, IPレジスタにセットされることでISRにジャンプしている。 資料によっては、割り込みの発生源に応じて割り込みの呼称を変えている。 - 例外割り込み -- トラップ:"INT"命令によるソフトウェア割り込み -- フォールト:0除算や無効な値を扱った場合 -- アボート:致命的なエラー, ダブルフォールトやコプロセッサの異常 - ハードウェア割り込み:キーボードやタイマーなど周辺機器からの割り込み発生 割り込み番号 00h - 1Fh まではIntelによる予約となっているが、初期は守られておらず、一部OS固有の割り込みハンドラとして使われた。例えばIBM PC 5150のROM BIOSではROM BASICをロードする機能が INT 18h に割り当てられていたが、当然これはROM BASICを搭載したマシン専用であり、現在は使われていないか、別の機能が割り当てられたりしている。 *** メモリレイアウト 8086/8088がCPUとして想定するメモリレイアウトは次のようになっている。 #pre||> +--------------------+ | RESET BOOTSTRAP | | PROGRAM JUMP | FFFF0h - FFFFFh +--------------------+ | | | | | | +--------------------+ | INTERRUPT POINTER | | FOR TYPE 255 | 3FCh - 3FFh +--------------------+ | (...) | +--------------------+ | INTERRUPT POINTER | | FOR TYPE 1 | 4h - 7h +--------------------+ | INTERRUPT POINTER | | FOR TYPE 0 | 0h - 3h +--------------------+ ||< 先頭から400h(1KB)まではこのように割り込み番号に応じたISRのアドレステーブル(割り込みベクタ)として予約されている。 "RESET BOOTSTRAP PROGRAM JUMP"の16バイトだが、ここは8086/8088が電源リセットの直後、最初に命令をフェッチするアドレスである。これはMS-DOSやIBM PC 5150 ROM BIOSのメモリレイアウトに関わってくる。 *** 参考資料 割り込み番号: - BIOS interrupt call -- http://en.wikipedia.org/wiki/BIOS_interrupt_call ** 86-DOS, IBM PC 5150, MS-DOSの誕生と640KBの壁(1981 - ) 86-DOS, IBM PC 5150, MS-DOSの流れについては [[614]] 参照。 640KBの壁については、ROM BIOSの配置やビデオRAMなどの配置の影響で、コンベンショナルメモリが0 - 640KBに制限されたことで生じた。 コンベンショナルメモリについては [[632]] 参照。 ** MS-DOSの構成 MS-DOSのカーネル構成やメモリレイアウトについて簡単に紹介する。 *** MS-DOSのブート直前 [[614]] より転載。 ROM BIOSのPOST(Power On Self Test)処理が完了し、BIOS内部でINT 19hが実行され、磁気ディスクの最初のセクタ(MBR)が0x7C00に読み込まれた状態。 #pre||> +--------------------- 0x0 | Interrupts vectors +--------------------- 0x400 | BIOS data area +--------------------- 0x5?? | OS load area +--------------------- 0x7C00 | Boot sector +--------------------- 0x7E00 | Boot data/stack +--------------------- 0x7FFF | (not used) +--------------------- (...) ||< ちなみに、0xFFFF0など物理アドレスの最後尾にはROM BIOS領域が割り当てられている。 この時点で、BIOSの提供する割り込みハンドラについては既に 0h - 3FFh の割り込みベクタにISRのアドレスを登録済になっている。 INT 20h/INT 21hなど、MS-DOSの提供する割り込みハンドラは、この後、MS-DOSのシステムがロードされる時に登録される。 *** MS-DOSのブート直後 MBRからロードされたbootloaderによりシステムがロードされ、 IO.SYS, MSDOS.SYS, COMMAND.COM, およびデバイスドライバが下図のようにメモリ上に展開される。 #pre||> +-------------------+ | VRAM/ROM BIOS領域 | +-------------------+ A0000h (640KB) | ユーザー領域 | +-------------------+ | COMMAND.COM | +-------------------+ | デバイスドライバ/ | | システム作業領域 | +-------------------+ | MSDOS.SYS | +-------------------+ | IO.SYS | +-------------------+ 5??h | BIOSデータ領域 | +-------------------+ 400h | 割り込みベクタ | +-------------------+ 0h ||< "MSDOS.SYS", "IO.SYS"は隠しファイルになっている。この二つは、実はDOSのバージョンやOEM先によって名前が違う。 | System | BIOS Extension | DOS Resident |H | MS-DOS | IO.SYS | MSDOS.SYS | | PC-DOS | IBMBIO.COM | IBMDOS.COM | |Compaq DOS | IBMBIO.COM | IBMDOS.COM | | DR DOS before 6.0 | DRBIOS.SYS | DRDOS.SYS | | DR DOS 6.0 | IBMBIO.COM | IBMDOS.COM | また"5??h"のアドレスについては、以下の資料では"5FFh"と明記されている。 - The DOS Memory Map -- http://www.nolm.org/TAE/c016p08.htm *** IO.SYS, MSDOS.SYS, COMMAND.COMについて CP/Mのモジュールと対比させると分かりやすい。 | CP/M | MS-DOS | 機能 | | BDOS | MSDOS.SYS | OSカーネル | | BIOS | IO.SYS | ハードウェア制御 | | CCP | COMMAND.COM | ユーザインターフェイス | | TPA | ユーザー領域 | ユーザープログラムがロードされる | *** ソフトウェア割り込みによるシステムコールの仕組み CP/Mの時と同様、OSの提供する機能を利用するには一度ゲートウェイを通してカーネル(CP/MならBDOS)を呼ぶ必要がある。 CP/Mでは"CALL 0005h"がその役目を負ったが、MS-DOSの場合は"INT"命令によるソフトウェア割り込みで実現している。 MS-DOSでは、主に20h以降のソフトウェア割り込み番号をMSDOS.SYS内のサービスルーチンに割り当てている。 一つのサービスルーチン内では、AHレジスタに設定される「ファンクション番号」で更に機能を細分化している。 例えばコンソールへ文字を直接出力するには、INT 21h, ファンクション番号は06hとなる。 例:'A'を表示 MOV AH, 06h # ファンクション番号 06h MOV DL, 41h # 出力したい文字 INT 21h # ソフトウェア割り込みによるシステムコール このように、ユーザープログラムが直接MSDOS.SYSの機能を使うのではなく、INT命令によるシステムコールを介して使うようになっている。 NG : [ユーザープログラム] <-----> [MSDOS.SYS] OK : [ユーザープログラム] <---> "INT xx" <---> [MSDOS.SYS] 周辺機器を扱う場合など、IO.SYSが関連してくる場合も同様である。ユーザープログラムが直接IO.SYSの機能を使うのではなく、INT命令によるシステムコール、つまりMSDOS.SYSを介するようになっている。 NG : [ユーザープログラム] <-----> [IO.SYS] OK : [ユーザープログラム] <---> "INT xx" <---> [MSDOS.SYS] <--+ | 周辺機器 (<---> [デバイスドライバ]) <---> [IO.SYS] <--+ *** 参考資料 MS-DOSのメモリレイアウト: - An Inside Look at MS-DOS -- http://www.patersontech.com/dos/Byte/InsideDos.htm - Hidden DOS Files -- http://www.nolm.org/TAE/c016p05.htm システムコール: - Using the INT Instruction -- http://www.nolm.org/TAE/c017p02.htm - MS-DOS API -- http://en.wikipedia.org/wiki/MS-DOS_API - DOS Kernel -- http://www.ctyme.com/intr/cat-010.htm ** Windows 1.0 の登場 (1985 - ) 1985年、Windows 1.0が発表される。マーケティング上はWindows 1.0だが、実際はWindows 1.01というバージョンになっていた。 「本当の」Windows 1.0は1983年の時点でアナウンスされていたが、動作段階には至っていなかったらしい。IBMに見せたが、IBMの興味を引くことなく終わってしまったという説もある。1983年説を採用すれば、実際はWindows 1.01だったというバージョン番号にも納得が行く。 ともあれ、多くの、Microsoft公式サイトでも、Windows 1.0 は1985年発表とされている。 もっとも、Microsoft公式サイトにおいても1983年から開発が始まっていたことは確認出来る。(1983年の段階で動作出来たのか、IBMに見せたのかは確証が得られなかった) 参考資料: [[631]] , "Windowsシリーズ"の参考URL参照。 Windows 1.0 はDOS上で動くGUIマネージャであり、リアルモードで動作するプログラムだった。OSというよりはGUIフロントエンドと呼んだ方がふさわしい。 DOS上で動作するリアルモードプログラムである以上、1セグメント64KBの制限および640KBの壁の制限を受けてしまう。 1984年時点でハードウェアタイプのEMSが利用可能だったが、OSとして公式サポートするまでには至っていなかった。 個人的にWindows 1.0で注目しておきたいポイントは、実行ファイルのフォーマットの一つ、 ''"new executable"(NE)フォーマットが初登場したのがWindows 1.0'' である点。拡張子はMS-DOSと同様に".EXE"だったが、Windowsのみが取り扱えるヘッダー構造になっていたらしい。 ** Windows 2.0 の登場 (1987 - ) 1987年、Windows 2.0が発表される。 同年、Lotus, Intel, Microsoft, それに ATSを加えて EMS 4.0 が策定されており、Windows 2.0でサポートされた。 この時点では8086/8088を搭載したマシンも多く、その場合はハードウェアタイプのExpanded Memoryを利用出来た。(プロテクトモードの1MB超えのメモリ領域を使ったソフトウェアエミュレーションタイプのEMSを利用するには後述の80286が必要だったが、80286自体は1982年に既に発表されている。1987年の時点で "IBM PC AT" や "IBM PC XT 286" など80286が搭載されたマシンも出回っていた。) 他にも、Windows1.0ではタイル上に配置されたWindowが、WIndows2.0になって新しいWindowが古いWindowの上に重なるようになり、より「デスクトップ」のメタファーに近づいた。 Windows 2.0はEMS4.0に対応したとはいえ、未だにDOS上で動作するリアルモードのプログラムであった。とはいえ、ルックスの改良やExcelやPageMakerなどのキラーアプリケーションの出現によりある程度の成功を収めている。 #navi_footer|技術|