Home
Introduction
Display
Strings
Graphics
Hardware
Interrupts
File Systems
Components
ASM Editors
Real&PMode
Assemblers
Libraries
Downloads
Links
Contact Us
 















        page    ,132
        title   BOOTSTRAP == Assembly of MS-DOS boot sector code
;******************************************************************************
;
;       name:       bootstrp
;
;       function:   this is the bootstrap loader for ms-dos.  it is loaded
;                   by bios into memory beginning at 0000:7c00 and control
;                   is passed to its first byte.
;
;       entry:      from rom bios boot code.  the hardware is assumed to have
;                   executed its initialization procedures, and low memory
;                   has been set up to reflect the hardware features of
;                   interest.
;
;                   dl = disk id from which this record was read (00h or 80h)
;                   other register contents are undefined.
;
;
;       processing: this routine:
;
;                       a: resets the disk system
;                       b: builds a new *diskette* parm table in memory,
;                          patches the data to reflect the number of sectors
;                          per track on the *boot* device, and changes the
;                          int 1e vector to point to this changed table.
;                       c: reads in the first sector of the root directory
;                       d: verifies that io.sys and dos.sys are the first
;                          two entries in the root directory
;                       e: reads the image of io.sys into memory beginning
;                          at 700:0.
;
;                   if test (d) fails, or if an i/o error is encountered,
;                   the boot is rejected and the user is told to replace
;                   the disk.
;
;       exit:       control is passed to io.sys at 700:0.
;
;                       ax:bx = 32-bit sector number of first data sector
;                       ch    = media descriptor byte
;                       dl    = disk id (should be 00h or 80h)
;                       0:500 = first sector of root directory
;                       int 1e vector -> a parm table with proper values
;                                        for sectors/track and head settle
;                                        for boot disk...invalid if boot
;                                        is from a fixed disk.
;
;       error exit: none.  control cannot pass until a successful load of
;                   io.sys; the only other exit possible is a three-finger
;                   salute.
;
;       version:    this code reflects boot blocks written by ms-dos 5.0
;
;       formatting and comments: joe morris 2/93
;
;******************************************************************************

.radix 16
;-------------;
; definitions ;
;-------------;

INT1E   equ     078h                            ; int 1e vector address
DIRBUFF equ     0500h                           ; address of buffer for
                                                ; root directory block

boot            segment byte
                assume cs:boot,ds:boot,ss:boot
                org     100h                    ; dummy
;--------------
;   note: the layout of the boot data block is mandatory regardless of
;         the type of device on which it appears.  the locations are
;         fixed and are assumed by numerous other programs.
;--------------
;         on the other hand, the data beginning at "new_sect_ct" did not
;         exist prior to dos 4.x and cannot be relied on if the boot block
;         was written by a prior release of dos.  the determinant seems to
;         be whether "old_sector_ct" is zero (new format) or nonzero (old
;         format).
;-------------


main            proc near
                jmp     short start             ; jump over data block
                nop

;------------------;
;  boot data block ;
;------------------;

oem_name        db      'MSDOS5.0'
bytesect        dw      512d                    ; bytes/sector
sectclust       db      04                      ; sectors/cluster
reserve_sect    dw      01                      ; reserved sectors at
                                                ;   beginning of disk
fatcopies       db      02                      ; number of fat copies
rootentries     dw      512d                    ; number of root dir entries
old_sector_ct   dw      0                       ; total # of sectors on disk
                                                ; (zero in new format block)
mediadesc       db      0f8h                    ; media description byte
sectorsfat      dw      64d                     ; sectors per fat copy
secthead        dw      32d                     ; sectors per head
headcyl         dw      64d                     ; heads per cylinder
hiddensect      dd      32d                     ; special hidden sectors...
hiddensect_lo   equ     word ptr hiddensect     ; ... low bits
hiddensect_hi   equ     word ptr hiddensect+2   ; ... high bits
new_sect_ct     dd      65504d                  ; total number of sectors on
                                                ;   disk (new format)...
new_sect_ct_lo  equ     word ptr new_sect_ct    ; ... low bits
new_sect_ct_hi  equ     word ptr new_sect_ct+2  ; ... high bits
disk_id         db      80                      ; physical disk id for int 13
                                                ;   (will be 00h or 80h)
head            db      00                      ; used as scratch work area
                                                ;   (documented as reserved)
