当前位置:Linux教程 - Linux - MS-DOS引导区源代码

MS-DOS引导区源代码



         得到这段代码纯属偶然。开始我也不相信是微软的,但是我读了程序,发现还真是微软的东东,不过是DOS 4.0的。具体的来源,我也不太清楚。难道是哪位高人从微软偷来的?呵呵,不管那么多了。先来研究研究再说!

    Page ,132
    TITLE BOOT SECTOR 1 OF TRACK 0 - BOOT LOADER
    ;/*
    ; * Microsoft Confidential
    ; * Copyright (C) Microsoft Corporation 1991
    ; * All Rights Reserved.
    ; */

    ; Rev 1.0 ChrisP, AaronR and others. 2.0 format boot
    ;
    ; Rev 3.0 MarkZ PC/AT enhancements
    ; 2.50 in label
    ; Rev 3.1 MarkZ 3.1 in label due to vagaries of SYSing to IBM drive Ds
    ; This resulted in the BPB being off by 1. So we now trust
    ; 2.0 and 3.1 boot sectors and disbelieve 3.0.
    ;
    ; Rev 3.2 LeeAc Modify layout of extended BPB for >32M support
    ; Move PHYDRV to 3rd byte from end of sector
    ; so that it won have to be moved again
    ; FORMAT and SYS count on PHYDRV being in a known location
    ;
    ; Rev. 3.3 D.C. L. Changed Sec 9 EOT field from 15 to 18. May 29, 1986.
    ;
    ; Rev 3.31 MarkT The COUNT value has a bogus check (JBE????) to determine
    ; if weve loaded in all the sectors of IBMBIO. This will
    ; cause too big of a load if the sectors per track is high
    ; enough, causing either a stack overflow or the boot code
    ; to be overwritten.
    ;
    ; Rev 4.00 J. K. For DOS 4.00 Modified to handle the extended BPB, and
    ; 32 bit sector number calculation to enable the primary
    ; partition be started beyond 32 MB boundary.
    ;
    ;
    ; The ROM in the IBM PC starts the boot process by performing a hardware
    ; initialization and a verification of all external devices. If all goes
    ; well, it will then load from the boot drive the sector from track 0, head 0,
    ; sector 1. This sector is placed at physical address 07C00h. The initial
    ; registers are set up as follows: CS=DS=ES=SS=0. IP=7C00h, SP=0400H.
    ;
    ; The code in this sector is responsible for locating the MSDOS device drivers
    ; (IBMBIO) and for placing the directory sector with this information at
    ; physical address 00500h. After loading in this sector, it reads in the
    ; entirety of the BIOS at BIOSEG:0 and does a long jump to that point.
    ;
    ; If no BIOS/DOS pair is found an error message is displayed and the user is
    ; prompted to reinsert another disk. If there is a disk error during the
    ; process, a message is displayed and things are halted.
    ;
    ; At the beginning of the boot sector, there is a table which describes the
    ; MSDOS structure of the media. This is equivalent to the BPB with some
    ; additional information describing the physical layout of the driver (heads,
    ; tracks, sectors)
    ;
    ;==============================================================================
    ;REVISION HISTORY:
    ;AN000 - New for DOS Version 4.00 - J.K.
    ;AC000 - Changed for DOS Version 4.00 - J.K.
    ;AN00x - PTM number for DOS Version 4.00 - J.K.
    ;==============================================================================
    ;AN001; d52 Make the fixed positioned variable "CURHD" to be local. 7/6/87 J.K.
    ;AN002; d48 Change head settle at boot time. 7/7/87 J.K.
    ;AN003; P1820 New message SKL file 10/20/87 J.K.
    ;AN004; D304 New structrue of Boot record for OS2. 11/09/87 J.K.
    ;AN005; Changed version to 5.0 03/08/90 E.A.
    ;AN006; Changed to remove MSLOAD in first cluster restriction 04/23/90 J.H.
    ;==============================================================================


    ORIGIN EQU 7C00H ; Origin of bootstrap LOADER
    BIO_SEG EQU 70H ; Destingation segment of BIOS
    BIO_OFFSET EQU 700H ; Offset of bios
    SECTOR_SIZE EQU 512 ; Sector size in bytes
    DIR_ENTRY_SIZE EQU 32 ; Size of directory entry in bytes
    DIR_OFF EQU 500h
    IBM_LOAD_SIZE EQU 3 ;J.K. Size of IBMLOAD module in sectors
    ROM_DISKRD EQU 2
    DSK_PARMS EQU 1EH*4 ;POINTER TO DRIVE PARAMETERS



    ; ==========================================================================

    include version.inc
    include dirent.inc

    ; ==========================================================================

    SEGBIOS SEGMENT AT BIO_SEG

    ; Define the destination segment of the BIOS, including the
    ; initialization label

    BIOS LABEL BYTE

    SEGBIOS ENDS

    ; ==========================================================================

    CODE SEGMENT
    ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
    ORG ORIGIN


    Public $START
    $START:
    ; WARNING -- Don change this to a short jmp
    jmp Main ; Jump to start of code


    ; ==========================================================================

    ; Start of BPB area of the boot record
    IF IBMCOPYRIGHT
    DB "IBM "
    ELSE
    DB "MSDOS"
    ENDIF

    ; BUGBUG -- 7 Dec 1992 -- chuckst -- changed version back to 5.0 to
    ; avoid bug in PC-TOOLS DISKFIX
    OsVersion DB "5.0" ; DOS version number
    BytesPerSector DW SECTOR_SIZE ; Size of a physical sector
    SecsPerClust DB 8 ; Sectors per allocation unit
    ReservedSecs DW 1 ; Number of reserved sectors
    NumFats DB 2 ; Number of fats
    NumDirEntries DW 512 ; Number of direc entries
    TotalSectors DW 4*17*305-1 ; Number of sectors - number of hidden
    ; sectors (0 when 32 bit sector number)
    MediaByte DB 0F8H ; MediaByte byte
    NumFatSecs DW 8 ; Number of fat sectors
    SecPerTrack DW 17 ; Sectors per track
    NumHeads DW 4 ; Number of drive heads

    HiddenSecs DD 1 ; Number of hidden sectors
    BigTotalSecs DD 0 ; 32 bit version of number of sectors
    BootDrv DB 80h
    CurrentHead DB 0h ; Current Head
    ExtBootSig DB 41
    SerialNum DD 0
    VolumeLabel DB NO NAME
    FatId DB FAT12

    ; Danger!!! If not 32 bit sector number calculation,
    ; FORMAT should set the value of HiddenSecsHigh and
    ; BigTotalSectors to 0 !!!

    PUBLIC uData
    uData LABEL BYTE
    ;Equates to allow access to
    ;storage where Main is now
    Sec9 EQU BYTE PTR uData+0 ;11 byte diskette parm. table
    BiosLow EQU WORD PTR uData+11
    BiosHigh EQU WORD PTR uData+13
    CurTrk EQU WORD PTR uData+15
    CurSec EQU BYTE PTR uData+17
    DirLow EQU WORD PTR uData+18
    DirHigh EQU WORD PTR uData+20

    ; =========================================================================

    ; First thing is to reset the stack to a better and more known
    ; place. The ROM may change, but wed like to get the stack
    ; in the correct place.
    MAIN:
    cli ;Stop interrupts till stack ok
    xor AX,AX
    mov SS,AX ;Work in stack just below this routine

    ASSUME SS:CODE
    mov SP,ORIGIN
    push SS
    pop ES

    ASSUME ES:CODE

    ; We copy the disk parameter table into a local area. We scan
    ; the table above for non-zero parameters. Any we see get
    ; changed to their non-zero values. We copy the disk parameter
    ; table into a local area (overlayed into the code)

    mov BX,DSK_PARMS
    lds SI,DWORD PTR SS:[BX] ; get address of disk table
    push DS ; save original vector for possible
    push SI ; restore
    push SS
    push BX
    mov DI,OFFSET Sec9
    mov CX,11
    cld

    repz movsb
    push ES
    pop DS ; DS = ES = code = 0.
    assume DS:CODE

    ; Set the head settle time to 15ms because we don have room
    ; to do a disk retry and then set sectors per from the value
    ; in the BPB

    mov BYTE PTR [DI-2], 0fh ; Head settle time
    mov CX, SecPerTrack
    mov BYTE PTR [DI-7], cl ; End of Track

    mov [BX+2],AX ; Place in new disk parameter
    mov [BX],offset Sec9 ; table vector

    ; We may now turn interrupts back on. Before this, there is
    ; a small window when a reboot command may come in when the
    ; disk parameter table is garbage

    sti ; Interrupts OK now
    int 13h ; Reset the disk system just in case
    jc CkErr ; any thing funny has happened.

    ; The system is now prepared for us to begin reading.
    ; First, determine logical sector numbers of the start of the
    ; directory and the start of the data area.

    xor AX,AX
    cmp TotalSectors,AX ; 32 bit calculation?
    je Dir_Cont

    mov CX,TotalSectors
    mov WORD PTR BigTotalSecs,CX ; BigTotalSecs

    Dir_Cont:
    mov AL,NumFats ;Determine sector dir starts on
    mul NumFatSecs ;DX;AX
    add AX,WORD PTR HiddenSecs
    adc DX,WORD PTR HiddenSecs[2]
    add AX,ReservedSecs
    adc DX,0

    ; DX:AX = NumFats * NumFatSecs + ReservedSecs + cSecHid

    mov [DirLow],AX
    mov [DirHigh],DX
    mov [BiosLow],AX
    mov [BiosHigh],DX

    ; Take into account size of directory (only know number
    ; of directory entries)

    mov AX,DIR_ENTRY_SIZE ; bytes per directory entry
    mul NumDirEntries ; convert to bytes in directory
    mov BX,BytesPerSector ; add in sector size
    add AX,BX
    dec AX ; decrement so that we round up
    div BX ; convert to sector number
    add [BiosLow],AX ; Start sector # of Data area
    adc [BiosHigh],0

    ; We load in the first directory sector and examine it to
    ; make sure the the BIOS and DOS are the first two directory
    ; entries. If they are not found, the user is prompted to
    ; insert a new disk. The directory sector is loaded into 00500h

    mov BX,DIR_OFF ; sector to go in at 00500h

    mov DX,[DirHigh]
    mov AX,[DirLow] ; logical sector of directory
    call DoDiv ; convert to sector, track, head
    jc CkErr ; Overflow? BPB must be wrong!!

    mov al, 1 ; disk read 1 sector
    call DoCall ; do the disk read
    jb CkErr ; if errors try to recover


    ; Now we scan for the presence of BIOS file.

    mov DI,BX
    mov CX,11
    mov SI,OFFSET Bio ; point to "ibmbio com"
    repz cmpsb ; see if the same
    jnz CkErr ; if not there advise the user

    ; Found the BIOS. Check the second directory entry.
    ; SI will already point to "MSDOS SYS" if first compare
    ; was successful

    lea DI,[BX+20h]
    ;** mov SI,OFFSET Dos
    mov CX,11
    repz cmpsb
    jz DoLoad

    ; There has been some recoverable error. Display a message
    ; and wait for a keystroke.


    CkErr: mov SI,OFFSET SysMsg ; point to no system message

    ErrOut:
    call Write ; and write on the screen


    xor AX,AX ; wait for response
    int 16h ; get character from keyboard
    pop SI ; reset disk parameter table back to
    pop DS ; rom
    pop [SI]
    pop [SI+2]
    int 19h ; Continue in loop till good disk

    Load_Failure:
    pop ax ;adjust the stack
    pop ax
    pop ax
    jmp short CkErr ;display message and reboot.

    ; We now begin to load the BIOS in.
    ; All we have to do is just read is multiply the BioStartClus
    ; by SecsPerClust to find the logical sector for the start
    ; of the BIOS file. When this value is added to the double
    ; word BiosHigh:BiosLow we get the absolute sector offset
    ; for the start of the file and then read the sectors
    ; contiguously IBM_LOAD_SIZE times. We here assume that
    ; IBMLOAD module is contiguous. Currently we estimate that
    ; IBMLOAD module will not be more than 3 sectors.
    DoLoad:
    mov AX,[BX].DIR_FIRST ; AX = BIOS starting cluster
    dec AX ; Subtract first 2 reserved clusters
    dec AX
    mov BL,SecsPerClust ; BX = Sectors per cluster
    xor BH,BH
    mul BX ; DX:AX = first logical sector of bios

    add AX,[BiosLow] ; Add absolute start sector
    adc DX,[BiosHigh] ; DX:AX = Absolute bios sector offset

    mov BX,BIO_OFFSET ;offset of ibmbio(IBMLOAD) to be loaded.
    mov CX,IBM_LOAD_SIZE ;# of sectors to read.

    Do_While:
    push AX
    push DX
    push CX
    call DoDiv ; DX:AX = sector number.
    jc Load_Failure ; Adjust stack. Show error message
    mov al, 1 ; Read 1 sector at a time.
    ; This is to handle a case of media
    ; when the first sector of IBMLOAD is the
    ; the last sector in a track.
    call DoCall ; Read the sector.
    pop CX
    pop DX
    pop AX
    jc CkErr ; Read error?
    add AX,1 ; Next sector number.
    adc DX,0
    add BX,BytesPerSector ; Adjust buffer address.
    loop Do_While


    ; =========================================================================
    ; Main read-in loop.
    ; ES:BX points to area to read.
    ; Count is the number of sectors remaining.
    ; BIOS$ is the next logical sector number to read
    ;
    ; CurrentHead is the head for this next disk request
    ; CurTrk is the track for this next request
    ; CurSec is the beginning sector number for this request
    ;
    ; AX is the number of sectors that we may read.
    ;
    ; =========================================================================
    ;
    ; IBMINIT requires the following input conditions:
    ;
    ; DL = INT 13 drive number we booted from
    ; CH = media byte
    ; IBMBIO init routine should check if the boot record is the
    ; extended one by looking at the extended_boot_signature.
    ; If it is, then should us AX;BX for the starting data sector number.
    ; =========================================================================

    DISKOK:
    mov CH,MediaByte
    mov DL,BootDrv
    mov BX,[BiosLow] ; J.K.I1.Get bios sector in bx
    mov AX,[BiosHigh] ; J.K.I1.
    jmp FAR PTR Bios ;CRANK UP THE DOS

    WRITE:
    lodsb ;GET NEXT CHARACTER
    or AL,AL ;Clear the high bit
    jz EndWr ;ERROR MESSAGE UP, JUMP TO BASIC
    mov AH,14 ;WILL WRITE CHARACTER & ATTRIBUTE
    mov BX,7 ;ATTRIBUTE
    int 10h ;PRINT THE CHARACTER
    jmp Write

    ; Convert a logical sector into Track/sector/head.
    ; DX;AX has the sector number. Because of not enough space, we
    ; are going to use Simple 32 bit division here.
    ; Carry set if DX;AX is too big to handle.

    DODIV:
    cmp DX,SecPerTrack ; To prevent overflow!!!
    jae DivOverFlow ; Compare high word with the divisor.
    div SecPerTrack ; AX = Total tracks, DX = sector number
    inc DL ; We assume SecPerTrack < 255 & DH=0
    ; curSec is 1-based.
    mov CurSec, DL ; Save it
    xor DX,DX
    div NumHeads
    mov CurrentHead,DL ;Also, NumHeads < 255.
    mov CurTrk,AX
    clc
    ret

    DivOverFlow:
    stc

    EndWR:
    ret
    ; =========================================================================
    ;
    ; Issue one read request. ES:BX have the transfer address,
    ; AL is the number of sectors.
    ;
    ; =========================================================================

    DOCALL:
    mov AH,ROM_DISKRD ;=2
    mov DX,CurTrk
    mov CL,6
    shl DH,CL
    or DH,CurSec
    mov CX,DX
    xchg CH,CL
    mov DL, BootDrv
    mov DH, CurrentHead
    int 13h
    ret

    ; =========================================================================

    include boot.cl1

    ; =========================================================================

    IF IBMCOPYRIGHT
    Bio DB "IBMBIO COM"
    Dos DB "IBMDOS COM"
    ELSE
    Bio DB "IO SYS"
    Dos DB "MSDOS SYS"
    ENDIF

    ; =========================================================================

    Free EQU (SECTOR_SIZE - 4) - ($-$start)

    if Free LT 0
    %out FATAL PROBLEM:boot sector is too large
    .ERR
    endif

    org origin + (SECTOR_SIZE - 2)
    db 55h,0aah ; Boot sector signature

    ; =========================================================================

    CODE ENDS
    END
    发布人:Kevin 来自:CandyLinux中文社区