1 ! masterboot 2.0 - Master boot block code Author: Kees J. Bot
2 !
3 ! This code may be placed in the first sector (the boot sector) of a floppy,
4 ! hard disk or hard disk primary partition. There it will perform the
5 ! following actions at boot time:
6 !
7 ! - If the booted device is a hard disk and one of the partitions is active
8 ! then the active partition is booted.
9 !
10 ! - Otherwise the next floppy or hard disk device is booted, trying them one
11 ! by one.
12 !
13 ! To make things a little clearer, the boot path might be:
14 ! /dev/fd0 - Floppy disk containing data, tries fd1 then d0
15 ! [/dev/fd1] - Drive empty
16 ! /dev/c0d0 - Master boot block, selects active partition 2
17 ! /dev/c0d0p2 - Submaster, selects active subpartition 0
18 ! /dev/c0d0p2s0 - Minix bootblock, reads Boot Monitor /boot
19 ! Minix - Started by /boot from a kernel image in /minix
20
21 ! boot sequence:
22 ! 1. If a hard drive partition:
23 ! masterboot(this code) -> bootstrap -> bootmonitor -> boot_MinixOperatingSystem
24 ! 2. If a hard drive subpartition is booted:
25 ! masterboot(this code) -> masterboot(again) -> bootstrap -> bootmonitor -> boot_MinixOperatingSystem
26
27
28 LOADOFF = 0x7C00 ! 本程序自动被Bios加载到这里.
29 BUFFER = 0x0600 ! First free memory
30 PART_TABLE = 446 ! 分区表的入口位置,也即是代码段的大小. 1BE
31 PENTRYSIZE = 16 ! 分区表每项16字节.(共4项, 共64字节)
32 MAGIC = 510 ! Location of the AA55 magic number ! (1FE, 1FF) (510, 511)
33
34 ! .h:
35 bootind = 0
36 sysind = 4
37 lowsec = 8
38
39 .text
40
41 ! Find active (sub)partition, load its first sector, run it.
42 master:
43 xor ax, ax
44 mov ds, ax
45 mov es, ax
46 cli ! 给ss,sp传值前要关闭中断响应
47 mov ss, ax ! ds = es = ss = Vector segment
48 mov sp, #LOADOFF
49 sti ! 重新打开中断响应
50
51 ! 复制本程序到BUFFER处去执行
52 mov si, sp ! si = start of this code
53 push si ! Also where we'll return to eventually
54 mov di, #BUFFER ! Buffer area
55 mov cx, #512/2 ! One sector
56 cld ! 方向位清零, 使得复制到的是0:LOADOFF+512而不是0:LOADOFF-512
57 ! rep: repeats execution of string instructions while cx != 0.
58 rep movs ! 从DS:SI复制数据到ES:DI.(一次复制1 word而不是1 bite??) ! ?????
59 jmpf BUFFER+migrate, 0 ! far jmp. 0:BUFFER+migrate
60 !
61 !上面的代码块把mbr的512字节移动到0x0000:0x0600处,然后跳转到migrate的代码处执行.
62 !接下来首先测试设备是否可引导,即dl的最高位是否为1, 为1则设备可引导; 否
63 !则跳转到nextdisk处.
64 !如果可引导则检测的分区,测试其类型同时是否是活动分区,总共测试4次,如果
65 !还没有找到则显示没有活动分区,然后直接跳到reboot的地方执行,显示一些信息后系统重启.
66 !
67 migrate:
68 ! Find the active partition
69 findactive:
70 ! ## testb sets the sign flag if the value in dl is negative. Remember that 0x00
71 ! and 0x01 correspond to the first and second floppy drives and 0x80, 0x81,
72 ! 0x82, and 0x83 correspond to hard drives 1-4.
73 testb dl, dl ! dl是负的吗?若是,则符号标记位被置位. dl的值从何来?????
74 jns nextdisk ! 如果为正数的话,是软盘,则跳转到nextdisk;
75 mov si, #BUFFER+PART_TABLE ! 否则为硬盘.
76 find: cmpb sysind(si), #0 ! Partition type, nonzero when in use
77 jz nextpart
78 testb bootind(si), #0x80 ! Active partition flag in bit 7
79 jz nextpart ! It's not active
80 loadpart:
81 call load ! Load partition bootstrap ! 为什么不是 call load0 ?????
82 jc error1 ! Not supposed to fail
83 bootstrap:
84 ret ! Jump to the master bootstrap
85 nextpart:
86 add si, #PENTRYSIZE
87 cmp si, #BUFFER+PART_TABLE+4*PENTRYSIZE ! 最多有4个主分区
88 jb find
89 ! No active partition, tell 'em
90 !利用call命令会把下一条要执行的指令的地址压人堆栈的特点吧.ascii字符的初始地址给压人了堆栈
91 !这样当进入print函数后就可以通过弹栈把字符的首地址取出,最后字符显示完后直接用jmp
92 !(si)指令跳转到下一个地方继续执行
93 call print
94 .ascii "No active partition\0"
95 jmp reboot
96
97 ! There are no active partitions on this drive, try the next drive.
98 nextdisk:
99 incb dl ! Increment dl for the next drive
100 testb dl, dl
101 js nexthd ! Hard disk if negative
102 ! ! INT 11 - BIOS - GET EQUIPMENT LIST
103 ! ! Return: (E)AX = BIOS equipment list word (see #00226,#03215 at INT 4B"Tandy")
104 int 0x11 ! Get equipment configuration
105 shl ax, #1 ! Highest floppy drive # in bits 6-7
106 shl ax, #1 ! Now in bits 0-1 of ah
107 andb ah, #0x03 ! Extract bits
108 cmpb dl, ah ! Must be dl <= ah for drive to exist
109 ja nextdisk ! Otherwise try disk 0 eventually
110 call load0 ! Read the next floppy bootstrap
111 jc nextdisk ! It failed, next disk please
112 ret ! Jump to the next master bootstrap
113 nexthd: call load0 ! Read the hard disk bootstrap
114 error1: jc error ! No disk?
115 ret
116
117
118 ! Load sector 0 from the current device. It's either a floppy bootstrap or
119 ! a hard disk master bootstrap.
120 load0:
121 mov si, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero ! 这是什么意思?????
122 !jmp load
123
124 ! Load sector lowsec(si) from the current device. The obvious head, sector,
125 ! and cylinder numbers are ignored in favour of the more trustworthy absolute
126 ! start of partition.
127 load:
128 mov di, #3 ! Three retries for floppy spinup !
129 retry: push dx ! Save drive code
130 push es
131 push di ! Next call destroys es and di
132 movb ah, #0x08 ! Code for drive parameters
133 ! ! INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)
134 ! ! AH = 08h
135 ! ! ES:DI = 0000h:0000h to guard against BIOS bugs
136 ! ! Return: CF set on error
137 ! ! CF clear if successful
138 ! ! CL = maximum sector number (bits 5-0),high two bits of maximum cylinder number (bits 7-6)
139 ! ! DH = maximum head number
140 ! 获取该设备的一些参数
141 int 0x13! 获取该设备的一些参数
142 pop di
143 pop es
144
145 ! 处理这些参数
146 andb cl, #0x3F ! cl = max sector number (1-origin) ! cl&63. <63>
147 incb dh ! dh = 1 + max head number (0-origin). <255>
148 movb al, cl ! al = cl = sectors per track
149 mulb dh ! dh = heads, ax = heads * sectors. ! ax=al*dh.
150 ! 每柱面扇区数 = 每道扇区数 * 每柱面磁头数 = 63 * 255 = 16065
151 mov bx, ax ! bx = sectors per cylinder = heads * sectors. <16065>
152 mov ax, lowsec+0(si)
153 mov dx, lowsec+2(si)! dx:ax = sector within drive ! 硬盘一个扇区=512KB
154 cmp dx, #[1024*255*63-255]>>16 ! bootable在8GB之后? ! 只须比较lowsec高16位. 8GB约等于1024*255*63个扇区. 是这个意思吗?????
155 jae bigdisk ! 在8GB之后, 跳转
156
157 ! 在8GB之前, 把逻辑扇区号转换为 C/H/S 形式, 以便调用bios把它加载到内存.
158 ! L = C*16065 + H*63 + S - 1 ==>
159 ! C = L / 16065
160 ! H = (L % 16065) / 63
161 ! S = (L % 16065) % 63 + 1
162 div bx ! ax = cylinder, dx = sector within cylinder. ! dx:ax/bx=ax...dx
163 xchg ax, dx ! ax = sector within cylinder, dx = cylinder
164 movb ch, dl ! ch = low 8 bits of cylinder<柱面号-低8位>
165 divb cl ! al<磁头号> = head, ah = sector (0-origin) ! ax/cl=al...ah
166 xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
167 shr dx, #1
168 shr dx, #1 ! dl[6..7] = high cylinder
169 orb dl, ah ! dl[0..5] = sector (0-origin)
170 movb cl, dl ! cl[0..5] = sector<扇区号-低6位>, cl[6..7] = high cyl<柱面号-高2位>
171 incb cl ! cl[0..5] = sector (1-origin)
172 pop dx ! Restore drive code in dl<设置号>
173 movb dh, al ! dh = al = head<磁头号>
174 mov bx, #LOADOFF! es:bx = where sector is loaded. 把该扇区加载到这里!!!!!
175 mov ax, #0x0201 ! Code for read, just one sector ah=2 al=1<一共读取1个扇区>
176 ! ! INT 13 - DISK - READ SECTOR(S) INTO MEMORY
177 ! ! AH = 02h
178 ! ! AL = number of sectors to read (must be nonzero)
179 ! ! CH = low eight bits of cylinder number
180 ! ! CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7, hard disk only)
181 ! ! DH = head number
182 ! ! DL = drive number (bit 7 set for hard disk)
183 ! ! ES:BX -> data buffer
184 ! ! Return: CF set on error
185 ! ! if AH = 11h (corrected ECC error), AL = burst length
186 ! ! CF clear if successful
187 ! ! AH = status (see #00234)
188 ! ! AL = number of sectors transferred (only valid if CF set for some BIOSes)
189 int 0x13 ! Call the BIOS for a read
190 jmp rdeval ! Evaluate read result
191
192 bigdisk:
193 mov bx, dx ! bx:ax = dx:ax = sector to read
194 pop dx ! Restore drive code in dl
195 push si ! Save si
196 mov si, #BUFFER+ext_rw ! si = extended read/write parameter packet
197 mov 8(si), ax ! Starting block number = bx:ax
198 mov 10(si), bx
199 movb ah, #0x42 ! Extended read
200 ! ! INT 13 - IBM/MS INT 13 Extensions - EXTENDED READ
201 ! ! AH = 42h
202 ! ! DL = drive number
203 ! ! DS:SI -> disk address packet (see #00272)
204 ! ! Return: CF clear if successful
205 ! ! CF set on error
206 int 0x13
207 pop si ! Restore si to point to partition entry
208 !jmp rdeval
209 rdeval:
210 jnc rdok ! Read succeeded
211 cmpb ah, #0x80 ! Disk timed out? (Floppy drive empty)
212 je rdbad
213 dec di
214 jl rdbad ! Retry count expired
215 xorb ah, ah
216 ! INT 13 - DISK - RESET DISK SYSTEM
217 ! AH = 00h
218 ! DL = drive (if bit 7 is set both hard disks and floppy disks reset)
219 ! Return: AH = status (see #00234)
220 ! CF clear if successful (returned AH=00h)
221 ! CF set on error
222 int 0x13 ! Reset ! CF set on error
223 jnc retry ! Try again
224 rdbad:
225 stc ! Set carry flag
226 ret
227 rdok: cmp LOADOFF+MAGIC, #0xAA55
228 jne nosig ! Error if signature wrong
229 ret ! Return with carry still clear ! 返回到LOADOFF执行刚成功加载的代码
230 nosig: call print
231 .ascii "Not bootable\0"
232 jmp reboot
233
234 ! A read error occurred, complain and hang
235 error:
236 mov si, #LOADOFF+errno+1
237 prnum: movb al, ah ! Error number in ah
238 andb al, #0x0F ! Low 4 bits
239 cmpb al, #10 ! A-F?
240 jb digit ! 0-9!
241 addb al, #7 ! 'A' - ':'
242 digit: addb (si), al ! Modify '0' in string
243 dec si
244 movb cl, #4 ! Next 4 bits
245 shrb ah, cl
246 jnz prnum ! Again if digit > 0
247 call print
248 .ascii "Read error "
249 errno: .ascii "00\0"
250 !jmp reboot
251
252 reboot:
253 call print
254 .ascii ". Hit any key to reboot.\0"
255 xorb ah, ah ! Wait for keypress ! ah=0
256 int 0x16 ! 读键盘字符
257 call print
258 .ascii "\r\n\0"
259 int 0x19 ! 重新引导装入程序, 即重起
260
261 ! Print a message.
262 print: pop si ! si = address of String following 'call print'
263 prnext: lodsb ! al = *si++ is char to be printed
264 testb al, al ! Null marks end
265 jz prdone
266 movb ah, #0x0E ! Print character in teletype mode
267 mov bx, #0x0001 ! Page 0, foreground color
268 int 0x10 ! ah=0E, int 0x10 显示字符并自动处理光标; al=要显示的字符, bh=页号
269 jmp prnext
270 prdone: jmp (si) ! Continue after the string
271
272 .data
273
274 ! Extended read/write commands require a parameter packet.
275 ext_rw:
276 .data1 0x10 ! Length of extended r/w packet
277 .data1 0 ! Reserved
278 .data2 1 ! Blocks to transfer (just one)
279 .data2 LOADOFF ! Buffer address offset
280 .data2 0 ! Buffer address segment
281 .data4 0 ! Starting block number low 32 bits (tbfi)
282 zero: .data4 0 ! Starting block number high 32 bits
283 ! # zero: .data4 0 ! Starting block number high 32 bits
284
285
286 ! 1. 硬盘第一扇区结构:
287 ! 0000 |------------------------------------------------|
288 ! | |
289 ! | |
290 ! | Master Boot Record |
291 ! | |
292 ! | |
293 ! | 主引导记录(446字节) |
294 ! | |
295 ! | |
296 ! | |
297 ! 01BD | |
298 ! 01BE 446------------------------------------------------|
299 ! | |
300 ! 01CD | 分区信息 1(16字节) |
301 ! 01CE |------------------------------------------------|
302 ! | |
303 ! 01DD | 分区信息 2(16字节) |
304 ! 01DE |------------------------------------------------|
305 ! | |
306 ! 01ED | 分区信息 3(16字节) |
307 ! 01EE |------------------------------------------------|
308 ! | |
309 ! 01FD | 分区信息 4(16字节) |
310 ! |------------------------------------------------|
311 ! | 01FE | 01FF |
312 ! | 55 | AA |
313 ! |------------------------------------------------|
314
315
316
317 ! 2. 分区表:
318 ! ========================================================================
319 ! | 字节 含义 |
320 ! 0 ========================================================================
321 ! | 0 Activeflag.活动标志.若为0x80H,则表示该分区为活动分区.若|
322 ! | 为0x00H,则表示该分区为非活动分区. |
323 ! ------------------------------------------------------------------------
324 ! | 该分区的起始可用的空间的磁头号,扇区号,柱面号. 磁头号:第|
325 ! |1,2,3 1字节, 扇区号:第2字节低6位, 柱面号:第2字节高2位 + 第3字|
326 ! | 节. |
327 ! 4 ------------------------------------------------------------------------
328 ! | 分区文件系统标志: |
329 ! | 分区未用: 0x00H. |
330 ! | 扩展分区: 0x05H, 0x0FH. |
331 ! | 4 FAT16分区: 0x06H. |
332 ! | FAT32分区: 0x0BH, 0x1BH, 0x0CH, 0x1CH. |
333 ! | NTFS分区: 0x07H. |
334 ! 5 ------------------------------------------------------------------------
335 ! |5,6,7 该分区的结束磁头号,扇区号,柱面号, 含义同上. |
336 ! 8 ------------------------------------------------------------------------
337 ! |8,9,10,11 逻辑起始扇区号. 即该分区起点之前已用了的扇区数. |
338 ! 12 ------------------------------------------------------------------------
339 ! |12,13,14,15 该分区所占用的扇区数. |
340 ! ========================================================================
341
问题讨论见:
阅读(1548) | 评论(0) | 转发(1) |