ext_sig         db      29                      ; extended boot signature
volser          db      1ch,9eh,0adh,16h        ; volume serial
vol_label       db      11 dup (' ')            ; volume label (if diskette)
fat_type        db      'FAT16   '              ; type of file allocation table

;---------------------;
; end boot data block ;
;---------------------;

;-----------------------------------------------------

; >>>> starts execution here <<<<

;note: 'start' is both:
;       the first byte of executable code after the boot
;       data block (at mandatory address 7c3e), and
;       the location of the temporary diskette parm table.

start:
                cli                             ; make sure we're disabled
                xor     ax,ax                   ; clear a work register
                mov     ss,ax                   ; fake out stack logic...
                mov     sp,offset boot          ; stack starts just ahead of us
                push    ss
                pop     es                      ; now ss and es are both zero
;;;;
datasect_lo     equ     $+01h          ;<07c49> ; sector # of 1st data - low
;;;;
                mov     bx,INT1E                ; int 1e vector address
;;;;
cylinder        equ     $+02h          ;<07c4d> ; scratch
datasect_hi    equ     $                       ; sector # of 1st data - high
;;;;
                lds     si,dword ptr ss:[bx]    ; -> disk parm table into ds:si
                push    ds                      ; segment...
;;;;
sector         equ     $                       ; scratch memory
;;;;
                push    si                      ; ...and offset
;;;;
rootsect_lo    equ     $                       ; sector # of root start - low
;;;;
                push    ss                      ; still zero
                push    bx                      ; -> int 1e vector
;;;;
rootsect_hi    equ     $                       ; sector # of root start - high
;;;;
                mov     di,offset start         ; point to code no longer needed
                mov     cx,000bh                ; (can be overlaid by 11 bytes)
                cld                             ; make sure we're facing forward
                repz    movsb                   ; copy table over our entry code
                                                ;    move ds:[si] -> es:[di]

                push    es
                pop     ds                      ; zero ds again
                mov     byte ptr [di-02],0fh    ; force in head settle time
                mov     cx,word ptr secthead    ; force in sectors/track for
                mov     byte ptr [di-07],cl     ; *this* disk type
                mov     word ptr [bx+02],ax     ; ...and point int 1e to our
                mov     word ptr [bx],offset start ; modified table
                sti                             ; ok, we'll take interrupts now
                int     13h                     ; ax is still zero: reset disk
                jc      fail                    ; reset failed

                xor     ax,ax
                cmp     word ptr old_sector_ct,ax ; test for old format header:
                                                ; is normal sector count zero?
                je      newcount                ; yes: new count must be valid
                mov     cx,word ptr old_sector_ct ; else copy valid count
                mov     word ptr new_sect_ct_lo,cx ;

newcount:       mov     al,byte ptr fatcopies   ; number of fat copies
                mul     word ptr sectorsfat     ; times sectors per fat give
                                                ; sectors in fat
                add     ax,word ptr hiddensect_lo ; add in 32-bit hidden count
                adc     dx,word ptr hiddensect_hi
                add     ax,word ptr reserve_sect ; and reserved count
                adc     dx,00
                mov     word ptr rootsect_lo,ax ; 32-bit root sector number
                mov     word ptr rootsect_hi,dx

                mov     word ptr datasect_lo,ax ; now calculate the sector #
                mov     word ptr datasect_hi,dx ; of the first data block
                mov     ax,0020h                ; size of a directory entry
                mul     word ptr rootentries    ; times number of root entries
                                                ; gives bytes in root
                mov     bx,word ptr bytesect    ; pick up bytes/sector
                add     ax,bx                   ; figure out how many sectors
                                                ; are in root.  make sure any
                                                ; fractions are rounded up.
                dec     ax
                div     bx                      ; sectors in root
                add     word ptr datasect_lo,ax
                adc     word ptr datasect_hi,00

                mov     bx,DIRBUFF              ; -> scratch area for directory
                mov     dx,word ptr rootsect_hi ; build c/h/r of root
                mov     ax,word ptr rootsect_lo
                call    calc_chr
                jc      fail                    ; bang

                mov     al,01                   ; read one record
                call    read_disk
                jb      fail                    ; bang.

                mov     di,bx                   ; -> first directory slot
                mov     cx,11d                  ; compare one filename+ext
                mov     si,offset io_fileid     ; -> "io      sys"
                repz    cmpsb                   ; it gotta be there...
                jne     fail                    ; ... or we're dead
                                                ; si now -> "msdos   sys"
                                                ; (note this sneaky way of
                                                ;   saving a few bytes)
                lea     di,word ptr [bx+20h]    ; -> second directory slot
                mov     cx,11d                  ; 11 bytes again
                repz    cmpsb                   ; this too is required
                je      got_boot_files          ; we love it.

