The below assembly code loads the secondary bootloader (boot2.bin) at address 0x8000 from the FAT12 filesystem and jumps to it.
;_______________________________________________
; File name : boot.asm |
; Authour : M.Alexander |
; Mail : programmer_83@hotmail.com |
; Date : 09-05-2004 |
; Description : Primary Bootloader |
;_______________________________________________|
[BITS 16]
; Memory Map
;_______________________________________________
; |
; _____________________ |
; | | <-- 0x0000 |
; | | |
; | STACK | |
; | | |
; |_____________________| <-- 0x05FF |
; | | <-- 0x0600 |
; | FAT COPY | |
; |_____________________| <-- 0x1800 |
; |////////UNUSED///////| |
; |_____________________| <-- 0x2000 |
; | | |
; | ROOT DIRECTORY | |
; |_____________________| <-- 0x3C00 |
; |/////////////////////| |
; |////////UNUSED///////| |
; |/////////////////////| |
; |_____________________| <-- 0x7C00 |
; | | |
; | PRIMARY BOOTLOADER | |
; |_____________________| <-- 0x7E00 |
; |/////////////////////| |
; |///////UNUSED////////| |
; |/////////////////////| |
; |_____________________| <-- 0x8000 |
; | | |
; |SECONDARY BOOTLOADER | |
; |_____________________| <-- ?? |
; |
;_______________________________________________/
%define FAT_CPY 0x0600
%define DIR_CPY 0x2000
%define SEC_BL 0x8000
[org 0x7C00]
jmp short start
nop
OEM_IDENT db 'FAT12FLP'
BYTES_PER_SCT dw 0200h
SCTS_PER_CLST db 01h
RESERVED_SCTS dw 01h
NO_OF_FATS db 02h
ROOT_ENT dw 0E0h
NO_OF_SCTS dw 0B40h
MEDIA_DCPTR db 0F0h
SCTS_PER_FAT dw 09h
SCTS_PER_TRK dw 012h
HDS_PER_CYL dw 02h
HDN_SCTS dd 0h
start:
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax ; Initialize segment registers
mov ax, 0x5ff
mov sp, ax ; Setup Stack space
sti ; Enable Interrupts
;____________________________________________________________.
; Loads FAT copy into main memory at address 0x0600 |
;____________________________________________________________|
xor ax, ax
add word ax, [RESERVED_SCTS]
call trans_add
mov ah, 0x02
mov al, [SCTS_PER_FAT]
mov dl, 0x00
mov bx, FAT_CPY
int 13h
;____________________________________________________________.
; Loads Directory Entries into main memory at |
; address 0x0600 |
;____________________________________________________________|
mov al, [SCTS_PER_FAT]
mul byte [NO_OF_FATS]
add word ax, [RESERVED_SCTS]
call trans_add
mov ah, 0x02
mov al, 0x0E
mov dl, 0x00
mov bx, DIR_CPY
int 13h
;____________________________________________________________.
; Calculates the start of data area and saves it in the |
; variable DATA_AREA for future use. |
;____________________________________________________________|
mov ax, [SCTS_PER_FAT]
mov bx, [NO_OF_FATS]
mul bx
add ax, [RESERVED_SCTS]
mov bx, ax
mov ax, [ROOT_ENT]
shl ax, 0x05
shr ax, 0x09
add ax, bx
mov [DATA_AREA], ax
;____________________________________________________________.
; Searching for the secondary file begins here. |
;____________________________________________________________|
mov bx, [ROOT_ENT] ; Move the number of root entries into bx (counter)
mov dx, DIR_CPY ; Move the address of Directory entry into dx
srch:
cld ; Clear the direction flag
mov di, sec_file ; Move the address of the secondary file into di
mov si, dx ; Load the source address
mov cx, 0x0b ; Number of characters to compare (8+3)
repe cmpsb ; Repeat till the characters not equal. Maximum 0x0b times
jnz short next ; If not found, try next entry
;____________________________________________________________.
; Loads the secondary file at the address SEC_BL declared |
; earlier. |
;____________________________________________________________|
mov bx, SEC_BL
mov si, dx
add si, 0x1A ; Byte 26 & 27 of the file entry
mov word ax,[si] ; (Entry cluster value)
push ax ; Push the starting cluster to the stack
load:
xor eax, eax
xor ecx, ecx
xor dx, dx ; Clear out necessary registers
pop ax ; Pop the last computed value for the sector
push ax ; Again save it for future use
cmp ax, 0x0FFF ; If End of sector for the file, jump to exit
jz exit
mov cl, [DATA_AREA]
dec ax
dec ax ; Subtract 2 from the next sector value
add ax, cx ; Converts the data sector into LBA
call trans_add ; Converts LBA into CHS
mov ax, 0x0201
mov dl, 0x00
int 13h ; Read the next data cluster into the main memory
add bx, 0x200 ; Increment the file pointer to load the sector
xor ax, ax
pop ax ; Pop the sector value from the stack
mov cx, 0x03
mul cx ; Multiply the value with 3
rcr ax, 1 ; Divide it by 2 (3/2 = 1.5)
jc carry ; If carry set, decimal number
mov si, ax
add si, 0x0600
mov word ax, [si]
and ax, 0x0fff
push ax
jmp load
carry:
mov si, ax
add si, 0x0600
mov word ax, [si]
shr ax, 4
push ax
jmp load
jmp $ ; File found. write code here
next:
dec bx ; Decrement number of entries to check still
jz exit ; If zero, file not found
add dx, 0x20 ; Point to next entry
jmp short srch ; Compare next entry
exit:
jmp 0000:8000h ; Jump to secondary boot loader code
trans_add:
;____________________________________________________________.
; FUNCTION : Translates LBA sector number into CHS value |
; INPUT : AX = LBA Sector |
; OUTPUT : CH = Cylinder, DH = Head, CL = Sector |
; |
; FORMULA USED: |
; sector = (LBA % SPT) + 1 |
; Head = (LBA / SPT) % HPC |
; Cylinder = (LBA / SPT) / HPC |
;____________________________________________________________|
; |
div word [SCTS_PER_TRK] ; LBA / SPT |
inc dl ; dl = (LBA % SPT) + 1 |
mov cl, dl ; cl = sector |
xor dx, dx ; Clear out dx reg. |
div word [HDS_PER_CYL] ; (LBA / SPT) / HPC |
mov ch, al ; ch = cylinder |
mov dh, dl ; dh = head |
ret ; Return |
;____________________________________________________________|
print:
;____________________________________________________________.
; FUNCTION : Prints a string |
; INPUT : SI = String Address |
; OUTPUT : Prints the string |
;____________________________________________________________|
; |
push ax ; |
push bx ; |
pchar: ; |
cld ; |
lodsb ; |
or al, al ; |
jz pexit ; |
mov ah, 0x0e ; |
mov bx, 0x0007 ; |
int 10h ; |
jmp pchar ; |
pexit: ; |
pop bx ; |
pop ax ; |
ret ; |
;____________________________________________________________|
sec_file db "BOOT2 BIN"
file_nt_fnd db CR,LF,'File not found',0
file_fnd db CR,LF,'File found',0
DATA_AREA db 0x00
FILE_BUF dw 0x8000
CR equ 0x0d
LF equ 0x0a
times(510-($-$$)) db 0
dw 0xaa55