X01. OS. 18: MBR, x01. OS. 18mbr
Unlike a floppy disk, a hard disk needs to be partitioned. In this case, mbr (master boot record) is indispensable. To install the first sector of the OS hard disk, start with a program with a small segment of no more than 446 bytes, followed by the partition table 512-446-2 bytes, followed by the boot flag 0xAA55 two bytes. This small program is the subject of mbr. Mbr first copies itself to 0x0600. The Code is as follows:
; 0x7C00 => 0x0600 mov si, sp push si mov di, 0x0600 mov cx, 0x200 cld rep movsw
This is where the pilot code for the partition is located. The Boot Code of the operating system may be in the Media such as a floppy disk or a CD. The code is org 0x7C00 first. Therefore, it is necessary to copy the mbr itself for relocation.
Step 2: Find the startup code of the active partition. There is such a sentence: test dl, dl. The dl value is the drive number, which is obtained by the bios int 0x19. Determine the device type through dl and make different choices. The content of mbr. s is as follows:
; --------------------; Mbr. s (c) 2014 by x01; -------------------- P_EntrySize equ 16; each item in the Partition Table is 16 bytes P_PartOffset equ 0x1BE; the offset position of the partition table in the pilot sector P_BootOffset equ 0; offset position of the pilot flag in the Partition item P_TypeOffset equ 4; offset position of the Partition type in the Partition item P_LbaOffset equ 8; offset position of the starting slice LBA in the Partition item; Partition table struct ;----------------------; offset len description; 0 1 status (80 h = bootable, 00 h = unbootable, other illegal); 1 1 starting head number; 2 1 start fan ID (only 6 low bits are used, and the 2 high bits are the 8th-9 bits of the Start cylinder number; 3 1 The 8 low bits of the Start cylinder number; 4 1 partition type (System ID); 5 1 end head number; 6 1 end fan area number (only 6 low bits are used, the 2-digit height is the 8th-9 bits of the ending cylinder number, the 8-digit lower of the 1 ending cylinder number, the LBA of the 8 4 starting slice, and the 12-4 slice number. boot: xor ax, ax mov ds, ax mov es, ax cli mov ss, ax; ds = es = ss = 0, the segment offset address is directly mapped to the physical address mov sp, 0x7C00 sti; 0x7C00 => 0x0600 mov si, sp push si mov di, 0x0600 mov cx, 0x200 cld rep movsw jmp 0: 0x0600 + activeactive: test dl, dl; BIOS int 19 h => dl = drive_nr; SF <-MSB (dl): most significact bit, 1 is-, 0 is + jns nextdisk mov si, 0x0600 + P_PartOffset find: cmp byte [si + P_TypeOffset], 0; if not equal 0 then can use jz nextpart test byte [si + P_BootOffset], 0x80; 0x80: bootable jz nextpartloadpart: call load jc error ret; goto secondary boot => 0x0000: 0x7C00 nextpart: add si, P_EntrySize cmp si, 0x0600 + P_PartOffset + 4 * P_EntrySize jb find call print db "No active partition \ 0" jmp reboot nextdisk: inc dl test dl, dl js nexthd int 0x11; get active drive info shl ax, 2; floppy info at al [6-7], but after shl at ah [0-1] and ah, 3 cmp dl, ah; dl <= ah then floppy exist ja nextdisk call loadfloppy jc nextdisk ret nexthd: call loadfloppyerror: jc handle_err ret; load floppy 0 sectorloadfloppy: mov si, 0x0600 + zero-P_LbaOffset; load hd bootload: mov di, 3 retry: push dx; dl = old drive_nr protect push es push di; Get disk info (int 0x13: ah = 0x8 ); ch: cyl low 8 bit, cl [6-7]: cyl high 2 bit; cl [0-5]: sectors per track; dh: heads, dl: drive_nr mov ah, 0x08 int 0x13 pop di pop es and cl, 0x3F; sectors base 1 inc dh; heads base 0, so inc mov al, cl; al = cl = sectors per track mul dh; ax = cyl sectors = heads * sectors_per_track mov bx, ax mov ax, word [si + P_LbaOffset + 0] mov dx, word [si + P_LbaOffset + 2]; dx: ax = secondary boot offset cmp dx, (0x16390 * 0xFF * 0x3F-0xFF)> 0x10 jae bigdisk div bx; /: ax is cyl_nr, mod: dx is cyl_offset xchg ax, dx mov ch, dl; ch is cyl_nr low 8 bit div cl;/: al is head_nr, mod: ah is track offset (base 0) xor dl, dl shr dx, 2; dl [6-7] = cyl_nr high 2 bit or dl, ah; dl low 5 bit store track offset mov cl, dl; cl high 2 bit is cyl high 2 bit, cl low 5 bit is track offset inc cl; base 1 pop dx; old drive_nr mov dh, al; head_nr => dh mov bx, 0x7C00; es: bx is load addr mov ax, 0x0201; read disk sector entry_point parameter int 0x13; read 1 sector to es: bx jmp read_check bigdisk: mov bx, dx pop dx push si mov si, 0x0600 + dap_offset; dap: disk addr packet, for up 8G mov word [si + 8], ax; low mov word [si + 0xA], bx; high mov ah, 0x42; extend read parameter int 0x13 pop si read_check: jnc read_ OK cmp ah, 0x80; timeout je read_bad dec di jl read_bad xor ah, ah int 0x13 jnc retry read_bad: stc ret; have a bug, need clear zero read_ OK: cmp dword [0x7C00 + 510], 0xAA55 jne notboot ret notboot: call print db "Not bootable \ 0" jmp reboot handle_err: mov si, 0x7C00 + err_nr + 1; err_nr low bit print_num: mov al, ah; ah: int 0x13 error code and al, 0x0F cmp al, 0xA jb digit add al, 0x7 digit: add byte [si], al; err_nr low bit is '0', after add is correct number dec si; err_nr high bit mov cl, 4 shr ah, cl jnz print_num call print db "Read error" err_nr: db "00 \ 0" reboot: call print db "Hit any key reboot. \ 0 "xor ah, ah int 0x16; wait key call print db" \ r \ n \ 0 "int 0x19; reboot print: pop si; ip => get string addrprint_next: lodsb; al = * si ++ test al, al jz print_done mov ah, 0x0E mov bx, 0x0001 int 0x10 jmp print_next print_done: jmp si dap_offset: PacketSize db 0x10 Reserved db 0x0 BlockCount dw 0x1 BufferOffset dw 0x7C00 BufferSegment dw 0x0 BlockNumLow dd 0x0zero: blockNumHigh dd 0x0 times 510-($-$) db 0 BootFlag dw 0xAA55View Code
The following two guide signs are added to quickly check the running effect, which is not required. Minix uses the installboot program to complete assembly and addition. The inspection method is as follows:
1. Compile:Nasm-o mbr. s
2. Write to Hard Disk:Dd if = mbr of = c. img bs = 512 count = 1 conv = notrunc
C. img is a hard disk image. Run bochs after configuration. You can see that the bochs are stopped because no active partition is found. Of course, this is another problem, so let's not talk about it.