Lesson 1: 引導扇區
這一課我們將學習引導扇區的知識,這樣我們就能寫一個我們自己的引導程序了。
當計算機從軟盤引導時, BIOS (Basic Input/Output System)將磁盤的第一個扇區讀入以0000:7C00開始的內存。這個扇區稱爲DOS Boot Record (DBR)。然後,BIOS跳轉到0x7C00開始執行那裏的指令。正是那些指令(即“boot loader”)將把OS加載到內存中,並且開始啓動處理。
我們要做的第一件事情是仔細看一看Boot Record。DOS的工具DEBUG非常有用,我們常常用它來查看內存或着是磁盤的內容。同樣,我們將用DEBUG來看看軟盤的Boot Record。
在DOS (或者Windows)的命令行方式下輸入debug。於是提示符變成了連接線。如果你輸入命令‘d’加上一個回車,它將顯示一塊內存的內容。如果你輸入一個問號,將顯示在DEBUG中可用的命令。(請仔細使用DEBUG。它可以用來覆蓋磁盤上的內容,這有可能導致數據的丟失。)
請在軟驅中放入一張新格式化的軟盤。要載入你軟盤上的Boot Record,請輸入如下命令。
-l 0 0 0 1
(第一個字符是字母‘l’,而不是數字‘1’。)這個命令將磁盤扇區載入到內存中。‘l’後面的四個數字,依次表示你希望將數據載入到其中的那塊內存的首地址,驅動器編號 (軟驅的話,是0),以及扇區的編號和扇區的數目。輸入這個命令將把磁盤的第一個扇區載入到內存以0開始的地方。
現在我們已經把Boot Record載入到內存裏了,接下來我們想看看它的內容,輸入下面的指令。
-d 0
你會看到8行數據,它們表示軟盤引導記錄最初的128(16進制的0x80)個字節。結果(我的軟盤)如下:
0AF6:0000 EB 3C 90 4D 53 44 4F 53-35 2E 30 00 02 01 01 00 .<.MSDOS5.0.....
0AF6:0010 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00 ...@............
0AF6:0020 00 00 00 00 00 00 29 F6-63 30 88 4E 4F 20 4E 41 ......).c0.NO NA
0AF6:0030 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 33 C9 ME FAT12 3.
0AF6:0040 8E D1 BC F0 7B 8E D9 B8-00 20 8E C0 FC BD 00 7C ....{.... .....|
0AF6:0050 38 4E 24 7D 24 8B C1 99-E8 3C 01 72 1C 83 EB 3A 8N$}$....<.r...:
0AF6:0060 66 A1 1C 7C 26 66 3B 07-26 8A 57 FC 75 06 80 CA f..|&f;.&.W.u...
0AF6:0070 02 88 56 02 80 C3 10 73-EB 33 C9 8A 46 10 98 F7 ..V....s.3..F...
粗看一眼,彷彿什麼都沒有。我能夠看出來這是張MS-DOS 5.0的軟盤,有一個沒有名字的FAT12文件系統。最左端的數字顯示的是內存地址。中間的16進制碼顯示的是這段內存的全部字節,最右邊顯示的是16進制碼所對應的ASCII字符(如果某字節不能被轉換爲一個可見的字符,就用一個句點來表示)。這部分引導記錄中的一些字節是boot loader的指令,另一些存儲了諸如每個扇區多少字節,每個磁道多少扇區這樣的信息。
現在到看一看boot loader代碼的時候了。輸入下面的指令。
-u 0
這將執行“unassemble”操作。這將同樣顯示剛纔的那些字節,(從地址0開始),只不過這一次DEBUG顯示的是這些字節所表示的INTEL的指令。我的軟盤結果如下:
0AF6:0000 EB3C JMP 003E
0AF6:0002 90 NOP
0AF6:0003 4D DEC BP
0AF6:0004 53 PUSH BX
0AF6:0005 44 INC SP
0AF6:0006 4F DEC DI
0AF6:0007 53 PUSH BX
0AF6:0008 352E30 XOR AX,302E
0AF6:000B 0002 ADD [BP+SI],AL
0AF6:000D 0101 ADD [BX+DI],AX
0AF6:000F 0002 ADD [BP+SI],AL
0AF6:0011 E000 LOOPNZ 0013
0AF6:0013 40 INC AX
0AF6:0014 0BF0 OR SI,AX
0AF6:0016 0900 OR [BX+SI],AX
0AF6:0018 1200 ADC AL,[BX+SI]
0AF6:001A 0200 ADD AL,[BX+SI]
0AF6:001C 0000 ADD [BX+SI],AL
0AF6:001E 0000 ADD [BX+SI],AL
第一個指令要求跳轉到0x3E。這之後的指令是關於剛纔我提到的軟盤參數的,並沒有對應的指令,但是DEBUG還是盡心盡責的爲我們翻譯了。
第一條指令跳過了這些數據,執行從地址0x3E開始的啓動程序的代碼。讓我們看看那裏的指令,輸入:
-u 3E
在這裏,你能看到負責加載DOS或者是WINDOWS的代碼的開始部分。代碼(就MS-DOS來說)將在磁盤上尋找IO.SYS和MSDOS.SYS。這些文件包含了操作系統的代碼。boot loader的代碼將把這些文件載入到內存中,並且開始執行它們。如果在磁盤上沒有找到這些文件,boot loader將顯示如下這條臭名昭著的錯誤信息:
Invalid system disk
Disk I/O error
Replace the disk, and then press any key
如果你看一下DOS引導記錄的最後部分,你將會發現這條信息。你可以看看我磁盤上的:
-d 180
0AFC:0180 18 01 27 0D 0A 49 6E 76-61 6C 69 64 20 73 79 73 ..'..Invalid sys
0AFC:0190 74 65 6D 20 64 69 73 6B-FF 0D 0A 44 69 73 6B 20 tem disk...Disk
0AFC:01A0 49 2F 4F 20 65 72 72 6F-72 FF 0D 0A 52 65 70 6C I/O error...Repl
0AFC:01B0 61 63 65 20 74 68 65 20-64 69 73 6B 2C 20 61 6E ace the disk, an
0AFC:01C0 64 20 74 68 65 6E 20 70-72 65 73 73 20 61 6E 79 d then press any
0AFC:01D0 20 6B 65 79 0D 0A 00 00-49 4F 20 20 20 20 20 20 key....IO
0AFC:01E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 7F 01 SYSMSDOS SYS..
0AFC:01F0 00 41 BB 00 07 60 66 6A-00 E9 3B FF 00 00 55 AA .A...`fj..;...U.
這是引導記錄的末尾。引導記錄在磁盤上恰好佔一個扇區(512字節)。如果從內存地址0開始加載它,那麼最後那個地址應該是0x1FF。如果你看一看引導記錄的這最後兩個字節(0x1FE和0x1FF),你會發現它們是0x55和0xAA。引導記錄的最後兩個字節一定得是這個值,否則BIOS將不會加載這個扇區並且執行它。
概括起來說,DOS的引導記錄以一個跳轉指令開始,這個跳轉指令講跳過緊隨其後的數據。這60字節的數據從0x02開始,至0x3D,之後是引導代碼,從0x3E到0xFD,再之後是兩個字節0x55和0xAA。下一課我們將利用我們的這些知識,來寫一個我們自己的引導程序。