Dec 122017
 
Disassembled DOS bootstrap program.
File BOOTSECT.ZIP from The Programmer’s Corner in
Category Assembly Language
Disassembled DOS bootstrap program.
File Name File Size Zip Size Zip Type
BOOTSECT.TXT 14563 4293 deflated
TPCREAD.ME 199 165 deflated

Download File BOOTSECT.ZIP Here

Contents of the BOOTSECT.TXT file


; PC-DOS Bootstrap Loader
;
; This code is found in sector 0 of every PC-DOS diskette. It loads
; the file IBMBIO.COM into memory and transfers control to it (on a
; bootable diskette) or displays relevant error messages (on a non-
; bootable diskette)
;
; Although this code (in object form) appears in sector 0 of every
; diskette formatted by DOS, copyrights are no doubt in effect, by
; Microsoft, or IBM, or Both.
; It has been hand dis-assembled from object code, and appropriately
; commented. Beware the computer police!
;
;
; Notes - This code taken from a high-density (1.2Meg) diskette
; - Boot code is loaded into memory, at absolute addr 0000:7C00
; - Several locations within the code are used for data after
; they are no longer useful. These locations have been combined
; into a structure, the elements of which are names xNN, where
; NN is a two digit number corresponding to sequence. They are
; accessed via equates, of the form aXXXXXX, where XXXXXX is
; a symbolic name ("a" stands for "alias")
;
;*****************************************************************************


LoadAdr equ 7C00h ; Load address of this code
Vec_1E equ 0078h ; Address of Interrupt 1E Vector
FNSize equ 11 ; Size of a Filename + Extension

DirLoad equ 0500h ; Where the directory block is loaded
BIOLoad equ 0700h ; Where IBMBI.COM is loaded

ConOut equ 10h ; BIOS Interrupt: Console Output
DiskInt equ 13h ; BIOS Interrupt: Diskette Control
KbdInt equ 16h ; BIOS Interrupt: Keyboard Input
Reboot equ 19h ; BIOS Interrupt: Reboot This Machine



; The following structure a directory entry.
; It's here to make the code look better.

DirNtry struc
Filename db 8 dup(?)
Extension db 3 dup(?)
Attrib db ?
Reserved db 10 dup(?)
FileTime dw ?
FileDate dw ?
FirstClstr dw ?
FileSize dd ?
DirNtry ends


page

; The following structure corresponds to the section of code space
; which is reused. All aliases are defined as byte offsets.
; In addition, the diskette-description header symbols are defined
; here, as absolute addresses, because that is how they are
; accessed within the program (Offsets from DS, which is 0000)

ReUsed struc
db LoadAdr dup(?) ; The beginning of memory
db 3 dup(?) ; The jump to executable code
OEM_ID db 8 dup(?) ; OEM Identification
Byt_Sec dw ? ; Bytes per Sector (512)
Sct_AlU db ? ; Sectors per Allocation Unit
RsvdSct dw ? ; Reserved Sectors (strt at 0)
NumFATs db ? ; Number of FAT's
RootSiz dw ? ; # of Root Dir Entries (112)
TotSect dw ? ; Total Sectors in Device (720)
MedDesc db ? ; Media Descriptor Byte (DS/9s)
FATSect dw ? ; # Sectors used by each FAT
Sct_Trk dw ? ; Sectors per Track
NumHead dw ? ; Number of Heads
NumHSct dw ? ; Nubmer of Hidden Sectors
aDrivNm db ? ; Drive Number (always 0, = A:)
aHeadNm db ? ; Head Number
db 0Bh dup(?) ; Disk Parameters Table
db ? ; - Not Resused -- It's START:
a1stDat dw ? ; First sector above directory
aTrakNm dw ? ; Track Number
aSectNm db ? ; Sector Number (1..n)
aFilSize db ? ; Sectors in current boot file
aCurSect dw ? ; Secotr to read from
aDirLoc dw ? ; First sector in directory
ReUsed ends


page
org 0000


Entry: 0000 JMP Start ; Skip identification code
0002 NOP


