I Like It !

Wednesday, June 16, 2010

A disassembly of the Master Boot Record

RELOCATION: The MBR's loader code begins by setting up a stack
at 0:7c00, then the MBR (except for the relocation code at
0:7c00 - 0:7c1a) is relocated to 0:061b, and operation resumes
at the new location.
7C00 xor ax,ax ;zero ax
7C02 mov ss,ax ;ss = 0
7C04 mov sp,07c00 ;stack @ 0:7c00
7C07 sti ;enable interrupts
7C08 push ax ;zero on stack
7C09 pop es ;es = 0
7C0A push ax ;zero on stack
7C0B pop ds ;ds = 0
7C0C cld ;clear direction
7C0D mov si,07c1b ;source index = 7c1b
7C10 mov di,061b ;dest index = 61b
7C13 push ax ;segment for retf = 0
7C14 push di ;offset for retf = 61b
7C15 mov cx,01e5 ;1e5 bytes to move
7C18 rep movsb ;relocate the MBR
7C1A retf ;jump to relocated MBR

SCAN PARTITION TABLE: the source index register (si) is set to
point to the "active flag" byte of the first partition record
(at offset 7BEh) in the MBR's partition table. The loader code
loops, checking the active flag of each record.

061B mov si,07be ;point si to first partition active flag
061E mov cl,4 ;4 partition records to examine
0620 cmp b[si],ch ;compare active flag to zero
0622 jl 062d ;jump if bit 7 of active flag set
If jl tests true here, we have an active partition.
0624 jne 061b ;hang computer in loop (bad flag)
Otherwise, the value of the must be zero, else the partition record
is corrupt. In that case the code goes into a loop and hangs the
system.
0626 add si,010 ;point to next record
0629 loop 0620 ;test next record
062B int 018 ;call ROM BASIC if no active partition
If no active partition is found in the partition table, a call is
made to ROM BASIC. This will normally result in "No ROM BASIC" being
displayed on the screen with the sytem hung.
062D mov dx,w[si] ;drive & head numbers to dx
We have found an active partition. The drive (80h) and head (usually 1)
are loaded in the dx register. Now check to be sure that the remaining
active flags are set to zero.
062F mov bp,si ;bp points to active partition entry
0631 add si,010 ;point to next entry
0634 dec cx ;decrement loop counter
0635 je 064d ;jump if finished
Finished testing active flags. Now go and read the active partition
boot sector to memory.
0637 cmp b[si],ch ;active byte = 0?
0639 je 0631 ;if so, check next entry
If we get here, a spurious (non-zero) active flag was found. The
MBR code now displays "Invalid Partition Table" and hangs.

