;------------------------------ ; 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 drcken",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