0003 db 'IBM 3.1' ; OEM Identification
000B dw 0200h ; Bytes per Sector (512)
000D db 2 ; Sectors per Allocation Unit
000E dw 1 ; Reserved Sectors (strt at 0)
0010 db 2 ; Number of FAT's
0011 dw 70h ; # of Root Dir Entries (112)
0013 dw 02D0h ; Total Sectors in Device (720)
0015 db 0FDh ; Media Descriptor Byte (DS/9s)
0016 dw 2 ; # Sectors used by each FAT
0018 dw 9 ; Sectors per Track
001A dw 2 ; Number of Heads
001C dw 0 ; Nubmer of Hidden Sectors

dw 0 ; - gets filled in...


DskParm db 00, 00, 00, 00 ; Disk parameter block - gets
db 0Fh, 00, 00, 00 ; contents of *IntVect_1E
db 00, 01h, 00 ; (except those already set)


Start: 002B CLI ; The stack will be placed just
002C XOR AX,AX ; below executable code
002E MOV SS,AX
0030 MOV SP, LoadAdr
0033 PUSH SS ; ES will do 0-page addressing
0034 POP ES

0035 MOV BX, Vec_1E ; Diskette parms at *IntVect_1E
0038 LDS SI, SS:[BX] ; DS:SI => Diskette Params
003B PUSH DS ; - These addresses are being
003C PUSH SI ; saved so that the locations
003D PUSH SS ; may be restored if a boot
003E PUSH BX ; error occurs
003F MOV DI, DskParm ; Params will go into our CS
0042 MOV CX, 000Bh ; Note - If any of the bytes
0045 CLD ; are already set in our
DParmLp:0046 LODSB ; table, our values are
0047 CMP Byte Ptr ES:[DI], 00 ; retained. This allows
004B JZ SetParm ; simple changes to the
004D MOV AL, ES:[DI] ; loaded code for any
SetParm:0050 STOSB ; diskette in use.
0051 MOV AL, AH
0053 LOOP DParmLp

ReParm: 0055 PUSH ES ; Re-point the Diskette params
0056 POP DS ; into the block just built
0057 MOV [BX+02],AX
005A MOV Word Ptr [BX],7C20
005E STI

