#navi_header|Assembler| ''重要:本記事で調査不足で曖昧だった点を解決した完全版をUPしました。ぜひこちらの方を参照して下さい。'' - [[614]] ---- x86アーキテクチャで、ブートローダ周りを調べ始めると必ず、 0x7C00 というマジックナンバーに遭遇する。"セグメント:オフセット"形式で 07C0:0000 という表記も見かける。 これはフロッピーディスク又はHDDのMBRが展開されるアドレスで、ブートローダ(MBRにインストールされる)はこのアドレスから始まることを想定して作成される。 一体誰がこのマジックナンバーを決定したのか?その起源と、確かな証拠を探してみた。 * 結論 x86アーキテクチャのPCの原型であるIBM PC 5150 (1981年発表) の BIOS は、ディスケット(フロッピーディスク)の先頭セクタ1つ分(今のMBR)を 0x7C00 にロードし、ブートローダとして実行するよう作成されていた。これが起源と思われる。 以降のIBM PC(およびその互換機)もその仕様を維持し、結果としてPC/AT互換機およびその上で動作するBIOSに引き継がれていった。 * 解説 "IBM Personal Computer XT Technical Reference manual" ((参考にしたファイル名には"ibm5160"とあった。その一つ手前、5150のTechnical Reference manualは入手出来なかった。)) の Appendix-A に BIOS の全ソースコード(アセンブラ)が記載されている。 大雑把な流れ: + システムチェック ++ ディスクチェック → INT 19h + INT 19h : ディスケットの先頭1セクタ分を 0x7C00 にロード ++ うまくロード出来れば、0x7C00 にJMPする。 ++ ロード出来なければ、 INT 18h で ROM BASIC を立ち上げる。 ** システムチェック ~ ディスクチェック → INT 19h 1142行目から "DISKETTE ATTACHMENT TEST" が始まり、この中で"INT 19h"が実行される。 1151行目の F9: ラベルからチェックが始まり、途中からPRINTERやRS232のチェックも始まる。 うまくいけば、1306 - 1307行の #cat|4,1306|> F21: ; LOAD_BOOT_STRAP: INT 19H ; GO TO THE BOOT LOADER ||< で "INT 19h" が実行される。 ** INT 19h ディスケットからトラック0, セクタ0番を 0x7C00 上に読み込む。 まず 0x7C00 というマジックナンバーは、63, 64行目で定義されている。 #cat|4,63|> ORG 7C00H BOOT_LOCN LABEL FAR ||< INT 19hの割り込みハンドラは1417行目から始まり、その中で上のBOOT_LOCNを使ってブートローダを読み込んでいる。(ソースコード上は"BOOTSTRAP"という表記もあるが、とりあえずこの記事の日本語中では「ブートローダ」に統一しておく) 以下に該当コードを載せるが、"H1:"ラベルで始まるブロックで最初のセクタを0x7C00にロードし、成功すれば"H4:"ラベルでBOOT_LOCN、つまり0x7C00にJMPしている。 #cat|4,1417|> ASSUME CS:CODE,DS:AB50 ORG 0E6F2H BOOT_STRAP PROC NEAR STI ; ENABLE INTERRUPTS SUB AX,AX ; ESTABLISH ADDRESSING MOV DS,AX ;--- RESET THE DISK PARAMETER TABLE VECTOR MOV WORD PTR DISK_POINTER, OFFSET DISK_BASE MOV WORD PTR DISK_POINTER + 2, CS ; --- 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 ; READ IN THE SINGLE SECTOR SUB DX, DX ; TO THE BOOT LOCATION MOV ES,DX MOV BX,OFFSET BOOT_LOCN ; DRIVE 0, HEAD 0 MOV CX, 1 ; SECTOR 1, TRACK 0 INT 13H ; DISKETTE_IO H2: POP CX ; RECOVER RETRY COUNT JNC H4 ; CF SET BY UNSUCCESSFUL LOOP H1 ; DO IT FOR RETRY TIMES ;----- UNABLE TO IPL FROM THE DISKETTE H3: INT 18H ; GOTO RESIDENT BASIC ;---- IPL HAS SUCCESSFUL H4: JMP BOOT_LOCN BOOT_STRAP ENDP ||< 他にBIOSのソースを確認出来たのは同マニュアルの改訂版、およびPC-JrのTechnical Reference manualの二つ。 細かい違いはあるが、INT 19h で 0x7C00 以降にブートローダをロード成功後JMPする、という流れは全て同じだった。 * 参考URL - Welcome to the Retrocomputing Archive -- http://www.retroarchive.org/dos/docs/ - PC Technical Reference Manual -- by Jalkanen Art & Science -- http://www.tec.sci.fi/tecref/ #navi_footer|Assembler|