fail:           mov     si,offset no_system_msg ; else write nasty message
                call    write_msg
                xor     ax,ax                   ; wait for a keyboard event
                int     16h
                pop     si                      ; recover post registers
                pop     ds
                pop     word ptr [si]
                pop     word ptr [si+02]
                int     19h                     ; and go repeat the boot process

pop_fail:       pop     ax                      ; come here for failure...
                pop     ax                      ; ...within a subroutine
                pop     ax
                jmp     short fail


got_boot_files: mov     ax,word ptr [bx+1ah]    ; cluster number of io.sys start
                dec     ax                      ; correct for fat arithmetic
                dec     ax
                mov     bl,byte ptr sectclust   ; sectors/cluster
                xor     bh,bh
                mul     bx
                add     ax,word ptr datasect_lo ; sector # of first data - low
                adc     dx,word ptr datasect_hi ; sector # of first data - high
                mov     bx,0700h                ; load data into 70:xxx
                mov     cx,0003h                ; only 3 sectors required

read_io_pgm:    push    ax
                push    dx
                push    cx
                call    calc_chr                ; calc cylinder/head/record #
                jb      pop_fail                ; code fall down go boom
                mov     al,01
                call    read_disk
                pop     cx
                pop     dx
                pop     ax
                jb      fail

                add     ax,0001h
                adc     dx,00
                add     bx,word ptr bytesect    ; bytes/sector
                loop    read_io_pgm             ; read three sectors in loop


;       bootstrap is complete.  load the information required
;       by io.sys for completion of second-level bootstrap
;       and pass control to it.

                mov     ch,byte ptr mediadesc   ; media description byte
                mov     dl,byte ptr disk_id     ; physical disk id for int 13
                mov     bx,word ptr datasect_lo ; sector of first data - low
                mov     ax,word ptr datasect_hi ; sector of first data - high

                db      0eah,000h,000h,070h,000h ; jmp  far 0070:0000

main            endp

;<07d52> wr teletype mode,al=char
write_msg       proc near
                lodsb                           ; get next character to output
                or      al,al                   ; is there one?
                je      sub_exit                ; exit if not (zero ends string)
                mov     ah,0eh                  ; output one character to crt...
                mov     bx,0007h                ; ...via int 10/ah=3
                int     10h                     ;
                jmp     short write_msg         ; back for another...

write_msg       endp

;<07d60> calculate cylinder/head/record # from relative sector #
;        input is flat sector # in dx:ax

calc_chr        proc near
                cmp     dx,word ptr secthead    ; make sure no divide check...
                jnb     chr_fail
                div     word ptr secthead       ; develop sector within head
                inc     dl                      ; sectors start at 1
                mov     byte ptr sector,dl
                xor     dx,dx
                div     word ptr headcyl        ; develop head within cylinder
                mov     byte ptr head,dl
                mov     word ptr cylinder,ax    ; what's left is the cylinder
                clc                             ; say all is well
                retn

;-----------------------------------------------------
chr_fail:       stc                             ; complain via carry flag
sub_exit:       retn                            ; common subroutine exit here

calc_chr        endp

;<07d81> * read disk sector addressed by cylinder/head/sector

read_disk       proc near
                mov     ah,02
                mov     dx,word ptr cylinder    ; load cylinder number
                mov     cl,06                   ; adjust for bios call
                shl     dh,cl                   ; 000:7d89 d2e6
                or      dh,byte ptr sector      ; sector # is in low bits
                mov     cx,dx
                xchg    ch,cl
                mov     dl,byte ptr disk_id     ; indicate what disk to read
                mov     dh,byte ptr head        ; specify the desired head
                int     13h                     ; read into es:bx
                retn

;-----------------------------------------------------

no_system_msg   db      0dh,0a
                db      'Non-System disk or disk error'
                db      0dh,0a
                db      'Replace and press any key when ready'
                db      0dh,0a,00

io_fileid       db      'IO      SYS'
                db      'MSDOS   SYS'

                db      00,00                   ; padding

signature       db      55,0aa

read_disk       endp
boot            ends

                end

   

New Articles










 
Copyright © 2000 eFront Media, Inc.
Hosted by www.Geocities.ws

1