Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- How It Works -- DOS Floppy Disk Boot Sector
- Version 1a
- by Hale Landis <hlandis@ibm.net>
- THE "HOW IT WORKS" SERIES
- This is one of several How It Works documents. The series
- currently includes the following:
- * How It Works -- CHS Translation
- * How It Works -- Master Boot Record
- * How It Works -- DOS Floppy Boot Sector
- * How It Works -- OS2 Boot Sector
- * How It Works -- Partition Tables
- DOS FLOPPY DISK BOOT SECTOR
- This article is a disassembly of a floppy disk boot sector for a
- DOS floppy. The boot sector of a floppy disk is located at
- cylinder 0, head 0, sector 1. This sector is created by a floppy
- disk formating program, such as the DOS FORMAT program. The boot
- sector of a FAT hard disk partition has a similar layout and
- function. Basically a bootable FAT hard disk partition looks
- like a big floppy during the early stages of the system's boot
- processing.
- At the completion of your system's Power On Self Test (POST), INT
- 19 is called. Usually INT 19 tries to read a boot sector from
- the first floppy drive. If a boot sector is found on the floppy
- disk, the that boot sector is read into memory at location
- 0000:7C00 and INT 19 jumps to memory location 0000:7C00.
- However, if no boot sector is found on the first floppy drive,
- INT 19 tries to read the MBR from the first hard drive. If an
- MBR is found it is read into memory at location 0000:7c00 and INT
- 19 jumps to memory location 0000:7c00. The small program in the
- MBR will attempt to locate an active (bootable) partition in its
- partition table. If such a partition is found, the boot sector
- of that partition is read into memory at location 0000:7C00 and
- the MBR program jumps to memory location 0000:7C00. Each
- operating system has its own boot sector format. The small
- program in the boot sector must locate the first part of the
- operating system's kernel loader program (or perhaps the kernel
- itself or perhaps a "boot manager program") and read that into
- memory.
- INT 19 is also called when the CTRL-ALT-DEL keys are used. On
- most systems, CTRL-ALT-DEL causes an short version of the POST to
- be executed before INT 19 is called.
- =====
- Where stuff is:
- The BIOS Parameter Block (BPB) starts at offset 0.
- The boot sector program starts at offset 3e.
- The messages issued by this program start at offset 19e.
- The DOS hidden file names start at offset 1e6.
- The boot sector signature is at offset 1fe.
- Here is a summary of what this thing does:
- 1) Copy Diskette Parameter Table which is pointed to by INT 1E.
- 2) Alter the copy of the Diskette Parameter Table.
- 3) Alter INT 1E to point to altered Diskette Parameter Table.
- 4) Do INT 13 AH=00, disk reset call.
- 5) Compute sector address of root directory.
- 6) Read first sector of root directory into 0000:0500.
- 7) Confirm that first two directory entries are for IO.SYS
- and MSDOS.SYS.
- 8) Read first 3 sectors of IO.SYS into 0000:0700 (or 0070:0000).
- 9) Leave some information in the registers and jump to
- IO.SYS at 0070:0000.
- NOTE:
- This program uses the CHS based INT 13H AH=02 to read the FAT
- root directory and to read the IO.SYS file. If the drive is
- >528MB, this CHS must be a translated CHS (or L-CHS, see my
- BIOS TYPES document). Except for internal computations no
- addresses in LBA form are used, another reason why LBA doesn't
- solve the >528MB problem.
- =====
- Here is the entire sector in hex and ascii.
- OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F *0123456789ABCDEF*
- 000000 eb3c904d 53444f53 352e3000 02010100 *.<.MSDOS5.0.....*
- 000010 02e00040 0bf00900 12000200 00000000 *...@............*
- 000020 00000000 0000295a 5418264e 4f204e41 *......)ZT.&NO NA*
- 000030 4d452020 20204641 54313220 2020fa33 *ME FAT12 .3*
- 000040 c08ed0bc 007c1607 bb780036 c5371e56 *.....|...x.6.7.V*
- 000050 1653bf3e 7cb90b00 fcf3a406 1fc645fe *.S.>|.........E.*
- 000060 0f8b0e18 7c884df9 894702c7 073e7cfb *....|.M..G...>|.*
- 000070 cd137279 33c03906 137c7408 8b0e137c *..ry3.9..|t....|*
- 000080 890e207c a0107cf7 26167c03 061c7c13 *.. |..|.&.|...|.*
- 000090 161e7c03 060e7c83 d200a350 7c891652 *..|...|....P|..R*
- 0000a0 7ca3497c 89164b7c b82000f7 26117c8b *|.I|..K|. ..&.|.*
- 0000b0 1e0b7c03 c348f7f3 0106497c 83164b7c *..|..H....I|..K|*
- 0000c0 00bb0005 8b16527c a1507ce8 9200721d *......R|.P|...r.*
- 0000d0 b001e8ac 0072168b fbb90b00 bee67df3 *.....r........}.*
- 0000e0 a6750a8d 7f20b90b 00f3a674 18be9e7d *.u... .....t...}*
- 0000f0 e85f0033 c0cd165e 1f8f048f 4402cd19 *._.3...^....D...*
- 000100 585858eb e88b471a 48488a1e 0d7c32ff *XXX...G.HH...|2.*
- 000110 f7e30306 497c1316 4b7cbb00 07b90300 *....I|..K|......*
- 000120 505251e8 3a0072d8 b001e854 00595a58 *PRQ.:.r....T.YZX*
- 000130 72bb0501 0083d200 031e0b7c e2e28a2e *r..........|....*
- 000140 157c8a16 247c8b1e 497ca14b 7cea0000 *.|..$|..I|.K|...*
- 000150 7000ac0a c07429b4 0ebb0700 cd10ebf2 *p....t).........*
- 000160 3b16187c 7319f736 187cfec2 88164f7c *;..|s..6.|....O|*
- 000170 33d2f736 1a7c8816 257ca34d 7cf8c3f9 *3..6.|..%|.M|...*
- 000180 c3b4028b 164d7cb1 06d2e60a 364f7c8b *.....M|.....6O|.*
- 000190 ca86e98a 16247c8a 36257ccd 13c30d0a *.....$|.6%|.....*
- 0001a0 4e6f6e2d 53797374 656d2064 69736b20 *Non-System disk *
- 0001b0 6f722064 69736b20 6572726f 720d0a52 *or disk error..R*
- 0001c0 65706c61 63652061 6e642070 72657373 *eplace and press*
- 0001d0 20616e79 206b6579 20776865 6e207265 * any key when re*
- 0001e0 6164790d 0a00494f 20202020 20205359 *ady...IO SY*
- 0001f0 534d5344 4f532020 20535953 000055aa *SMSDOS SYS..U.*
- =====
- The first 62 bytes of a boot sector are known as the BIOS
- Parameter Block (BPB). Here is the layout of the BPB fields
- and the values they are assigned in this boot sector:
- db JMP instruction at 7c00 size 2 = eb3c
- db NOP instruction 7c02 1 90
- db OEMname 7c03 8 'MSDOS5.0'
- dw bytesPerSector 7c0b 2 0200
- db sectPerCluster 7c0d 1 01
- dw reservedSectors 7c0e 2 0001
- db numFAT 7c10 1 02
- dw numRootDirEntries 7c11 2 00e0
- dw numSectors 7c13 2 0b40 (ignore numSectorsHuge)
- db mediaType 7c15 1 f0
- dw numFATsectors 7c16 2 0009
- dw sectorsPerTrack 7c18 2 0012
- dw numHeads 7c1a 2 0002
- dd numHiddenSectors 7c1c 4 00000000
- dd numSectorsHuge 7c20 4 00000000
- db driveNum 7c24 1 00
- db reserved 7c25 1 00
- db signature 7c26 1 29
- dd volumeID 7c27 4 5a541826
- db volumeLabel 7c2b 11 'NO NAME '
- db fileSysType 7c36 8 'FAT12 '
- =====
- Here is the boot sector...
- The first 3 bytes of the BPB are JMP and NOP instructions.
- 0000:7C00 EB3C JMP START
- 0000:7C02 90 NOP
- Here is the rest of the BPB.
- 0000:7C00 ......4d 53444f53 352e3000 02010100 * MSDOS5.0.....*
- 0000:7C10 02e00040 0bf00900 12000200 00000000 *...@............*
- 0000:7C20 00000000 0000295a 5418264e 4f204e41 *......)ZT.&NO NA*
- 0000:7C30 4d452020 20204641 54313220 2020.... *ME FAT12 *
- Now pay attention here...
- The 11 bytes starting at 0000:7c3e are immediately overlaid by
- information copied from another part of memory. That
- information is the Diskette Parameter Table. This data is
- pointed to by INT 1E. This data is:
- 7c3e = Step rate and head unload time.
- 7c3f = Head load time and DMA mode flag.
- 7c40 = Delay for motor turn off.
- 7c41 = Bytes per sector.
- 7c42 = Sectors per track.
- 7c43 = Intersector gap length.
- 7c44 = Data length.
- 7c45 = Intersector gap length during format.
- 7c46 = Format byte value.
- 7c47 = Head settling time.
- 7c48 = Delay until motor at normal speed.
- The 11 bytes starting at 0000:7c49 are also overlaid by the
- following data:
- 7c49 - 7c4c = diskette sector address (as LBA)
- of the data area.
- 7c4d - 7c4e = cylinder number to read from.
- 7c4f - 7c4f = sector number to read from.
- 7c50 - 7c53 = diskette sector address (as LBA)
- of the root directory.
- START: START OF BOOT SECTOR PROGRAM
- 0000:7C3E FA CLI interrupts off
- 0000:7C3F 33C0 XOR AX,AX set AX to zero
- 0000:7C41 8ED0 MOV SS,AX SS is now zero
- 0000:7C43 BC007C MOV SP,7C00 SP is now 7c00
- 0000:7C46 16 PUSH SS also set ES
- 0000:7C47 07 POP ES to zero
- The INT 1E vector is at 0000:0078.
- Get the address that the vector points to
- into the DS:SI registers.
- 0000:7C48 BB7800 MOV BX,0078 BX is now 78
- 0000:7C4B 36 SS:
- 0000:7C4C C537 LDS SI,[BX] DS:SI is now [0:78]
- 0000:7C4E 1E PUSH DS save DS:SI --
- 0000:7C4F 56 PUSH SI saves param tbl addr
- 0000:7C50 16 PUSH SS save SS:BX --
- 0000:7C51 53 PUSH BX saves INT 1E address
- Move the diskette param table to 0000:7c3e.
- 0000:7C52 BF3E7C MOV DI,7C3E DI is address of START
- 0000:7C55 B90B00 MOV CX,000B count is 11
- 0000:7C58 FC CLD clear direction
- 0000:7C59 F3 REPZ move the diskette param
- 0000:7C5A A4 MOVSB table to 0000:7c3e
- 0000:7C5B 06 PUSH ES also set DS
- 0000:7C5C 1F POP DS to zero
- Alter some of the diskette param table data.
- 0000:7C5D C645FE0F MOV BYTE PTR [DI-02],0F change head settle time
- at 0000:7c47
- 0000:7C61 8B0E187C MOV CX,[7C18] sectors per track
- 0000:7C65 884DF9 MOV [DI-07],CL save at 0000:7c42
- Change INT 1E so that it points to the
- altered Diskette param table at 0000:7c3e.
- 0000:7C68 894702 MOV [BX+02],AX change INT 1E segment
- 0000:7C6B C7073E7C MOV WORD PTR [BX],7C3E change INT 1E offset
- Call INT 13 with AX=0000, disk reset, so
- that the new diskette param table is used.
- 0000:7C6F FB STI interrupts on
- 0000:7C70 CD13 INT 13 do diskette reset call
- 0000:7C72 7279 JB TALK jmp if any error
- Detemine the starting sector address of
- the root directory as an LBA.
- 0000:7C74 33C0 XOR AX,AX AX is now zero
- 0000:7C76 3906137C CMP [7C13],AX number sectros zero?
- 0000:7C7A 7408 JZ SMALL_DISK yes
- 0000:7C7C 8B0E137C MOV CX,[7C13] number of sectors
- 0000:7C80 890E207C MOV [7C20],CX save in huge num sects
- SMALL_DISK:
- 0000:7C84 A0107C MOV AL,[7C10] number of FAT tables
- 0000:7C87 F726167C MUL WORD PTR [7C16] number of fat sectors
- 0000:7C8B 03061C7C ADD AX,[7C1C] number of hidden sectors
- 0000:7C8F 13161E7C ADC DX,[7C1E] number of hidden sectors
- 0000:7C93 03060E7C ADD AX,[7C0E] number of reserved sectors
- 0000:7C97 83D200 ADC DX,+00 number of reserved sectors
- 0000:7C9A A3507C MOV [7C50],AX save start addr
- 0000:7C9D 8916527C MOV [7C52],DX of root dir (as LBA)
- 0000:7CA1 A3497C MOV [7C49],AX save start addr
- 0000:7CA4 89164B7C MOV [7C4B],DX of root dir (as LBA)
- Determine sector address of first sector
- in the data area as an LBA.
- 0000:7CA8 B82000 MOV AX,0020 size of a dir entry (32)
- 0000:7CAB F726117C MUL WORD PTR [7C11] number of root dir entries
- 0000:7CAF 8B1E0B7C MOV BX,[7C0B] bytes per sector
- 0000:7CB3 03C3 ADD AX,BX
- 0000:7CB5 48 DEC AX
- 0000:7CB6 F7F3 DIV BX
- 0000:7CB8 0106497C ADD [7C49],AX add to start addr
- 0000:7CBC 83164B7C00 ADC WORD PTR [7C4B],+00 of root dir (as LBA)
- Read the first root dir sector into 0000:0500.
- 0000:7CC1 BB0005 MOV BX,0500 addr to read into
- 0000:7CC4 8B16527C MOV DX,[7C52] get start of address
- 0000:7CC8 A1507C MOV AX,[7C50] of root dir (as LBA)
- 0000:7CCB E89200 CALL CONVERT call conversion routine
- 0000:7CCE 721D JB TALK jmp is any error
- 0000:7CD0 B001 MOV AL,01 read 1 sector
- 0000:7CD2 E8AC00 CALL READ_SECTORS read 1st root dir sector
- 0000:7CD5 7216 JB TALK jmp if any error
- 0000:7CD7 8BFB MOV DI,BX addr of 1st dir entry
- 0000:7CD9 B90B00 MOV CX,000B count is 11
- 0000:7CDC BEE67D MOV SI,7DE6 addr of file names
- 0000:7CDF F3 REPZ is this "IO.SYS"?
- 0000:7CE0 A6 CMPSB
- 0000:7CE1 750A JNZ TALK no
- 0000:7CE3 8D7F20 LEA DI,[BX+20] addr of next dir entry
- 0000:7CE6 B90B00 MOV CX,000B count is 11
- 0000:7CE9 F3 REPZ is this "MSDOS.SYS"?
- 0000:7CEA A6 CMPSB
- 0000:7CEB 7418 JZ FOUND_FILES they are equal
- TALK:
- Display "Non-System disk..." message,
- wait for user to hit a key, restore
- the INT 1E vector and then
- call INT 19 to start boot processing
- all over again.
- 0000:7CED BE9E7D MOV SI,7D9E "Non-System disk..."
- 0000:7CF0 E85F00 CALL MSG_LOOP display message
- 0000:7CF3 33C0 XOR AX,AX INT 16 function
- 0000:7CF5 CD16 INT 16 read keyboard
- 0000:7CF7 5E POP SI get INT 1E vector's
- 0000:7CF8 1F POP DS address
- 0000:7CF9 8F04 POP [SI] restore the INT 1E
- 0000:7CFB 8F4402 POP [SI+02] vector's data
- 0000:7CFE CD19 INT 19 CALL INT 19 to try again
- SETUP_TALK:
- 0000:7D00 58 POP AX pop junk off stack
- 0000:7D01 58 POP AX pop junk off stack
- 0000:7D02 58 POP AX pop junk off stack
- 0000:7D03 EBE8 JMP TALK now talk to the user
- FOUND_FILES:
- Compute the sector address of the first
- sector of IO.SYS.
- 0000:7D05 8B471A MOV AX,[BX+1A] get starting cluster num
- 0000:7D08 48 DEC AX subtract 1
- 0000:7D09 48 DEC AX subtract 1
- 0000:7D0A 8A1E0D7C MOV BL,[7C0D] sectors per cluster
- 0000:7D0E 32FF XOR BH,BH
- 0000:7D10 F7E3 MUL BX multiply
- 0000:7D12 0306497C ADD AX,[7C49] add start addr of
- 0000:7D16 13164B7C ADC DX,[7C4B] root dir (as LBA)
- Read IO.SYS into memory at 0000:0700. IO.SYS
- is 3 sectors long.
- 0000:7D1A BB0007 MOV BX,0700 address to read into
- 0000:7D1D B90300 MOV CX,0003 read 3 sectors
- READ_LOOP:
- Read the first 3 sectors of IO.SYS
- (IO.SYS is much longer than 3 sectors).
- 0000:7D20 50 PUSH AX save AX
- 0000:7D21 52 PUSH DX save DX
- 0000:7D22 51 PUSH CX save CX
- 0000:7D23 E83A00 CALL CONVERT call conversion routine
- 0000:7D26 72D8 JB SETUP_TALK jmp if error
- 0000:7D28 B001 MOV AL,01 read one sector
- 0000:7D2A E85400 CALL READ_SECTORS read one sector
- 0000:7D2D 59 POP CX restore CX
- 0000:7D2E 5A POP DX restore DX
- 0000:7D2F 58 POP AX restore AX
- 0000:7D30 72BB JB TALK jmp if any INT 13 error
- 0000:7D32 050100 ADD AX,0001 add one to the sector addr
- 0000:7D35 83D200 ADC DX,+00 add one to the sector addr
- 0000:7D38 031E0B7C ADD BX,[7C0B] incr mem addr by sect size
- 0000:7D3C E2E2 LOOP READ_LOOP read next sector
- Leave information in the AX, BX, CX and DX
- registers for IO.SYS to use. Finally,
- jump to IO.SYS at 0070:0000.
- 0000:7D3E 8A2E157C MOV CH,[7C15] media type
- 0000:7D42 8A16247C MOV DL,[7C24] drive number
- 0000:7D46 8B1E497C MOV BX,[7C49] get start addr of
- 0000:7D4A A14B7C MOV AX,[7C4B] root dir (as LBA)
- 0000:7D4D EA00007000 JMP 0070:0000 JUMP TO 0070:0000
- MSG_LOOP:
- This routine displays a message using
- INT 10 one character at a time.
- The message address is in DS:SI.
- 0000:7D52 AC LODSB get message character
- 0000:7D53 0AC0 OR AL,AL end of message?
- 0000:7D55 7429 JZ RETURN jmp if yes
- 0000:7D57 B40E MOV AH,0E display one character
- 0000:7D59 BB0700 MOV BX,0007 video attrbiutes
- 0000:7D5C CD10 INT 10 display one character
- 0000:7D5E EBF2 JMP MSG_LOOP do again
- CONVERT:
- This routine
- converts a sector address (an LBA) to
- a CHS address. The LBA is in DX:AX.
- 0000:7D60 3B16187C CMP DX,[7C18] hi part of LBA > sectPerTrk?
- 0000:7D64 7319 JNB SET_CARRY jmp if yes
- 0000:7D66 F736187C DIV WORD PTR [7C18] div by sectors per track
- 0000:7D6A FEC2 INC DL add 1 to sector number
- 0000:7D6C 88164F7C MOV [7C4F],DL save sector number
- 0000:7D70 33D2 XOR DX,DX zero DX
- 0000:7D72 F7361A7C DIV WORD PTR [7C1A] div number of heads
- 0000:7D76 8816257C MOV [7C25],DL save head number
- 0000:7D7A A34D7C MOV [7C4D],AX save cylinder number
- 0000:7D7D F8 CLC clear carry
- 0000:7D7E C3 RET return
- SET_CARRY:
- 0000:7D7F F9 STC set carry
- RETURN:
- 0000:7D80 C3 RET return
- READ_SECTORS:
- The caller of this routine supplies:
- AL = number of sectors to read
- ES:BX = memory location to read into
- and CHS address to read from in
- memory locations 7c25 and 7C4d-7c4f.
- 0000:7D81 B402 MOV AH,02 INT 13 read sectors
- 0000:7D83 8B164D7C MOV DX,[7C4D] get cylinder number
- 0000:7D87 B106 MOV CL,06 shift count
- 0000:7D89 D2E6 SHL DH,CL shift upper cyl left 6 bits
- 0000:7D8B 0A364F7C OR DH,[7C4F] or in sector number
- 0000:7D8F 8BCA MOV CX,DX move to CX
- 0000:7D91 86E9 XCHG CH,CL CH=cyl lo, CL=cyl hi + sect
- 0000:7D93 8A16247C MOV DL,[7C24] drive number
- 0000:7D97 8A36257C MOV DH,[7C25] head number
- 0000:7D9B CD13 INT 13 read sectors
- 0000:7D9D C3 RET return
- Data not used.
- 0000:7D90 ca86e98a 16247c8a 36257ccd 13c3.... *.....$|.6%|... *
- Messages here.
- 0000:7D90 ........ ........ ........ ....0d0a * ..*
- 0000:7Da0 4e6f6e2d 53797374 656d2064 69736b20 *Non-System disk *
- 0000:7Db0 6f722064 69736b20 6572726f 720d0a52 *or disk error..R*
- 0000:7Dc0 65706c61 63652061 6e642070 72657373 *eplace and press*
- 0000:7Dd0 20616e79 206b6579 20776865 6e207265 * any key when re*
- 0000:7De0 6164790d 0a00.... ........ ........ *ady... *
- MS DOS hidden file names (first two root directory entries).
- 0000:7De0 ........ ....494f 20202020 20205359 * IO SY*
- 0000:7Df0 534d5344 4f532020 20535953 000055aa *SMSDOS SYS..U.*
- The last two bytes contain a 55AAH signature.
- 0000:7Df0 ........ ........ ........ ....55aa * U.*
- /end/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement