#navi_header|Assembler|
English Version: " [[Why BIOS loads MBR into 0x7C00 in x86 ?>http://www.glamenv-septzen.net/en/view/6]] "
[[610]] ''で調査が不十分だった点を補った完全版です。''
: 対象読者 : x86アーキテクチャとアセンブラの基礎知識があり、MBRからのOSのロードに興味がある人("割り込みベクタ"や"INT xxx"と言われても「???」とならない人)。
自分がx86アーキテクチャの、特にOSのブートする仕組みやプロテクトモードを学習した時、MBR(Master Boot Record)で最初の一歩を踏み出した。MBRはフロッピーディスク(FDD)やHDDの最初の1セクタ:512バイトブロックである。OSをブートする機械語のプログラムと、ディスクの論理パーティション情報が格納されている。Interlの80x86系列のCPUを採用しているPCは、電源投入後、まずBIOSのPOST(Power On Self Test)が行われ、周辺機器が認識された後、MBRを読み込んでOSのブート処理を開始する。
BIOSはROMチップに書き込まれている為通常は変更出来ない(EEPROMなど、書き換え可能なROMを使っており、BIOSアップデートなどの特殊なソフトウェアを使うことで書き換えることができる)。一方のMBRはFDD/HDDの最初の1セクタということで、プログラマ自身が書き換えることが可能である。
2010年現在、Bochs, QEMU, VirtualBox, VMwareなどの仮想環境を手軽に活用できる環境が整っている。
そうした仮想環境を利用すれば、仮想環境用のディスクイメージファイルのMBR部分に好きな機械語を書き込むだけで、手軽に機械語の実験を行うことが可能になる。ホストOS側の現実の物理HDDのMBRを書き換えてOSが立ち上がらなくなる心配も無い。
多くの書籍やWebの記事では次のような流れでMBRのコードが実行される、と説明している。
+ BIOSがPOST(Power On Self Test)を実行
+ POST後、BIOSはFDD or HDDのMBRを ''0x7C00'' にロードし、そこから処理を続行する。(もちろんCD/DVDからブートすることも出来るが、本記事ではFDD/HDDからのブートを扱う。)
+ MBRにはOSのカーネルをロードし、実行する為の機械語が格納されており、OSのブートが始まる。
MBRから直接OSのカーネルをロードするのではなく、一つ or 二つ程度の中間ローダを介する場合もある。MBRの機械語コード、およびMBRがロード&実行する中間ローダはOS固有の場合(MicrosoftのNTLDR)もあれば、複数のOSに対応したオープンソースソフトウェアの場合(LILO, GRUB)もある。
ところで、実際にMBRを弄った人は、次の疑問を抱いたことはないだろうか?
「"0x7C00"って、どこの仕様書で決められているんだろうか?」
x86CPUについて学んでいくと、独特の"メモリアドレスのマジックナンバー"がいくつかあることに気づく。
: 64KBの壁 : もちろん、「セグメント16bit:オフセット16bit」の組み合わせによる、1セグメント64KBの制限値である。
: 0x3FF : #block||>
これは割り込みベクタ用のメモリ空間で、
4バイトの割り込みハンドラのアドレス x 256個の割り込みベクタ
= 1024バイト
= 0x400 バイト
で、x86の仕様として割り込みベクタはアドレス0番地から始まる為、一つ分ずらした値となる。
||<
: 0xFFFFF(1MB) : リアルモードでの最大アドレス値。これは80186以前はアドレスバスが20本、20bit = 指定可能な最大値が0xFFFFFだったことに基づく。
: 0xFFFF0 : IBM PC(5150)の誕生に深く関わる Intel 8086/8088 が、電源投入の初期化後に最初に処理を開始するアドレス。
・・・ところが、"0x7C00" の意味については、CPU関連を調べても何も分からない。ブートローダやMBR関連の情報を調べても、単に0x7C00にロードされる、と書かれているだけで、なぜこの値なのか?誰が決めたのか?についての情報は皆無にみえる。
前ぶりが長くなったが、 ''本記事はMBRがロードされる "0x7C00" というアドレスの起源と、その意味について調べた結果をまとめている。''
この記事単体で何かしら「使える」知識を増やすことは出来ないが、もしも読者のあなたが "0x7C00" について喉に魚の骨が刺さったままのような感触を覚えているのであれば、ぜひ一読をお奨めしたい。
#more||
#outline||
----
* IBM PC(5150) 誕生前後の流れの再確認
"0x7C00" が ''「いつ」'' 現れたのかについて先に結論を言うと ''1981年8月に発表された IBM Personal Computer (PC) 5150の ROM BIOS'' で初めて現れた。
IBM PC 5150は16bit/8bit両対応のCPU Intel 8088 を使った、現在に連なるx86アーキテクチャのご先祖様に相当する。短い開発期間と、それまでのIBMのやり方と異なるオープンアーキテクチャの採用など、歴史の転換点にふさわしくその誕生はドラマティックな数々のエピソードに彩られている。
ここでIBM Personal Computer(PC), モデル番号5150誕生前夜の歴史について簡単に確認しておく。
Intel 4004 に始まる汎用CPUは、8bitの Intel 8080(1974年) でマイクロコンピュータ市場を席巻した。MITS Altair8800(1975年) にも搭載された。Digital Research社のOS、CP/M は1974-1975年前後に誕生したとされているが、8bitマイコン市場の盛り上がりと共に、CP/Mは互換CPUやほかのマイコンシステムへの移植が進んでいった。
当時既にメインフレーム市場で巨人となったIBMも、その流れを無視していたわけではない。
1975年には "5100 Portable Computer" を発表、1978年には "IBM 5110 Computing System"、1979年には "5520 Administrative System"、1980年2月には "5120 Computer System" と、机の上に載るサイズのコンピュータシステムを発表している。しかしいずれもビジネスオフィス、あるいは科学技術計算用途に使われており、マイコン市場には食い込めていない。
1980年、ドン・エストリッジをリーダーとする12人のチームは、1年という制約期間でIBM初の "Personal Computer" を開発し、マイコン市場に挑戦する事になる。この時に採用されたのが 8bit/16bit両対応の Intel 8088である。
ソフトウェアでさしあたり必要なのはプログラミング言語とOSで、プログラミング言語はMicrosoft社の開発したBASICをROMに搭載することになった。OSについては、一度Digital Research社のCP/Mを採用しようと商談を進めたようだがうまくまとまらず、こちらも最終的にMicrosoft社に依頼することになった。当時マイコン市場で人気のCP/Mに対応したソフトを動かしたいということで、CP/M互換OSの開発を依頼した。
この辺は有名な話になるが、当時のMicrosoft社にはOSを開発した経験が無かった。どうしたかというと、Seatle Computer Products(SCP)のTim Patersonが開発した8086対応のCP/M互換OS、"86-DOS"(初期には"QDOS : Quick and Dirty Operating System"と呼ばれていた)を買い取り、それをベースにIBM PC 5150用のCP/M互換OSを開発した。
1979年当時は"S-100"というバスを使ったマイコンがAltair8800やIMSAI 8080で主に使われており、SCPもS-100バスに挿せる形で8086CPUボードとそのOSを提供しようとしていた。OSについては当初はDigital Research社により8086に対応したCP/Mが提供されるのを期待していたらしい。
1979年の11月には、SCPによる8086CPUボードとスタンドアロンで動作するBASICが出荷されたが、中々CP/Mの8086対応が進まないため、自分達で互換OSを開発することを1980年の4月に決定。
1980年の8月にはQDOS 0.10をリリースし、1980年の年末には "86-DOS" ver 0.3 をリリース、同時にMicrosoft社に提供している。
これとほぼ同時期に、Digital Research社も8086対応のCP/M-86をリリース。
1981年の7月にはMicrosoftによりDOSの全権利が買い取られ、1981年の8月、86-DOSと「非常によく似たOS」であるPC-DOSがIBM PC 5150とともに発表される事になる。
* 86-DOS → PC-DOS + ROM BIOS
2010年現在のPCでは、マザーボード上のROMチップにBIOSが搭載され、OSはHDDなど外部記憶ディスクに保存されるのが常識となっている。この棲み分けは、まさしく IBM PC 5150 が原点となっている。
というのも、 ''MS-DOSの原型にあたる86-DOS(とCP/M)ではBIOS相当の機能もOSの一部に含まれていた。''
BIOSの機能というのは、
+ メモリやCPUのチェック、周辺機器の認識など現在のPOSTにあたる機能に加え、
+ CP/M互換OSが使うソフトウェア割り込み処理も含まれる。
もちろんPOST処理は重要だが、それ以上にOSが使うソフトウェア割り込みも重要で、これにより画面上に文字や図形を描画したり、FDD/HDDにアクセスしてデータを読み出したり、ファイル処理やプログラムをメモリ上にロードしたりしていた。当時はそうした機能が全て"OS"の中に含まれていたことになる。86-DOSのベースとなったCP/Mもそのようになっていた。
これが OS と BIOS に分離された形式になり、以降の流れを決定づけた起点が IBM PC 5150 である。
** 閑話休題:0xFFFF0(Intel 8086/8088がハードリセット後に最初に実行するアドレス)
ここで、そもそもx86のCPU自身が、ハードリセット(電源投入)後電子回路のレベルで初期化され、最初に命令をフェッチするアドレスについて再確認しておきたい。
| CPU | CS | IP | 物理アドレス |
| 8086/8088 | F000H | FFF0H | FFFF0H |
| 80286 | F000H(※1) | FFF0H | FFFFF0H |
| 80386以降 | F000H(※2) | FFF0H | FFFFFFF0H |
どの世代でも、当時のマシンに搭載されていた標準的な物理メモリを越えた場所を指している。
これは割り込みベクタの影響でアドレス0を使えない為と、最初の命令フェッチから始まる初期化プログラムをなるべくアドレスの高位に配置することで、一般的なプログラムの使えるアドレス空間を邪魔しないようにとの意図らしい。
BIOSが格納されたROMは、電子回路のレベルでこれら高位アドレスにマッピングされるよう調整されている。
IBM PC 5150 ではROM BIOSがFE000以降にロードされるようになっており、丁度 FFFF0H に、BIOSコードの先頭へJMPする機械語コードが配置されている。(後述)
※1 : 80286は24bitのアドレスバスを持つが、リアルモードでは20bitしか使われない。A20-A23はリセット後は1になっている。そのため、CSこそ"F000H"になっているが、もう4bit分全て1のデータが上位に隠れている。
(F)F0000 H(CS) (4bit左シフト)
FFF0 H(IP)
--------------
F FFFF0 H
となり、"FFFFF0H"が最初にフェッチされるアドレスとなる。
参考:
- "M80C286 HIGH PERFORMANCE CHMOS MICROPROCESSOR WITH MEMORY MANAGEMENT AND PROTECTION"
-- "Memory Addressing", "Reserved Memory Locations" (p10)
※2 : 80386ではアドレスバスが32bitになるが、リアルモードでは20bitしか使われない。A20-A31はリセット後は1になっている。そのため、CSこそ"F000H"になっているが、もう12bit分全て1のデータが上位に隠れている。
(FFF)F0000 H(CS) (4bit左シフト)
FFF0 H(IP)
--------------
FFF FFFF0 H
参考:
- "INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986"
-- "10.1 Processor State After Reset" (p174)
-- "10.2.3 First Instructions" (p176)
** 86-DOS のブートプロセス(MBRを200Hにロード)
SCPは8086用CPUボードの他に"CPU Support Card"というボードも開発した。"CPU Support Card"にはデバッグ機能とbootstrapローダ機能を備えた、2KBの機械語プログラム("Monitor")が搭載されていた。
Monitorを使うと、マシン起動後はMonitorのコマンドプロンプトが最初に表示される。ここで"B"コマンドを実行することで、ディスクの先頭セクタをbootstrapとして 200H にロードし、bootstrapの先頭にジャンプして処理を続行する。
Monitorプログラムは8086のメモリ空間(1MB)の末尾2KBに位置するようになっている。
8086が電源投入後に最初にフェッチするアドレス FFFF0H には、Monitorプログラム上で次の機械語が配置されるようになっている。
JMP 0,0FF80H ;Power-on jump to monitor
セグメント指定のFARジャンプで、
FF80:0000 → FF800 H
にジャンプすることになる。FF800HからはMonitor用のコードが始まる。
MON.ASM:
#pre||>
;Start of Monitor code
ORG 0
PUT PUTBASE ; 無視してOK(恐らく当時のアセンブラ独特の疑似命令)
;One-time initialization
UP ; 今のアセンブラでは"CLD"
XOR AX,AX
MOV SS,AX
(...)
||<
オフセット(ORG)が0になっているが、これは(恐らく)アセンブラの都合とMonitor用のボードの電子回路的な都合によるものだろう。
この時点でのメモリ空間:
#pre||>
+---------------------- FFFFFH
|
+----------------------
| JMP 0,FF80H FFFF0H
+----------------------
|
|
| Monitor コード FF800H
+----------------------
|
|
+---------------------- 3FFH
|(割り込みベクタ)
+---------------------- 0H
||<
Monitorのコマンドプロンプトで"B"コマンドを実行すると、FDDの先頭512バイトを200Hにロードする。
MON.ASM:
#pre||>
(...)
LOAD: EQU 200H
(...)
COMTAB:
DW BOOT ;B
DW PERR ;C
(...)
BOOT:
PUSH DI
(以下、当時のディスクコントローラ毎に200Hにロードするコード)
;Successful read
MOV [CSSAVE],0
MOV [IPSAVE],LOAD
POP DI
JMP GO ; GOルーチン内でレジスタ調整後、CS:0000H,IP:200H(LOAD)へJMP
||<
これにより読み込まれるbootstrapのアセンブラが、BOOT.ASMとして86-DOSに同梱されている。
BOOT.ASMを読んでみると、SS(Stack Segment)に0, SP(Stack Pointer)に200Hをセットしている。bootstrap実行中の一時的なスタック領域は200Hから始まることが分かる。
BOOT.ASM(bootstrap)を200Hへロードした後のメモリ空間:
#pre||>
+---------------------- FFFFFH
|
+----------------------
| JMP 0,FF80H FFFF0H
+----------------------
|
|
| Monitor コード FF800H
+----------------------
|
|
+---------------------- 3FFH これ以下↓が8086の割り込みベクタ
| BOOT.ASM
+---------------------- 200H これ以下↓がBOOT.ASMが使うスタック領域
|
+---------------------- 0H
||<
200HにロードされたBOOT.ASM中では引き続きシステムをディスクからロードする処理が続く。BOOT.ASMではOSの基本部分を400H以降にロード後、400HにJMPする。ちょうど400Hから始まるOSの基本部分の一部が、DOSIO.ASMとして86-DOSに同梱されている。
BOOT.ASM:
#pre||>
ORG BOOTER
(...)
MOV DI,LOAD ; LOAD equ 400H
(...)
READ:
(...)
DONE:
(...)
JMP 0,SEG ; SEG equ 40H
||<
最後のJMPはfarジャンプとなり、CS:40H, IP:0H → 400Hにジャンプする。
ちなみに、まだこの時点では割り込みベクタは初期化されていない。MON.ASMやBOOT.ASMを読んでみるとINT命令が全く使われていないことに驚く。
OSの基本部分を400Hへロードした後のメモリ空間:
#pre||>
+---------------------- FFFFFH
|
+----------------------
| JMP 0,FF80H FFFF0H
+----------------------
|
|
| Monitor コード FF800H
+----------------------
|
| DOSIO.ASM + その他OS
| の基本部分
+---------------------- 400H以上↑領域
+---------------------- 3FFH これ以下↓が8086の割り込みベクタ
| BOOT.ASM
+---------------------- 200H これ以下↓がBOOT.ASMが使うスタック領域
|
+---------------------- 0H
||<
いよいよOSの初期化処理が始まる。400HにJMP後、SSは0にクリアされ、SPも400Hに変更される。BOOT.ASMはもう使わないので、直前までBOOT.ASMがロードされていた 200H - 3FFH のメモリ空間をOSの初期化処理用のスタック領域に使うことを意味する。
SS, SP調整後、この時点でロード済のメモリ 800H 以降のルーチンをCALLする。
DOSIO.ASM:
#pre||>
(...)
DOSSEG: EQU 80H
ORG 0
(...)
JMP INIT
(...)
INIT:
(...)
XOR AX,AX ; AXが0クリア
MOV SS,AX ; SSが0Hに。
MOV SP,400H ;Set stack just below I/O system
(...)
CALL 0,DOSSEG ; 80H:0Hのサブルーチン呼び出し
MOV DX,100H
MOV AH,26 ;Set DMA address
INT 21H
(以下、COMMAND.COMの起動へ続く)
||<
この 800H のルーチンCALLにより、INT20h以降のソフトウェア割り込みベクタが調整され、OSの提供するINT機能が使えるようになる。
800Hより戻ってきたら、引き続きCOMMAND.COMの起動に入り、OSのユーザに対するインターフェイスである、コマンドプロンプトを開始する。(COMMAND.COM起動時にはSS,SPも再調整される)
COMMAND.COM起動後のメモリ空間:
#pre||>
+---------------------- FFFFFH
|
+----------------------
| JMP 0,FF80H FFFF0H
+----------------------
|
|
| Monitor コード FF800H
+----------------------
|
| OS + COMMAND.COM
| + ユーザープログラム
|
+---------------------- 400H
+---------------------- 3FFH
|(割り込みベクタ)
+---------------------- 0H
||<
以上が86-DOSのブートの流れである。
参考:
- 86-DOS Resource Website
-- http://www.86dos.org/index.htm
--- "86DOS_FILES.ZIP"中のMON.ASM, BOOT.ASM, DOSIO.ASM
- Early DOS Manuals
-- http://www.patersontech.com/dos/manuals.aspx
--- "First Advertisement for the 8086 Computer"
--- "8086 Monitor Instruction Manual"
--- "86-DOS Instruction Manual"
--- "86-DOS Programmer's Manual"
** 86-DOSがbootstrapを 200H にロードする理由 (From Tim Paterson)
86-DOS ではディスクの先頭に配置されているbootstrapを 200H にロードしている。
この "200H" という値は、8086の割り込みベクタ(0H - 3FFH)の内部である。
Tim Paterson によれば、CPUの割り込みベクタ内であり仕様的には「予約済」であることと、そのためにOS自身は0H-3FFH内には絶対にロードされない「安全地帯」であることが、200Hを選択した理由とのこと。
From Tim Paterson:
>At SCP, I chose 0x200 because it was in the interrupt vector space (0 -
>3FFH). This means it needed to be reserved and couldn't be in the way of
>an OS, no matter where it wanted to load.
まとめると
+ 0x0 - 0x3FF は8086の仕様上、割り込みベクタに使われていた。
+ 0x400 以降に86-DOSのシステムがロードされる。
+ 0x200 - 0x3FF の間の割り込みベクタは86-DOSの時点では特に使っていなかった。
以上の理由で 200H - 3FFH の間の隙間が使われた。ちなみに、100H - 200H の間も、レジスタの退避やMonitor/bootstrapなどの初期処理が使うスタック領域として利用されていたらしい。
* IBM PC(5150) ROM BIOS INT19h
86-DOSやCP/Mでは、bootstrapのロードや割り込みベクタの調整と対応するハンドラなどが全て"OS"の中に含まれていた。
これが、IBM PC 5150において次のように分裂した。
- ROM BIOS
-- IBMが開発
-- OSに関わらず最低限度必要な機能(bootstrapのロードや基本的な割り込みハンドラ、POST処理)
- OS本体 + MBR
-- Microsoftが開発
-- bootstrap(MBR)やOS固有の初期化処理、割り込みハンドラ、COMMAND.COM
86-DOSやCP/Mが厳密にMS-DOSの祖先かというと議論が必要なようだが(例:メモリレイアウトの設計コンセプトが大幅に変更されている。86-DOSでは"640KBの壁"という制限は無かった。)、とにかく、IBMとMicrosoftの二社協同で分担したことが、現在に至るBIOSとOSの役割分担の起源であることは間違いないだろう。
IBM PC 5150 の ROM BIOS でMBRを 7C00H にロードするのは INT 19h というソフトウェア割り込みハンドラである。
これは ROM BIOS により割り込みベクタに登録されると共に、POST後に INT 命令で呼ばれる。
ちなみに5150ではROM BASICを起動する INT 18h というソフトウェア割り込みも存在し、INT 19hでMBRのロードに失敗した場合に INT 18h が呼ばれるようになっていた。
** INT 19h までの流れ(MBRを7C00Hにロード)
5150のROM BIOSのアセンブラリストは、"IBM Personal Computer Technical Reference manual"に掲載されている。
実際にBIOSのアセンブラコードを追いつつ、INT 19hまでの流れを簡単に追ってみる。
line.6199 - :
#pre||>
VECTOR SEGMENT AT 0FFFFH
JMP RESET
DB '10/27/82' ; RELEASE MARKER
VECTOR ENDS
||<
"SEGMENT" - "ENDS" はコードの配置を決定する擬似コード。セグメントが "0FFFFH" で先頭がJMP命令と言うことは、物理アドレス上は
FFFFH:0000H = FFFF0H : JMP RESET
ということになる。つまり、CPUのハードリセット直後にフェッチされる命令は"RESET"ラベルへのJMPとなる。
ちなみに"RELEASE MARKER"が1982年になっているが、入手出来たドキュメントのバージョンが1983年4月の改訂版なので、その影響だろう。
RESETラベルは308行に存在し、8088CPUのテストコードが始まる。以降、現在のPOSTに相当するCPU/メモリ/HWのチェックコードが続く。
line.306 - :
#pre||>
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
ORG 0E05BH
RESET LABEL FAR
START:
CLI ; DISABLE INTERRUPTS
MOV AH,0D5H
SAHF
(...)
||<
気になるのが、
ASSUME CS:CODE,...
と
ORG 0E05BH
の二行。なぜ初期化コードが中途半端な場所から始まるのか?
まず "CODE" については224行目で次のようにSEGMENT 0F000H が指定されている。
line. 224 - :
CODE SEGMENT AT 0F000H
その直後、56KB分データ領域(?)を確保している。
line. 225 - :
DB 57344 DUP(?) ; FILL LOWEST 56K
57344 = E000 H
となり、さらにE000Hから暫くはデータやストレージのR/Wテスト用サブルーチンが配置されており、結果としてRESETラベルは "0E05BH" から始まる。
RESETラベルから始まる初期処理に戻ると、1132行目からDISKETTE(FDD)のテストに入り、OKであればINT 19hを呼ぶ。
line. 1132 - :
#pre||>
;-----------------------------------------------------------------------;
; DISKETTE ATTACHMENT TEST ;
; DESCRIPTION ;
; CHECK IF IPL DISKETTE DRIVE IS ATTACHED TO SYSTEM. IF ATTACHED, ;
; VERIFY STATUS OF NEC FDC AFTER A RESET. ISSUE A RECAL AND SEEK ;
; CMD TO FDC AND CHECK STATUS. COMPLETE SYSTEM INITIALIZATION ;
; THEN PASS CONTROL TO THE BOOT LOADER PROGRAM. ;
;-----------------------------------------------------------------------;
F9:
MOV AL, BYTE PTR EQUIP_FLAG
(...)
(line. 1261)
;----- ENABLE NMI INTERRUPTS
MOV AL,80H ; ENABLE NMI INTERRUPTS
OUT 0A0H,AL
CMP MFG_TST,1 ; MFG MODE?
JE F21 ; LOAD BOOT_STRAP
MOV DX,1
CALL ERR_BEEP ; BEEP 1 SHORT TONE
F21: ; LOAD_BOOT_STRAP:
INT 19H ; BOOTSTRAP
||<
割り込みベクタはいつ初期化されたのか?E05Bから始まる初期処理の途中、595行目からBIOS用の割り込みベクタの初期化が行われている。line. 595 - :
#pre||>
;----- SET UP THE BIOS INTERRUPT VECTORS TO TEMP INTERRUPT
MOV CX, 32 ; FILL ALL 32 INTERRUPTS
SUB DI,DI ; FIRST INTERRUPT LOCATION
D3:
MOV AX,OFFSET D11 ; MOVE ADDR OF INTR PROC TO TBL
STOSW
MOV AX, CS ; GET ADDR OF INTR PROC SEG
STOSW
LOOP D3 ; VECTBL0
;----- SET UP OTHER INTERRUPTS AS NECESSARY
MOV NMI_PTR,OFFSET NMI_INT ; NMI INTERRUPT
MOV INT5_PTR,OFFSET PRINT_SCREEN ; PRINT SCREEN
MOV BASIC_PTR+2,0F600H ; SEGMENT FOR CASETTE BASIC
||<
(すみません、この辺はきちんと読み切れてません。この直ぐ上の592行目で既に INT 3EH が呼ばれていたりするので、割り込みの種類毎に何段階かにわけて初期化しているのかもしれません。あるいは途中の分岐を読み飛ばしている、など。少なくとも INT 19h の読み出しまでに、割り込みベクタが初期化されていることは確かです。でないとINT 19hをそもそも呼べないので。)
INT 19h の割り込みハンドラは1493行目から始まる。
line. 1493 - :
#pre||>
;--- INT 19 ------------------------------------------------------
; BOOT STRAP LOADER ;
; IF A 5 1/4" DISKETTE DRIVE IS AVAILABLE ON THE SYSTEM, ;
; TRACK 0, SECTOR 1 IS READ INTO THE BOOT LOCATION ;
; (SEGMENT 0, OFFSET 7C00) AND CONTROL IS TRANSFERRED ;
; THERE. ;
; ;
; IF THERE IS NO DISKETTE DRIVE, OR IF THERE IS A ;
; HARDWARE ERROR CONTROL IS TRANSFERRED TO THE RESIDENT ;
; BASIC ENTRY POINT. ;
; ;
; IPL ASSUMPTIONS; ;
; 8255 PORT 60H BIT 0 = 1 IF IPL FROM DISKETTE ;
;-----------------------------------------------------------------
ASSUME CS:CODE,DS:ABS0
;----- IPL HAS SUCCESSFUL
H4:
JMP BOOT_LOCN
ORG 0E6F2H
BOOT_STRAP PROC NEAR
STI ; ENABLE INTERRUPTS
(...)
;----- MUST LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT
MOV CX,4 ; SET RETRY COUNT
H1: ; IPL_SYSTEM
PUSH CX ; SAVE RETRY COUNT
MOV AH,0 ; RESET THE DISKETTE SYSTEM
INT 13H ; DISKETTE_IO
JC H2 ; IF ERROR, TRY AGAIN
MOV AX,201H
SUB DX,DX
MOV ES,DX
MOV BX,OFFSET BOOT_LOCN
MOV CX,1 ; SECTOR 1, TRACK 0
INT 13H ; DISKETTE_IO
H2: POP CX ; RECOVER RETRY COUNT
JNC H4 ; CF SET BY UNSUCCESSFUL READ
LOOP H1 ; DO IT FOR RETRY TIMES
;----- UNABLE TO IPL FROM THE DISKETTE
H3: ; CASSETE_JUMP:
INT 18H ; USE INTERRUPT VECTOR TO GET TO BASIC
BOOT_STRAP ENDP
||<
"H4"ラベルがなぜ"BOOT_STRAP"の前に位置しているのかが謎だが、とにかく、"H2"ラベルで読み出し成功と判断されると"JNC H4"でH4にジャンプし、そのまま "BOOT_LOCN" にジャンプするようになっている。
"BOOT_LOCN"はROM BIOSのアセンブラリストの冒頭で ''7C00H'' にEQU(equate)されている。
line. 34 - :
#pre||>
;---------------------------------
; 8088 INTERRUPT LOCATIONS ;
;---------------------------------
ABS0 SEGMENT AT 0
STG_LOC0 LABEL BYTE
ORG 2*4
NMI_PTR LABEL WORD
ORG 5*4
INT5_PTR LABEL WORD
(...)
ORG 7C00H
BOOT_LOCN LABEL FAR
ABS0 ENDS
||<
ここで、
JMP BOOT_LOCN
がセグメント内のNEARジャンプになってしまうのでは?と疑問に思った人もいるだろう。
ROM BIOSのアセンブラリストには、対応する機械語も掲載されている。このJMPに対応する機械語を見てみると、次のようになっている。
EA007C0000
=
E A 00 7C 00 00
1110 1010 (offset L-H) (segment L-H)
よって、これはセグメント指定のFARジャンプであり、ジャンプ後は
CS:0000H, IP:7C00H
となる。よって問題なく、0000:7C00HにJMPできる。
** IBM PC 5150 の ROM BIOS INT 19h が MBR を 7C00H(0x7C00) にロードする理由 (From Dr. David Bradley)
いよいよ 7C00H の謎が解かれる。
が、その前に 7C00H のそもそもの謎について再確認したい。
まず 7C00H というのは
32KB(8000H) - 1024B
である。先頭から32KB、その丁度1024バイト手前が、7C00Hである。まず一点目、この"32KB - 1024 = 7C00"というのがいかにも意味ありげであり、なぜこの場所にしたのか?というのが謎の一つめ。
謎の2つ目が、IBM PC 5150 発表時の最小メモリモデルが ''16KB(4000H) のRAMしか積んでいない'' こと。つまり、16KBのRAMでは当然7C00にMBRをロードすることは出来ない。よって16KBモデルではDOSを起動出来なかったのではないか?
まとめると:
- "0x7C00" は 32KB - 1024Bに位置する。なぜこの位置なのか?
- 5150の最小メモリモデルは16KBしかRAMを搭載していない。 → 16KBのモデルではOSを起動出来なかったのではないか?(0x7C00にアクセス出来ない)
この2点について、IBM PC 5150 の ROM BIOS の開発者、David Bradley氏にメールで質問してみた。同氏は"Ctrl-Alt-Delete"によるリセット機能を実装したことで知られている。
なお質問で「86-DOSは200Hにロードするが、なぜ変更したのか?」というのも含めたが、
>I don't know anything about 86-DOS.
と回答している。つまり同氏は 86-DOS のコードは見ずに、つまり "86-DOSは200Hにbootstrapをロードする" 事実は知らないまま、ROM BIOSを開発した。
ではDavid Bradley氏からの回答で、まずは16KBモデルについての回答から。
>It had to boot on a 32KB machine.
>DOS 1.0 required a minimum of 32KB, so we weren't concerned about attempting a boot in 16KB.
DOS 1.0 は最小で32KBを必要としていた為、16KBのメモリモデルについては考慮しなかったとのこと。
続いていよいよ、「なぜ32KB-1024Bなのか?」に対する回答:
>We wanted to leave as much room as possible for the OS
>to load itself within the 32KB. The 808x Intel architecture
>used up the first portion of the memory range for software
>interrupts, and the BIOS data area was after it. So we put
>the bootstrap load at 0x7C00 (32KB-1KB) to leave all the room
>in between for the OS to load. The boot sector was 512 bytes,
>and when it executes it'll need some room for data and a stack,
>so that's the other 512 bytes. So the memory map looks like
>this after INT 19H executes:
+ OSの必要とする最小メモリ、32KBをなるべく空けておきたかった。
+ アドレス0から始まる 0H - 3FFH までは割り込みベクタとして予約されているので使えない。
+ なので、32KBの末尾にロードするようにした。
+ MBR中のbootstrap自身が使うデータやスタック用に、もう512バイト確保した。
+ よって、32KB - 512B(MBR) - 512B(データとスタック) で、7C00H とした。
同氏によれば、INT 19h実行後のメモリレイアウトは次のようになる:
#pre||>
+--------------------- 0x0
| Interrupts vectors
+--------------------- 0x400
| BIOS data area
+--------------------- 0x5??
| OS load area
+--------------------- 0x7C00
| Boot sector
+--------------------- 0x7E00
| Boot data/stack
+--------------------- 0x7FFF
| (not used)
+--------------------- (...)
||<
以上が、四半世紀を越えて x86 IBM PC/AT互換機上のOSのbootstrapを支配してきた "0x7C00", "7C00H" の出自である。
* 参考資料
86-DOS関連PDF資料:
- "8086 Monitor Instruction Manual"(MON 86 - V1.4)
- "86-DOS(TM) User's Manual Version 0.3"
- "86-DOS(TM) Programmer's Manual Version 0.3"
- "86-DOS(TM) Instruction Manual Version ??"
IBM PC 5150 関連PDF資料:
- "IBM Personal Computer Hardware Reference Library", "Technical Reference" (IBM Personal Computer Technical Reference manual)
- "IBM Personal Computer XT Hardware Reference Library", "Technical Reference" (IBM Personal Computer XT Technical Reference manual)
Intel CPU データシートPDF:
- "8086 16-BIT HMOS MICROPROCESSOR"
- "M80C86/M80C86-2 16-BIT CHMOS MICROPROCESSOR"
- "8088 8-BIT HMOS MICROPROCESSOR"
書籍:
#amazon||>
||<
#amazon||>
||<
#amazon||>
||<
以下、参考URL。
** "Personal Computer"の歴史
- Xerox Alto - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Alto_%28computer%29
--- 初期の "Personal Computer", 1973年
- Altair 8800 - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Altair_8800
--- Intel 8080 搭載のマイクロコンピュータ, 1975年
*** Apple関連
- Apple (disambiguation) - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Apple_%28disambiguation%29
- Apple I - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Apple_I
- Apple II series - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Apple_II_series
- Apple III - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Apple_III
- List of products discontinued by Apple Inc. - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/List_of_products_discontinued_by_Apple_Inc.
- TK-80 - Wikipedia
-- http://ja.wikipedia.org/wiki/TK-80
*** NEC勢
- PC-8000シリーズ - Wikipedia
-- http://ja.wikipedia.org/wiki/PC-8000%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA
- PC-8800シリーズ - Wikipedia
-- http://ja.wikipedia.org/wiki/PC-8800%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA
- PC-6000シリーズ - Wikipedia
-- http://ja.wikipedia.org/wiki/PC-6000%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA
- PC-9800シリーズ - Wikipedia
-- http://ja.wikipedia.org/wiki/PC-9801
*** CP/M関連
- CP/M - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/CP/M
- Gary Kildall - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Gary_Kildall
- The Unofficial CP/M Web Site
-- http://www.cpm.z80.de/
- CP/M Internals : Oscar Vermeulen Personal Web Site
-- http://www.dcast.vbox.co.uk/cpm.html
--- メモリレイアウトやブートコードなど、マニアック。
- Digital Research - CP/M
-- http://www.digitalresearch.biz/CPM.HTM
--- Digital Research社本家のCP/Mページ
- CP/M Main Page
-- http://www.seasip.demon.co.uk/Cpm/
- CP/M-86 - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/CP/M-86
--- 8086対応のCP/M。これが1年でも早くリリースされていたら、PCは別の道を歩んでいたかも知れない。
*** 86-DOS, Tim Paterson 氏, 初期のMS-DOS(PC-DOS)関連
- QDOS - Wikipedia
-- http://ja.wikipedia.org/wiki/QDOS
- 86-DOS - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/86-DOS
- 86-DOS Resource Website
-- http://www.86dos.org/index.htm
--- Altair8800のシミュレータおよびその86-DOSイメージのリンクがある。
--- 86-DOSのファイルセットがzipで入手可能。
- Tim Paterson - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/Tim_Paterson
Tim Paterson 氏のサイト:
- Early DOS Manuals
-- http://www.patersontech.com/dos/manuals.aspx
--- 86-DOSの各種マニュアルがDL可能。
- An Inside Look at MS-DOS
-- http://www.patersontech.com/dos/Byte/InsideDos.htm
--- 初期のDOSの設計思想、初期FATファイルシステムの解説
- A Short History of MS-DOS
-- http://www.patersontech.com/dos/Byte/History.html
--- CP/M → SCP QDOS → SCP 86-DOS → IBM PC 5150 PC-DOS への転換点の当事者による記録
- DosMan Drivel
-- http://dosmandrivel.blogspot.com/
--- Tim Paterson 氏による初期DOSの詳しい歴史や解説Blog
- MS-DOS - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/MS-DOS
- The DOS Memory Map
-- http://www.nolm.org/TAE/c016p08.htm
--- DOSのメモリレイアウト
*** 初期のMS-DOSの日本語資料
- MS-DOS - Wikipedia
-- http://ja.wikipedia.org/wiki/MS-DOS
- DOSの歴史セミナ
-- http://hp.vector.co.jp/authors/VA000199/history.html
- Software Design 1998.6 MS-DOS HISTORY -colors of Peole
-- http://www.os.rim.or.jp/~ppp/msdos/SD/
*** IBM PC 5150 前後の歴史について
- PC History: The PC at 20
-- http://pcworld.about.com/magazine/1908p133id52503.htm
- PCの歴史関連URL(日本語資料)
-- http://www.sanosemi.com/history_of_PC_refURL.htm
- 図書カード:パソコン創世記
-- http://www.aozora.gr.jp/cards/000055/card365.html
- IBM 5100 computer, 1975年
-- http://oldcomputers.net/ibm5100.html
- Welcome to the Retrocomputing Archive
-- http://www.retroarchive.org/dos/docs/
--- 各種PDF資料
- PC Technical Reference Manual -- by Jalkanen Art & Science
-- http://www.tec.sci.fi/tecref/
--- Technical Reference manualのHW/メモリレイアウトを見やすくまとめ直したCheatSheet
- IBM提供のIBM PCの歴史関連資料
-- IBM Archives: Exhibits
--- http://www-03.ibm.com/ibm/history/exhibits/index.html
-- IBM Archives: The IBM Personal Computer
--- http://www-03.ibm.com/ibm/history/exhibits/pc25/pc25_intro.html
-- IBM Archives: IBM Personal Computer
--- http://www-03.ibm.com/ibm/history/exhibits/pc/pc_1.html
-- IBM Archives: The birth of the IBM PC
--- http://www-03.ibm.com/ibm/history/exhibits/pc25/pc25_birth.html
- Vintage IBM 5150 Documentation Page
-- http://www.ibm5150.net/docs.html
--- 当時のBASICやTechnical Reference manualがDL可能。
その他IBM PC関連のWikipage:
- http://en.wikipedia.org/wiki/IBM_Personal_Computer
- http://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
- http://en.wikipedia.org/wiki/IBM_PCjr
- http://en.wikipedia.org/wiki/IBM_Personal_Computer/AT
- http://en.wikipedia.org/wiki/IBM_Personal_System/2
- http://en.wikipedia.org/wiki/IBM_PC_compatible
*** David Bradley氏関連
- David Bradley (engineer) - Wikipedia, the free encyclopedia
-- http://en.wikipedia.org/wiki/David_Bradley_%28engineer%29
- Inventor of the Week: Archive
-- http://web.mit.edu/invent/iow/bradley.html
- USATODAY.com - Man who invented Ctrl-Alt-Del key combo retiring
-- http://www.usatoday.com/tech/news/2004-01-29-david-bradley-retires_x.htm
- Dr. David Bradley - Adjunct Faculty - Department of Electrical and Computer Engineering
-- http://www.ece.ncsu.edu/people/dbradley
- Dr. David J. Bradley Retires from IBM - Newsroom - Department of Electrical and Computer Engineering
-- http://www.ece.ncsu.edu/news/387
** BIOS, MBR, アセンブラ関連
- Programming MS-DOS with Power
-- http://www.fysnet.net/index.htm
--- MS-DOSのプログラミングに関する、ひたすら「濃い」コンテンツ。
--- ROM BIOSのメモリレイアウトなど、機械語 - BIOS - DOSの境界線をひた走る。
- ATA-ATAPI.COM -- HIW: How It Works Documents
-- http://www.ata-atapi.com/hiw.html
--- MBRやCHSの変換など、ATA-ATAPI技術の内容が濃い。
- MBR and Windows Boot Sectors
-- http://home.att.net/~rayknights/pc_boot/pc_boot.htm
--- Win95/98/2000のMBRをdisassmbleして解説している。とにかく、濃い。
- Dump a BIOS using debug.com [MESS]
-- http://mess.redump.net/dumping:dump_bios_using_debug/
--- "DEBUG"コマンドでBIOSのダンプイメージを取得する手法
- BIM PC 5150 のROM BIOSダンプイメージファイル
-- http://www.vintagecomputer.net/ibm/5150/BIOS_dumps/
- IBM Personal Computer Assembly Language Tutorial | Simon Steed's Blog About Stuff!
-- http://blog.xploiter.com/programming-related-content/ibm-personal-computer-assembly-language-tutorial/
--- IBM PC 5150当時の MACRO アセンブラのチュートリアル。
- The Segment:Offset Addressing Scheme
-- http://thestarman.pcministry.com/asm/debug/Segments.html
--- SEGMENT:OFFSET形式のアドレス指定の解説
- PCのbootstrap(MBR)や呼び出し規約の、GCCを使った講義ノート
-- http://pdos.csail.mit.edu/6.828/2003/labs/lab1.html
-- http://zoo.cs.yale.edu/classes/cs422/2010/lec/l3-hw
-- http://flint.cs.yale.edu/cs422/precepts/bochs.html
- I/O Ports and Controllers on IBM Compatibles and PS/2
-- http://www.os2site.com/sw/info/memory/ports.txt
--- I/Oポートアドレス一覧
- CMOS Memory Map
-- http://bochs.sourceforge.net/techspec/CMOS-reference.txt
--- CMOSの内部メモリレイアウト
- その他BIOS, bootstrap関連Wikipedia
-- http://en.wikipedia.org/wiki/Initial_program_load
-- http://en.wikipedia.org/wiki/Booting
-- http://en.wikipedia.org/wiki/Nonvolatile_BIOS_memory
-- http://en.wikipedia.org/wiki/Input/Output_Base_Address
** Intel x86 の初期CPUのWikipedia
- 4bit
-- http://en.wikipedia.org/wiki/Intel_4004
-- http://en.wikipedia.org/wiki/Intel_4040
- 8bit
-- http://en.wikipedia.org/wiki/Intel_8008
-- http://en.wikipedia.org/wiki/Intel_8080
-- http://en.wikipedia.org/wiki/Intel_8085
- 8/16bit
-- http://en.wikipedia.org/wiki/Intel_8086
-- http://en.wikipedia.org/wiki/Intel_8088
-- http://en.wikipedia.org/wiki/Intel_80186
-- http://en.wikipedia.org/wiki/Intel_80188
-- http://en.wikipedia.org/wiki/Intel_80286
- 32bit
-- http://en.wikipedia.org/wiki/Intel_80386
-- http://en.wikipedia.org/wiki/Intel_80486
* Special Thanks
下手くそな英語で突然質問してきたmsakamoto-sfに対して、親切に回答してくれた
Tim Peterson
David Bradley
両氏に対してSpecial Thanksです。
#navi_footer|Assembler|