[bits 16]
%define RD_BUFF 0x0500
%define FAT_BUFF 0x0500
%define FILE_BUFF 0x0700
org 0x7c00
entry:
jmp short begin
nop
LABEL DB 'ANSFLPY0'
BYTES_PER_SECT DW 0200h
SECTS_PER_CLUST DB 01h
SECTS_IN_BOOT DW 01h
FAT_COPIES DB 02h
DIR_ENTRIES DW 0e0h
SECTORS DW 0b40h
DISK_TYPE DB 0F0h
SECTS_PER_FAT DW 09h
SECTS_PER_TRK DW 012h
HEADS DW 02h
HIDDEN_SECTS DD 0h
HUGE_SECTS DD 0h
DRIVE_NO DB 0h
RESERVED DB 0h
BOOT_SIGN DB 29h
VOL_ID DD 00007c00h
VOL_LABEL DB 'ANSELM MEYN'
FS_TYPE DB 'FAT12 '
begin:
cli ; disable interrupts
xor ax,ax ; initialize all the necessary
mov ds,ax ; registers
mov ss,ax
mov es,ax
mov sp,7c00h
mov [DRIVE_NO],dl ; DRIVE_NO overwritten here
sti ; enable interrupts
;________________________________________________________________________________
; Calculate the start of Root Directory and save in AX
;-------------------------------------------------------------------------------+
mov al,[FAT_COPIES] ;
mov bx,[SECTS_PER_FAT] ;
mul bx ;
add ax,[SECTS_IN_BOOT] ;
add ax,word [HIDDEN_SECTS] ;
;________________________________________________________________________________
;________________________________________________________________________________
; Calculate the start of Data Area and save it in DX +
;-------------------------------------------------------------------------------+
mov dx,[DIR_ENTRIES] ;
shl dx,5 ;
add dx,[BYTES_PER_SECT]
dec dx ;
shr dx,9 ;
push dx ;
;
add dx,ax ;
mov [SECTS_B4_DA],dx
;________________________________________________________________________________
;________________________________________________________________________________
; Now to read the first sector of Root Directory at RD_BUFF +
; Reads the entries at ES:BX +
;-------------------------------------------------------------------------------+
call trans_address ; AX translated to physical address +
mov bx,RD_BUFF ; move starting location for read to BX +
pop ax ; sectors to read in +
call disk_read ; read the disk sector +
;________________________________________________________________________________
;________________________________________________________________________________
; Now the search for internal files begins +
; Called after reading the directory entries +
; this searches first 16 entries for the given filename +
;-------------------------------------------------------------------------------+
mov dx,[DIR_ENTRIES]
mov bx,RD_BUFF
filsrch:
cld
mov di,file ; FILE NAME INIT.BIN
mov si,bx
mov cx,0bh
repe cmpsb
je found
add bx,20h
dec dx
jnz filsrch
mov si,finderr
call print
jmp error
;________________________________________________________________________________
found:
;________________________________________________________________________________
; If the file is found then +
; address of file directory entry is in DX +
;-------------------------------------------------------------------------------+
mov dx,[bx+1ah]
mov ax,[SECTS_IN_BOOT]
push dx
call trans_address
mov bx,FAT_BUFF
mov ax,3
call disk_read
pop dx
mov ax,dx
;________________________________________________________________________________
;________________________________________________________________________________
; Search and read of the File clusters +
; Here AX=?, BX=FAT_BUFF,CX=?,DX=? +
;--------------------------------------------------------------------------------
mov bx,FILE_BUFF
sub bx,200h
jmp chk
fat_cont:
mov ax,dx
add ax,ax
add ax,dx
clc
rcr ax,1
pushf
push bx
mov bx,FAT_BUFF
add bx,ax
mov ax,[bx]
pop bx
popf
jc odd
; even part
and ax,0x0fff
jmp chk
odd:
shr ax,4
chk:
mov dx,ax
push dx
cmp ax,0x0ff8
jge quit
dec ax
dec ax
add ax,[SECTS_B4_DA]
call trans_address
add bx,200h
call disk_read
pop dx
jmp fat_cont
;_______________________________________________________________________________
quit:
mov si,endmsg
call print
mov dl,[DRIVE_NO]
mov bx,0x500
mov ax,FILE_BUFF
mov cs,ax
mov ds,ax
cli
jmp 0000:FILE_BUFF
;
; I GET THE MESSAGE "Loading Secondary"
; AFTER THIS THE MESSAGE "Error Press any key to reboot" COMES
; I CAN'T UNDERSTAND WHAT HAPPENS
; PLEASE HELP ME OUT
;
; THE ROUTINES USED BEGIN FROM HERE DOWNWARDS
jmp $
error:
;_______________________________________________________________________________
; This is called on any error it displays an error message and \
; asks the user to press any key for reboot *
; Input:- the specific String in SI reg *
; clobbers SI Reboots at the end *
;-------------------------------------------------------------------------------*
mov si,errmsg ; dispaly the *
call print ; error message *
mov ah,0 ; *
int 16h ; wait for key press *
int 19h ; reboot *
;_______________________________________________________________________________/
print:
;_______________________________________________________________________________
; Print Function for NULL terminated Strings \
; the NULL terminated string must be present in SI *
; Registers Affected:- AX,BX(popped back)
;-------------------------------------------------------------------------------*
push ax ; save AX and BX *
push bx ; registers *
ploop:
cld
lodsb ; AL = [DS:SI] *
or al, al ; Set zero flag if al=0 *
jz pstop ; jump to stop if zero flag is set *
mov ah, 0eh ; video function 0Eh (print char) *
mov bx, 0007h ; color *
int 10h ; interrupt 10h for screen display *
jmp short ploop ; keep printing *
pstop:
pop bx ; retrieve BX and AX *
pop ax ; registers *
retn ; end print *
;_______________________________________________________________________________/
trans_address:
;_______________________________________________________________________________
; Translates Logical sector in AX to Physical sector,head,cylinder \
; Input:- the LBA address in the AX reg *
; Output:- cl=sector,ch=cylinder,dh=head *
; Formula:- *
; HPC = Number of heads/cylinder *
; SPT = sectors/track *
; Sector = (LBA mod SPT) + 1 *
; Head = (LBA / SPT) mod HPC *
; Cylinder = (LBA / SPT) / HPC *
; Registers Affected:- AX,CX,DX *
;-------------------------------------------------------------------------------*
xor dx,dx ; clear out DX reg *
div word [SECTS_PER_TRK] ; divide AX by SPT *
inc dl ; increment dl to get sector address *
mov cl,dl ; get sector value *
xor dx,dx ; clear DX reg *
div word [HEADS] ; *
mov ch,al ; get cylinder value *
mov dh,dl ; get head value *
retn ; all values obtained now *
;_______________________________________________________________________________/
disk_read:
;_______________________________________________________________________________
; Disk Read Routine using int13h, the registers must be set up already \
; Input:- ES:BX=Dest address *
; Output:- CF=success/failure,AL=sectors read,AH=stat code *
; Re-tries 3 times for read *
; Registers Affected:-AH=02,all *
;-------------------------------------------------------------------------------*
push si ; save SI *
mov si,4 ; 3 tries *
rtry:
mov dl,[DRIVE_NO] ; DL=drive no *
mov ah,0h ; reset the disk *
int 13h ; *
mov ah,02h ; disk read function *
dec si ; one try up *
jz rstop ; is it zero *
int 13h ; no then read it *
jc rtry ; if read errror then retry *
rstop:
mov si,readerr ; critical error *
jc error ; must stop *
pop si ; else restore SI and return *
retn ; end disk_read *
;_______________________________________________________________________________/
file db 'INIT BIN'
readerr db CR,LF,'DISK Error',0
finderr db CR,LF,'File Missing',0
errmsg db CR,LF,'Error Press any Key to Continue...',0
endmsg db CR,LF,'Loading Secondary',0
SECTS_B4_DA dw 0
size equ $-entry
%if size+2>512
%error "code greater than 512 bytes"
%endif
times (510-size) db 0
dw 0aa55h
CR equ 0dh
LF equ 0ah