Print error message:
063B mov si,0710 ;si points to error msg string
063E dec si ;adjust
063F lodsb ;get next character in al
0640 cmp al,0 ;end of string?
0642 je 063e ;if so, hang
0644 mov bx,7 ;color white on black
0647 mov ah,0e ;print character function
0649 int 010 ;print the char
064B jmp 063f ;print next char
READ BOOT SECTOR:
Now we are ready to read the active partition's boot sector to
memory. First, we need to determine whether to use CHS addressing
or the BIOS interrupt 13 LBA extensions. The LBA extensions are
used for partition types 0ch (FAT32 LBA), 0eh (FAT16 LBA).
064D mov w[bp+025],ax ;ax is = 0 here
0650 xchg ax,si ;si = 0
0651 mov al,b[bp+4] ;al = partition type
0654 mov ah,6 ;ah = 6
0656 cmp al,0e ;partition type 0e?
0658 je 066b ;if so, jump
065A mov ah,0b ;ah = 0b
065C cmp al,0c ;partition type 0c?
065E je 0665 ;if so, jump
0660 cmp al,ah ;partition type 0b?
0662 jne 068f ;jump if not
0664 inc ax ;resets zero flag
0665 mov b[bp+025],6 ;marker
0669 jne 068f ;jump
if the partition type is 0c or 0e, then we need to check if the int 13
BIOS extensions are supported.
066B mov bx,055aa ;per int 13 ah = 41
066E push ax ;save ax on stack
066F mov ah,041 ;this function is an installation
; check for the int 13 BIOS extension
0671 int 013 ;BIOS disk i/o
0673 pop ax ;restore ax
0674 jb 068c ;jump if error occurred
0676 cmp bx,0aa55 ;extensions supported?
067A jne 068c ;jump if not
067C test cl,1 ;disk access functions supported?
067F je 068c ;jump if not
0681 mov ah,al ;partition type to ah
0683 mov b[bp+024],dl ;drive no.
0686 mov w[06a1],01eeb ;patch code with jump to 06c1
068C mov b[bp+4],ah ;overwrite partition type
We will enter here, skipping the BIOS extensions tests, if the
partition type is other than 0c or 0e.
068F mov di,0a ;di=0a
0692 mov ax,0201 ;int 13 read 1 sector
0695 mov bx,sp ;stack pointer to bx
0697 xor cx,cx ;zero cx
0699 cmp di,5 ;compare
069C jg 06a1 ;jump if di > 5
069E mov cx,w[bp+025] ;will be 0 or 6
If the BIOS Interrupt 13 extensions are in use, this instruction
will have been overwritten with jmp 06c1. If CHS addressing
is in use, on the other hand, we will proceed as follows.
06A1 add cx,w[bp+2] ;start cyl/sector of partition
06A4 int 013 ;read sector to 0:7c00
06A6 jb 06d1 ;jump if error occurred
06A8 mov si,0746 ;pointer to error message
Message is "Missing operating system"
06AB cmp w[07dfe],0aa55 ;system signature present?
06B1 je 070d ;jump if so
06B3 sub di,5 ;else decrement di
06B6 jg 0692 ; and try again
06B8 test si ;si = 0?
06BA jne 063f ;go print error msg if not
06BC mov si,0727 ;pointer to error msg
Message will be "Error loading operating system"
06BF jmp 064b ;go print message
06C1 cbw ;ah = 0
06C2 xchg ax,cx ;cx = 1, ax = 0
06C3 push dx ;save dx
06C4 cwd ;dx = 0
06C5 add ax,w[bp+8] ;move "relative sectors"
06C8 adc dx,w[bp+0a] ; to ax/dx
06CB call 06e0 ;read the sector
06CE pop dx ;restore dx
06CF jmp 06a6 ;test for error & system sig

Error handler for int 13 reads:
06D1 dec di ;decrement retry counter
06D2 je 06b8 ;if zero go print error msg
06D4 xor ax,ax ;zero ax
06D6 int 013 ;reset disk drive
06D8 jmp 0692 ;retry read
06DA db... (6 bytes) ;Windows inserts a drive identifier here
06E0 push si ;save si
06E1 xor si,si ;zero si
06E3 push si ;LBA of
06E4 push si ; first block
06E5 push dx ; to read -
06E6 push ax ; qword
06E7 push es ;disk i/o
06E8 push bx ; buffer
06E9 push cx ;blocks to transfer
06EA mov si,010 ;si = 10
06ED push si ;save on stack
06EE mov si,sp ;si = sp
06F0 push ax ;save registers
06F1 push dx ; .
06F2 mov ax,04200 ;extd int 13 read
06F5 mov dl,b[bp+024] ;drive no.
06F8 int 013 ;read
06FA pop dx ;restore registers
06FB pop ax ; .
06FC lea sp,[si+010] ;adjust stack pointer
06FF jb 070b ;jump if error occurred
0701 inc ax ;increment ax
0702 jne 0705 ;jump if not zero
0704 inc dx ;increment dx
0705 add bh,2 ;add 200h to buffer offset
0708 loop 0701 ;
070A clc ;clear carry
070B pop si ;restore si
070C ret ;return
070D jmp 0783h
070F db 'Invalid partition table',0
0727 db 'Error loading operating system',0
0746 db 'Missing operating system',0
075F db... ;unused area
0783 mov di,sp ;stack pointer to di
0785 push ds ;seg for retf
0786 push di ;offst for retf
0787 mov si,bp ;si points to active partition record
0789 retf ;jump to DBR boot code
0790 db... ;unused area
07BE ;partition table goes here
07FE dw 0AA55 ;system signature