;------------------------------
; boot sector disassembly by michael dehlwes
; from ms-dos 6.2, german version.
; this source will assemble exactly to my boot record
; this code will be loaded by bios to 0:7c00h
; offset of error message:
; 7d9e (used in code)
; -19e (physically)
; ----
; 7c00
; then this code loads io.sys to 0:700h
; ss=es=ds=0 for most parts of code
; first 11 bytes of code (offset 3eh) will be overwritten with
; disk parameter table (dpt)
;name: boot.bin
;filelength: 00200h - 512d
;start (cs:ip): 00000h
;code ende: 00200h end
;code anfang: 00000h begin
;datum: sat jul 30 11:22:51 1994
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE,ES:NOTHING,SS:NOTHING
ORG 0
H00000: JMP Short H0003E ;00000 eb3c
;---------------------------------------------------
NOP ;00002 90
;---------------------------------------------------
DB "MSDOS5.0"
; but it's a dos 6.2 harddisk. formats are the same, i think.
;---------------------------------------------------
; media description follows here.
DB 0 ;0000b
DB 02h ;0000c
; bytes per sector
DB 10h ;0000d
; sectors per cluster
DB 01h ;0000e
DB 00h ;0000f
; boot sectors at beginning
DB 02h ;00010
; fat copies
DB 00h ;00011
DB 02h ;00012
; boot directory entries
DB 00h ;00013
DB 00h ;00014
; (unused): total sectors on disk
DB 0F8h ;00015
; media descriptor byte
DB 0CBh ;00016
DB 00h ;00017
; sectors per fat
DB 38h ;00018
DB 00h ;00019
; sectors per track
DB 0Fh ;0001a
DB 00h ;0001b
; sides
DB 38h ;0001c
DB 00h ;0001d
DB 00h ;0001e
DB 00h ;0001f
; special hidden sectors
DB 0A8h ;00020
DB 0A9h
DB 0Ch
DB 00h
; dword: big total number of sectors
DB 80h ;00024
DB 00h ;00025
; physical drive number 80h = harddisk 0
DB 29h ;00026
; extended boot record signature
DB 0D8h,1Dh,";'" ;00027
; dword: volume serial number
DB "HD-MICHI " ;0002b
; volume label
DB "FAT16 "
; file system id
;---------------------------------------------------
; following code will be overwritten with dpt
; 3eh-48h
; dd 49h = (sect/fat)*fats + hiddensectors + bootsectors@begin + bootdirsectors
; this data is required when giving control to io.sys
; dd 50h = (sect/fat)*fats + hiddensectors + bootsectors
; = location of root directory
H0003E: CLI
XOR AX,AX
MOV SS,AX ;ss=0
MOV SP,7C00h ;sp=7c00h
PUSH SS
POP ES ;es=0
MOV BX,0078h
LDS SI,SS:[BX] ;ds:si = [0:78h] int 1eh vector =
; pointer to disk parameter table
PUSH DS ; 4 registers pushed, will only be poped
PUSH SI ; when error occurred and int 19h is called
PUSH SS
PUSH BX
MOV DI,7C3Eh ; start of code
MOV CX,0Bh ; 11 bytes
CLD ; overwrite first code with disk parameter
REPZ MOVSB ; table (dpt)
PUSH ES
POP DS ;ds=0
; after rep movsb di points to 7c49h, end of dpt
; [di-2] = dpt[9] = head settle time in milliseconds
MOV Byte Ptr [DI-02h],0Fh
MOV CX,DS:[7C18h] ; get sectors per track
; [di-7] = dpt[4]
MOV [DI-07h],CL ; store into dpt
MOV [BX+02h],AX ; redirect dpt pointer to our data
MOV Word Ptr [BX],7C3Eh
STI
; ax=0, dl=0, int 13h - reset disk system
INT 13h ;b-reset_fd
JB H000ED ;error ? yes -> error prompt
XOR AX,AX
CMP DS:[7C13h],AX ; check small field total sectors on disk
JZ H00084 ; this field is unused with big drives
; so if 0 (unused), skip
MOV CX,DS:[7C13h]
MOV DS:[7C20h],CX ; else store value to big field
H00084: MOV AL,DS:[7C10h] ; sectors per fat * fat copies (2 in my case)
MUL Word Ptr DS:[7C16h] ; -> dx:ax
ADD AX,DS:[7C1Ch] ; add hidden sectors
ADC DX,DS:[7C1Eh]
ADD AX,DS:[7C0Eh] ; add boot sectors at beginning
ADC DX,+00h
MOV DS:[7C50h],AX ; store to [50h]
MOV DS:[7C52h],DX
MOV DS:[7C49h],AX ; and to [49h]
MOV DS:[7C4Bh],DX
MOV AX,20h
MUL Word Ptr DS:[7C11h] ; calculate boot directory size in bytes
MOV BX,DS:[7C0Bh]
ADD AX,BX
DEC AX
DIV BX ; adjust to sectors
ADD DS:[7C49h],AX ; add to dd [49h]
ADC Word Ptr DS:[7C4Bh],0
MOV BX,500h ; load root directory to es:500h
MOV DX,DS:[7C52h] ; location of root dir
MOV AX,DS:[7C50h]
CALL H00160 ;calc sector
JB H000ED ;error? -> prompt for valid system disk
MOV AL,1 ;read 1 sector
CALL H00181 ;read hd sector
JB H000ED ;error? -> prompt for valid system disk
MOV DI,BX ;check if first entry is io.sys
MOV CX,0Bh ;length "io sys"
MOV SI,7DDFh ;offset "io sys"
REPZ CMPSB
JNZ H000ED ;not identical? -> error prompt
; after previos rep cmps si points at "msdos sys"
LEA DI,[BX+20h] ;load offset "msdos sys" in root dir
MOV CX,0Bh ;length "msdos sys"
REPZ CMPSB
JZ H00105 ;identical? yes-> continue with file load
;no-> error prompt
;---------------------------------
; invalid system disk, prompt for new one.
H000ED: MOV SI,7D9Eh ;offset "no system disk or drive error"
CALL H00152 ;print asciz string
XOR AX,AX
INT 16h ;b-next_kbd_char
POP SI
POP DS
POP [SI]
POP [SI+2]
INT 19h ;bios reboot
H00100: POP AX ;adjust stack
POP AX
POP AX
JMP Short H000ED ;reboot
;---------------------------------------------------
; read file from disk (io.sys)
H00105: MOV AX,[BX+1Ah] ; get location of io.sys (in dir entry)
DEC AX
DEC AX
MOV BL,DS:[7C0Dh]
XOR BH,BH
MUL BX ; convert to cluster
; dx:ax = [b 7c0dh] * ( [w bx+1ah] - 2 )
ADD AX,DS:[7C49h]
ADC DX,DS:[7C4Bh]
; dx:ax+= [dd 7c49h]
MOV BX,0700h ; load io.sys to es:700h
MOV CX,3 ; load three sectors
; read next sector
H00120: PUSH AX
PUSH DX
PUSH CX
CALL H00160 ;calc sector
JC H00100 ;error? -> prompt for valid system disk
MOV AL,01h ;read 1 sector
CALL H00181 ;read hd sector
POP CX
POP DX
POP AX
JB H000ED ;error? -> prompt for valid system disk
; advance to next sector
ADD AX,1
ADC DX,0
ADD BX,DS:[7C0Bh]
LOOP H00120
; give control to io.sys
MOV CH,DS:[7C15h]
MOV DL,DS:[7C24h]
MOV BX,DS:[7C49h]
MOV AX,DS:[7C4Bh]
DB 0EAh
DW 0,70h
; =jmp 0070h:0000h ;0014d ea00007000
;---------------------------------------------------
; write a 0-terminated string to tty (bios)
; offset in si
H00152: LODSB ;00152
OR AL,AL ;00153
JZ H00180 ;jmp to ret instr. ;00155
MOV AH,0Eh ;00157
MOV BX,0007h ;00159
INT 10h ;b-wr_tty_char ;0015c
JMP Short H00152 ;0015e
;---------------------------------------------------
; calculates logical sector
; on entry: dx:ax (physical sector/cluster?)
; carry flag set on error
; if dx >= [7c18h] goto errorexit
; dx:ax div [w 7c18h] -> ax
; remainder+1 -> [b 7c4fh]=sector number
; 0:ax div [w 7c1ah] -> [w 7c4dh]=cylinder number
; remainder -> [b 7c25h]=head number
H00160: CMP DX,DS:[7C18h] ;00160
JNB H0017F ; error exit ;00164
DIV Word Ptr DS:[7C18h] ;00166
INC DL ;0016a
MOV DS:[7C4Fh],DL ;0016c
XOR DX,DX ;00170
DIV Word Ptr DS:[7C1Ah] ;00172
MOV DS:[7C25h],DL ;00176
MOV DS:[7C4Dh],AX ;0017a
CLC ;0017d
RET ;ret_near ;0017e
H0017F: STC ;0017f
H00180: RET ;ret_near ;00180
;---------------------------------------------------
; read disk sector
; al (must be set on entry): number of sectors to read
; es:bx: offset data buffer
; byte [7c24h] = drive number
; byte [7c25h] = head number
; word [7c4dh] = cylinder number
; byte [7c4fh] = sector number
H00181: MOV AH,02h ; bios function read sector
MOV DX,DS:[7C4Dh] ;00183
MOV CL,06h ;00187
SHL DH,CL ;00189
OR DH,DS:[7C4Fh] ;0018b
MOV CX,DX ;0018f
XCHG CH,CL ;00191
; convert to bios call requirements
; cx=ccccccccccssssss
; ch=low eight bits of cylinder number "c"
; cl=sector number (bits 0-5) "s"
; high two bits of cylinder (bit 6-7 hd only) "c"
MOV DL,DS:[7C24h] ;00193
; dl=drive number (bit 7 set: hard disk)
MOV DH,DS:[7C25h] ;00197
; dh=head number
INT 13h ;bios-read disk sect;0019b
RET ;ret_near ;0019d
;---------------------------------------------------
; ralf brown says:
; 1beh (16 bytes) partition record for partition 1
; 1ceh (16 bytes) partition record for partition 2
; 1deh (16 bytes) partition record for partition 3
; 1eeh (16 bytes) partition record for partition 4
; but that's not valid in this case. funny.
DB 13,10,"Kein System oder Laufwerksfehler" ;0019e
; no system or drive error
DB 13,10,"Wechseln und Taste drcken",13,10,0
; change [disk] and press key
DB "IO SYS" ;001df
DB "MSDOS SYS" ;001ea
DB 9 DUP (0) ; fill ;001f5
DB 055h,0AAh ;001fe
; signature, indicates valid boot block.
CODE ENDS
END H00000