;0-10    File name (8 bytes) with extension (3 bytes)
;11      Attribute - a bitvector. Bit 0: read only. Bit 1: hidden.
;        Bit 2: system file. Bit 3: volume label. Bit 4: subdirectory.
;        Bit 5: archive. Bits 6-7: unused.
;12-21   Reserved (see below)
;22-23   Time (5/6/5 bits, for hour/minutes/doubleseconds)
;24-25   Date (7/4/5 bits, for year-since-1980/month/day)
;26-27   Starting cluster (0 for an empty file)
;28-31   Filesize in bytes



.586

text segment word 'code'
assume cs:text, ds:text

org 7C00h


jmp short ldr

boot    proc

db ?                    ;byte not needed for short jump

OEMname         db     'OEM NAME'
SecSize         dw     512
ClustSize       db     1
reserved        dw     1
FATCnt          db     2
RootEntries     dw     224  ;max entries in root directory
unused1         dw     ?
mdb             db     0F0h
FATSize         dw     9
SecsPerTrk      dw     18
heads           dw     2
hidden          dd     10   ;sectors reserved for boot loader (5120 bytes available)
unused2         dd     0
drive           db     0
unused3         db     0
signature       db     29h
SerNum          dd     03C9A71BFh
VolumeLabel     db     'NO NAME   '
                db     'FAT12   '

ldr:
cli
xor ax,ax
mov cs,ax
mov ds,ax                   ;initialise segment registers
mov ss,ax
mov es,ax
mov sp, 0fffeh              ;set up stack
sti

mov ax, FATSize             ;load sectors per track
mov bh, FATCnt
mul bh                      ;calculate number of FAT sectors
add ax, reserved            ;add on boot sector(s)
inc ax                      ;first sector of root directory
push ax
pop cx                      ;cl = first sector to read, ch = track 0
push cx                     ;save sector address of root directory
xor dh,dh                   ;dh = head 0
mov dl, drive               ;load drive number
mov bx, 8000H               ;es:bx -> buffer on DMA boundary
mov ax, 201H                ;read first sector of root directory into memory
int 13h
jc BadTrk0                  ;jump to error handler if read failed

mov si, 8000H               ;ds:si -> first directory entry
lea di, osldr               ;es:di -> loader's filename
mov cx, 11
repe cmpsb                  ;is loader present?
je ldr_found                ;if so, skip error handler

lea si, errmsg2             ;ds:si -> non system disk message
call disp                   ;display message
lea si, errmsg10
call disp
jmp short reboot            ;reboot computer

ldr_found:
mov ax, RootEntries         
shr ax, 4                   ;ax = number of root directory sectors
pop cx                      ;pop seg address of root directory & track number
add cl,al                   ;cl = first sector after root directory
cmp cl, byte ptr SecsPerTrk ;isw cl > number of sectors on track?
jna la1                     ;no - so no adjustment necessary

sub cl, byte ptr SecsPerTrk ;sector number for track 0, head 1
xor dh, 1                   ;toggle head number

la1:
call read64k                ;read loader into memory
jnc ldr_read_ok             ;skip error handler if read was successful

BadTrk0:
lea si, errmsg1             ;ds:si -> error message
call disp                   ;display message
lea si, errmsg10
call disp

reboot:
xor ah,ah                   ;wait for keystroke
int 16h
mov bx,472H                 ;0:472 = address of boot status word
mov word ptr [ bx ], 1234H  ;skip POST test
int 19h                     ;reboot

ldr_read_ok:
jmp ldr_addr                ;jump to osldr

osldr     db 'osldr   sys'

errmsg1   db 'Bad track 0 - Disk unusable.', 0dh, 0ah, 0
errmsg2   db 'Not a system disk', 0dh, 0ah, 0
errmsg10  db 'Strike any key', 0

ldr_addr  dd 8000H

boot endp


disp    proc

nextChar:
xor bh,bh               ;page number
lodsb                   ;load next character
or al,al                ;end of string?
jz EndDisp              ;if so jump out of loop

mov ah, 0Eh             ;display character
int 10h
jmp short nextChar      ;next character

EndDisp:
ret

disp    endp


read64k    proc    near
;dl = drive
;dh = head
;cl = sector
;ch = track
;bx -> buffer on DMA boundary

mov si,cx                ;save sector and track numbers
mov cx, 16               ;16 * 4096 byte pages = 64kb

nextPage:
xchg cx,si               ;cx = sector and track numbers, si = loop count
call readPage            ;read 4096 byte page into memory
jc read64kEnd

xchg si,cx               ;si = returned sector and track numbers, cx = loop count
loop nextPage            ;read next page

clc

read64kEnd:
ret

read64k    endp


readPage    proc    near
;dl = drive
;dh = head
;cl = sector
;ch = track
;bx -> buffer on DMA boundary

push bx
push cx
push dx
mov ax, 8              ;8 sectors = 4096 byte DMA page
push cx                ;save sector and track number
add cl,al              ;calculate end sector number
cmp cl, byte ptr SecsPerTrk
pop cx                 ;past end of track?
jna SameTrk            ;no - so skip special code
                
mov ax, SecsPerTrk     ;load al with number of sectors per track
sub al,cl
inc ax                 ;ax = number of sectors to read
push ax                
push bx
push cx
push dx
mov ah, 2              ;read sectors into buffer
int 13h
pop dx
pop cx
pop bx
pop ax                 ;ax = number of sectors read
jnc la3                ;skip error handler if carry clear

la4:
add sp, 8              ;pop pushed registers
stc                    ;flag error
ret                    ;return to caller

la3:
push ax                
shl ax, 9              ;ax = number of bytes read
add bx,ax              ;update buffer pointer ready for next read
pop ax
sub al, 8
neg al                 ;ax = number of remaining sectors to read
mov cl, 1              ;starting with sector 1
xor dh, 1              ;toggle head number
jnz SameTrk            ;jump if not back with head 0

inc ch                 ;otherwise increment track number

SameTrk:
mov ah, 2              ;complete read
int 13h
jc la4                 ;return with carry set upon error

pop dx
pop cx
pop bx
add bx, 4096           ;increment bx by number of bytes in page
add cl, 8              ;increment starting sector by eight
cmp cl, byte ptr SecsPerTrk ;pased end of track?
jna la2                ;no - so skip handler

sub cl, byte ptr SecsPerTrk
xor dh, 1              ;toggle head number
jnz la2                ;if head != 0 do not increment track number

inc ch                 ;new track number

la2:
clc                    ;no error
ret

readPage    endp


dw 0, 55AAH

text ends

end

Chances are you wiould need a utility to strip off the first 7C00H bytes after compiling and linking it. (Not yet tested or debugged by the way.)

This article has been dead for over six months. Start a new discussion instead.