005F INT DiskInt ; Reset the disk subsystem
0061 JB DskErr2 ; (fatal error abort)
0063 MOV AL, [NumFATs] ; Find the starting sector for
0066 CBW ; the Root Directory
0067 MUL Word Ptr [FATSect]
006B ADD AX, [NumHSct]
006F ADD AX, [RsvdSct]
0073 MOV [aDirLoc], AX
0076 MOV [a1stDat], AX
0079 MOV AX, TYPE DirNtry
007C MUL Word Ptr [RootSiz] ; How big is the directory?
0080 MOV BX, [Byt_Sec]
0084 ADD AX, BX ; (this will round up)
0086 DEC AX
0087 DIV BX
0089 ADD [a1stDat], AX ; Store upper bounds of Root
008D MOV BX, DirLoad
0090 MOV AX, [aDirLoc] ; And point to the first block
0093 CALL CvtSct
0096 MOV AX, 0201h
0099 CALL ReadSct ; Read it In!
009C JB DskErr1 ; (Can't do it! Abort!)
009E MOV DI, BX ; Index into the directory blk
00A0 MOV CX, FNSize
00A3 MOV SI, BIO_Nam ; Looking for "IBMBIO.COM"
00A6 REPZ
00A7 CMPSB
00A8 JNZ DskErr1 ; It wasn't the first file!

00AA LEA DI, [BX+20] ; Looking for "IBMDOS.COM"
00AD MOV SI, DOS_Nam
00B0 MOV CX, FNSize
00B3 REPZ
00B4 CMPSB
00B5 JZ BootIt ; Hey! It's Bootable!

DskErr1:00B7 MOV SI, OFFSET DskMsg ; Yell at the user
DE_Sub: 00BA CALL DspErr
00BD XOR AH, AH ; And wait for a keystroke
00BF INT KbdInt
00C1 POP SI ; Pop the Int_1E Vector Addr
00C2 POP DS
00C3 POP [SI] ; Diskette Params pointer goes
00C5 POP [SI+02] ; back into this vector
00C8 INT Reboot ; And we do it all again.

DskErr2:00CA MOV SI, OFFSET BootMsg ; An indeterminate, real bad
00CD JMP DE_Sub ; error has happened.


BootIt: 00CF MOV AX, [DirLoad.FileSize] ; Get the IBMBIO.COM's size
00D2 XOR DX, DX ; We hope it's under 64k!
00D4 DIV Word Ptr [Byt_Sec]
00D8 INC AL
00DA MOV [aFilSize], AL ; Store it away
00DD MOV AX, [a1stDat] ; It must start right after
00E0 MOV [aCurSect], AX ; the root directory ends
00E3 MOV BX, BIOLoad
RdLoop: 00E6 MOV AX, [a1stDat] ; So set up the location
00E9 CALL CvtSct
00EC MOV AX, [Sct_Trk] ; And read that track, from
00EF SUB AL, [aSectNm] ; that sector to the end
00F3 INC AX
00F4 PUSH AX
00F5 CALL ReadSct
00F8 POP AX
00F9 JB DskErr2
00FB SUB [aFilSiz], AL ; Is there any more?
00FF JBE CallBIO
0101 ADD [a1stDat], AX ; Yes, position the buffer ptr
0105 MUL Word Ptr [Byt_Sec] ; after what we've read in,
0109 ADD BX, AX ; and read the next track
010B JMP RdLoop
CallBIO:010D MOV CH, [MedDesc] ; Ready to call IBMBIO.COM
0111 MOV DL, [aDrivNm]
0115 MOV BX, [aCurSct]
0119 JMP 0070:0000


;****************************************************************
;
; DspErr
;
; Display error message on console
;
; Input:
; DS:SI = Pointer to NUL-terminated string
;

DspErr: 011E LODSB
011F OR AL, AL ; Check for End-Of-String
0121 JZ Return ; Save a byte!
0123 MOV AH, 0E ; Using TTYOUT mode
0125 MOV BX, 0007
0128 INT Video
012A JMP DspErr


;****************************************************************
;
; CvtSct
;
; Convert logical sector number to absolute Head / Track / Sector
; position.
;
; Input:
; AX = Logical Sector Number
;
; Output:
; -- = Absolute position is stored in aliased variables
; AX = Track Number
; DL = Head Number

CvtSct: 012C XOR DX,DX
012E DIV Word Ptr [SctTrk] ; Sectors go from 1 .. N
0132 INC DL
0134 MOV [aSectNm], DL
0138 XOR DX, DX
013A DIV Word Ptr [NumHead]
013E MOV [aHeadNm], DL
0142 MOV [aTrakNm], AX
Return: 0145 RET


;****************************************************************
;
; ReadSct
;
; Reads a sector into memory
; position.
;
; Input:
; AL = Number of sectors to read
; BX = Buffer Address
;
; Output:
; -- = Output is identical to BIOS Interrupt 13 (AH=2)

ReadSct:0146 MOV AH, 02 ; We will be doing a Read
0148 MOV DX, [aTrakNm] ; Track and sector get mixed -
014C MOV CL, 06 ; high 2 bits of track number
014E SHL DH, CL ; are combined with sector #
0150 OR DH, [aSectNm] ; (allows 1024 tracks/cyl)
0154 MOV CX, DX
0156 XCHG CH, CL
0158 MOV DX, [aDrivNum] ; Drive and Head are here
015C INT DiskInt ; Perform the operation
015E RET



;******************************************************************************
;
; Messages, And Whatever else is Needed
;
;******************************************************************************


DskMsg 015F db 13, 10, 'Non-System disk or disk error'
db 13, 10, 'Replace and strike any key when ready'
db 13, 10, 0
BootMsg 01A8 db 13, 10, 'Disk Boot failure'
db 13, 10, 0

BIO_Nam 01BE db 'IBMBIO COM'
DOS_Nam 01CA db 'IBMDOS COM'

Resrvd db 42 dup( 0 )
Boot_ID db 55h, 0AAh


 December 12, 2017  Add comments

Leave a Reply