This is a continuation of Windows 95b Boot Sector which discussed the boot sector from a PC running Windows 95 OSR2. This page will focus on Windows 98 SE (Second Edition) and the additional boot sectors, including disassembly of the program code as well as pertinent topics not previously addressed.
The boot code in the first boot sector of Windows 98 SE is identical to that in the first boot sector of Windows 95 (OSR2). Since the additional boot sectors were only mentioned and not discussed in detail in Windows 95b Boot Sector, this document will concentrate on these additional sectors.
The boot sectors shown here were acquired from a new hard drive with a virgin installation of the retail version of Windows 98SE using 32-bit FAT on a Maxtor 30GB hard drive on 23 April 2001. Both Windows 98SE and the hard drive were bought new just previous to the installation.
Three partitions were created, a primary partition of 8184 MB using a 4 KB cluster size, and an extended partition with two logical partitions. The first logical partition was 8184 MB using 4 KB clusters and the second was 14353 MB using 8 KB clusters.
The entire first track (63 sectors) was examined. The first 3 sectors on the track contain the OS boot code, the next 3 sectors contain all 0's, the next 3 sectors (7th-9th) are a duplicate of the first 3 sectors with the exception of 4 bytes (bytes 488-491 in the second sector of each group). The next 23 sectors contain all 0's. The last 31 sectors contain the beginning of the first FAT. This makes a total of 63 sectors/track.
Go back to the Table of Contents.
The boot record now occupies the first 6 sectors of the volume though only the first 3 sectors contain non zero values (and are officially considered the boot record by Microsoft). There is a copy of the boot record in the next 6 sectors. The next 20 sectors contain all zero values but are still part of the reserved area and could be used for expansion.
The first sector of each boot record contains part of the boot code as well as the BPB and EBPB structures. The second sector of each boot record does not contain boot code but is occupied by the FAT32 FSInfo Sector Structure. The third sector of each boot record contains the remainder of the boot code. The only difference between the two copies of the boot record is the FSI_Free_Count value (4 bytes) in the FSInfo structure. In each of these sectors the signature (0xAA55) must occupy the last two bytes. (Actually this is only true for 512 byte sectors, for larger sectors it still must be found at byte locations 511 and 512.)
The layout of the first sector is as follows:
The offsets given below are from the beginning of the track on which the boot sectors reside. The first 3 sectors comprising the boot sector code are reproduced below. Since the backup boot sector is nearly identical, only the differences will be mentioned. That is to say, bytes at locations 000000 to 0005F0 are identical to those at locations 000C00 to 001100 with the exception that bytes at locations 0003E8 to 0003EB differ from those at locations 000FE8 to 000FEB.
OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
----------------------------------------------------------------------------
000000 EB 58 90 4D 53 57 49 4E - 34 2E 31 00 02 08 20 00 .X.MSWIN4.1... .
000010 02 00 00 00 00 F8 00 00 - 3F 00 FF 00 3F 00 00 00 ........?...?...
000020 E4 E7 F3 00 DC 3C 00 00 - 00 00 00 00 02 00 00 00 ................
000030 01 00 06 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
000040 80 00 29 DA 11 2D 46 44 - 49 53 4B 31 50 41 52 54 ..)..-FDISK1PART
000050 30 30 46 41 54 33 32 20 - 20 20 FA 33 C9 8E D1 BC 00FAT32 .3....
000060 F8 7B 8E C1 BD 78 00 C5 - 76 00 1E 56 16 55 BF 22 .{...x..v..V.U."
000070 05 89 7E 00 89 4E 02 B1 - 0B FC F3 A4 8E D9 BD 00 ..~..N..........
000080 7C C6 45 FE 0F 8B 46 18 - 88 45 F9 38 4E 40 7D 25 |.E...F..E.8N@}%
000090 8B C1 99 BB 00 07 E8 97 - 00 72 1A 83 EB 3A 66 A1 .........r...:f.
0000A0 1C 7C 66 3B 07 8A 57 FC - 75 06 80 CA 02 88 56 02 .|f;..W.u.....V.
0000B0 80 C3 10 73 ED BF 02 00 - 83 7E 16 00 75 45 8B 46 ...s.....~..uE.F
0000C0 1C 8B 56 1E B9 03 00 49 - 40 75 01 42 BB 00 7E E8 ..V....I@u.B..~.
0000D0 5F 00 73 26 B0 F8 4F 74 - 1D 8B 46 32 33 D2 B9 03 _.s&..Ot..F23...
0000E0 00 3B C8 77 1E 8B 76 0E - 3B CE 73 17 2B F1 03 46 .;.w..v.;.s.+..F
0000F0 1C 13 56 1E EB D1 73 0B - EB 27 83 7E 2A 00 77 03 ..V...s..'.~*.w.
000100 E9 FD 02 BE 7E 7D AC 98 - 03 F0 AC 84 C0 74 17 3C ....~}.......t..
000110 FF 74 09 B4 0E BB 07 00 - CD 10 EB EE BE 81 7D EB .t............}.
000120 E5 BE 7F 7D EB E0 98 CD - 16 5E 1F 66 8F 04 CD 19 ...}.....^.f....
000130 41 56 66 6A 00 52 50 06 - 53 6A 01 6A 10 8B F4 60 AVfj.RP.Sj.j...`
000140 80 7E 02 0E 75 04 B4 42 - EB 1D 91 92 33 D2 F7 76 .~..u..B....3..v
000150 18 91 F7 76 18 42 87 CA - F7 76 1A 8A F2 8A E8 C0 ...v.B...v......
000160 CC 02 0A CC B8 01 02 8A - 56 40 CD 13 61 8D 64 10 ........V@..a.d.
000170 5E 72 0A 40 75 01 42 03 - 5E 0B 49 75 B4 C3 03 18 ^r.@u.B.^.Iu....
000180 01 27 0D 0A 49 6E 76 61 - 6C 69 64 20 73 79 73 74 .'..Invalid syst
000190 65 6D 20 64 69 73 6B FF - 0D 0A 44 69 73 6B 20 49 em disk...Disk I
0001A0 2F 4F 20 65 72 72 6F 72 - FF 0D 0A 52 65 70 6C 61 /O error...Repla
0001B0 63 65 20 74 68 65 20 64 - 69 73 6B 2C 20 61 6E 64 ce the disk, and
0001C0 20 74 68 65 6E 20 70 72 - 65 73 73 20 61 6E 79 20 then press any
0001D0 6B 65 79 0D 0A 00 00 00 - 49 4F 20 20 20 20 20 20 key.....IO
0001E0 53 59 53 4D 53 44 4F 53 - 20 20 20 53 59 53 7E 01 SYSMSDOS SYS~.
0001F0 00 57 49 4E 42 4F 4F 54 - 20 53 59 53 00 00 55 AA .WINBOOT SYS..U.
FAT32 FSInfo Sector (second sector)
000200 52 52 61 41 00 00 00 00 - 00 00 00 00 00 00 00 00 RRaA............
000210 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
...... All 0's ................
0003D0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0003E0 00 00 00 00 72 72 41 61 - 47 05 1C 00 02 00 00 00 ....rrAaG.......
0003F0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 55 AA ..............U.
Additional program code (third sector)
000400 FA 66 0F B6 46 10 66 8B - 4E 24 66 F7 E1 66 03 46 .f..F.f.N$f..f.F
000410 1C 66 0F B7 56 0E 66 03 - C2 33 C9 66 89 46 FC 66 .f..V.f..3.f.F.f
000420 C7 46 F8 FF FF FF FF FA - 66 8B 46 2C 66 83 F8 02 .F......f.F,f...
000430 0F 82 CF FC 66 3D F8 FF - FF 0F 0F 83 C5 FC 66 0F ....f=........f.
000440 A4 C2 10 FB 52 50 FA 66 - C1 E0 10 66 0F AC D0 10 ....RP.f...f....
000450 66 83 E8 02 66 0F B6 5E - 0D 8B F3 66 F7 E3 66 03 f...f..^...f..f.
000460 46 FC 66 0F A4 C2 10 FB - BB 00 07 8B FB B9 01 00 F.f.............
000470 E8 BE FC 0F 82 AA FC 38 - 2D 74 1E B1 0B 56 BE D8 .......8-t...V..
000480 7D F3 A6 5E 74 19 03 F9 - 83 C7 15 3B FB 72 E8 4E }..^t......;.r.N
000490 75 D6 58 5A E8 66 00 72 - AB 83 C4 04 E9 64 FC 83 u.XZ.f.r.....d..
0004A0 C4 04 8B 75 09 8B 7D 0F - 8B C6 FA 66 C1 E0 10 8B ...u..}....f....
0004B0 C7 66 83 F8 02 72 3B 66 - 3D F8 FF FF 0F 73 33 66 .f...r;f=....s3f
0004C0 48 66 48 66 0F B6 4E 0D - 66 F7 E1 66 03 46 FC 66 HfHf..N.f..f.F.f
0004D0 0F A4 C2 10 FB BB 00 07 - 53 B9 04 00 E8 52 FC 5B ........S....R.[
0004E0 0F 82 3D FC 81 3F 4D 5A - 75 08 81 BF 00 02 42 4A ..=..?MZu.....BJ
0004F0 74 06 BE 80 7D E9 0E FC - EA 00 02 70 00 03 C0 13 t...}......p....
000500 D2 03 C0 13 D2 E8 18 00 - FA 26 66 8B 01 66 25 FF .........&f..f%.
000510 FF FF 0F 66 0F A4 C2 10 - 66 3D F8 FF FF 0F FB C3 ...f....f=......
000520 BF 00 7E FA 66 C1 E0 10 - 66 0F AC D0 10 66 0F B7 ..~.f...f....f..
000530 4E 0B 66 33 D2 66 F7 F1 - 66 3B 46 F8 74 44 66 89 N.f3.f..f;F.tDf.
000540 46 F8 66 03 46 1C 66 0F - B7 4E 0E 66 03 C1 66 0F F.f.F.f..N.f..f.
000550 B7 5E 28 83 E3 0F 74 16 - 3A 5E 10 0F 83 A4 FB 52 .^(...t.:^.....R
000560 66 8B C8 66 8B 46 24 66 - F7 E3 66 03 C1 5A 52 66 f..f.F$f..f..ZRf
000570 0F A4 C2 10 FB 8B DF B9 - 01 00 E8 B4 FB 5A 0F 82 .............Z..
000580 9F FB FB 8B DA C3 00 00 - 00 00 00 00 00 00 00 00 ................
000590 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005A0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005B0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005C0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005D0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005E0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0005F0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 55 AA ..............U.
Sectors 4 to 6
000600 to 000BFF contain all 0's
Sectors 7 to 9 (Second copy of boot record)
000C00
} Identical to rows 000000 to 0003D0 above
000FD0
000FE0 00 00 00 00 72 72 41 61 - FF FF FF FF 02 00 00 00 ....rrAa........
0010F0
} Identical to rows 0003F0 to 0005F0 above
0011F0
Go back to the Table of Contents.
Since the BPB was discussed in Windows 95b Boot Sector only the differences in values and those used in the boot program will be listed. Some of the fields used in the boot program will be discussed in more detail.
| Hex Offset from Start of Entry | Length |
Value | Description |
|---|---|---|---|
| 0Bh | 2 bytes | 0002 = 0200h = 512d | Number of bytes per sector |
| 0Dh | 1 byte | 08h = 8d | Number of sectors per cluster |
| 0Eh | 2 bytes | 2000 = 0020h = 32d | Number of sectors in reserved area |
| 10h | 1 byte | 02 | Number of copies of FAT |
| 1Ah | 2 bytes | FF00 = 00FFh = 255d | Number of heads (sides) |
| 1Ch | 4 bytes | 0000003Fh = 63d | Number of hidden sectors |
| 20h | 4 bytes | 00F3E7E4h = 15,984,612d | Large Sectors if Small Sectors = 0 |
| FAT32 BPB fields ONLY | |||
| 24h | 4 bytes | 00003CDCh = 15,580d | Sectors per FAT (FAT32 only) |
| 28h | 2 bytes | 0000h | Extended Flags (FAT32 only) |
| 2Ch | 4 bytes | 00000002h = 2d | Root Cluster Number (FAT32 only) |
| 30h | 2 bytes | 0001h | File System Information Sector Number (FAT32 only) |
| Extended BPB Fields for FAT32 Volumes | |||
| 43h | 4 bytes | DA112D46 = 462D11DAh | Volume serial number |
| 47h | 11 bytes | DISK1PART00 | Volume label |
This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Found at offset 28h in the BPB and is 2 bytes in size.
| Bits | 0-3 | -- | Zero-based number of active FAT. Only valid if mirroring is disabled. |
| Bits | 4-6 | -- | Reserved. |
| Bit | 7 | -- | 0 means the FAT is mirrored at runtime into all FATs. |
| -- | 1 means only one FAT is active; it is the one referenced in bits 0-3. | ||
| Bits | 8-15 | -- | Reserved. |
Found at offset 2Ch, this 4-byte field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. This is set to the cluster number of the first cluster of the root directory, usually 2 but not required to be 2. Will almost always be the first non-bad cluster on the drive though this allows the root directory to be placed anywhere.
Found at offset 30h, this 2-byte field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. (Sector numbers listed in the BPB start at 0, so sector 1 is the second sector in the volume. Same as DOS logical sector numbering.) NOTE: There will be a copy of the FSINFO structure in BackupBoot, but only the copy pointed to by this field will be kept up to date (i.e., both the primary and backup boot record will point to the same FSINFO sector).
Go back to the Table of Contents.
This structure is pointed to in offset 30h of the BPB. Both the primary and backup boot record will point to the same FSINFO sector. Only the copy pointed to by this field will be kept up to date, which accounts for the differences between the 2 boot records noted above.
The following information is taken from the Microsoft document FAT32 File System Specification which is listed in On Line References below.
| Name | Hex Offset from Start of Sector | Size in bytes |
Description |
|---|---|---|---|
| FSI_LeadSig | 0 | 4 | Value 0x41615252. This lead signature is used to validate that this is in fact an FSInfo Sector |
| FSI_Reserved1 | 4 | 480 | This field is currently reserved for future expansion. FAT32 format code should always initialize all bytes of this field to 0. Bytes in this field must currently never be used. |
| FSI_StrucSig | 1E4 | 4 | Value 0x61417272. Another signature that is more localized in the sector to the location of the fields that are used. |
| FSI_Free_Count | 1E8 | 4 | Contains the last known free cluster count on the volume. If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. Any other value can be used, but is not necessarily correct. It should be range checked at least to make sure it is <= volume cluster count. |
| FSI_Nxt_Free | 1EC | 4 | This is a hint for the FAT driver. It indicates the cluster number at which the driver should start looking for free clusters. Because a FAT32 FAT is large, it can be rather time consuming if there are a lot of allocated clusters at the start of the FAT and the driver starts looking for a free cluster starting at cluster 2. Typically this value is set to the last cluster number that the driver allocated. If the value is 0xFFFFFFFF, then there is no hint and the driver should start looking at cluster 2. Any other value can be used, but should be checked first to make sure it is a valid cluster number for the volume. |
| FSI_Reserved2 | 1F0 | 12 | This field is currently reserved for future expansion. FAT32 format code should always initialize all bytes of this field to 0. Bytes in this field must currently never be used. |
| FSI_TrailSig | 1FC | 4 | Value 0xAA550000. This trail signature is used to validate that this is in fact an FSInfo sector. Note that the high 2 bytes of this value - which go into the bytes at offsets 1FE and 1FF - match the signature bytes used at the same offsets in sector 0. |
Go back to the Table of Contents.
Since the boot program looks through the root directory entries for the file IO.SYS, this section will focus on the structure of the root directory entries. This has changed from that used for FAT16 where the 10 bytes starting at hex offset 0Ch were reserved and normally set to 0. Not all of the fields are discussed here. See the Microsoft document FAT32 File System Specification, which is listed in On Line References below, pp. 22-25 for more details.
All directory entries are 32 bytes in length. This results in 16 directory entries per sector. When long filenames (LFNs) are used, several entries may be utilized for a single file. Short filenames use only one entry per file.
| Hex Offset from Start of Entry | Name | Size (bytes) | Description |
|---|---|---|---|
| 00h | DIR_Name | 8 | Filename (ASCII characters) |
| 08h | DIR_Ext | 3 | Filename extension (ASCII characters) |
| 0Bh | DIR_Attr | 1 | Attribute byte (Bit coded) |
| 0Ch | DIR_NTRes | 1 | Reserved for use by Windows NT |
| 0Dh | DIR_CrtTimeTenth | 1 | Millisecond stamp at file creation time (tenths of a second). |
| 0Eh | DIR_CrtTime | 2 | Time file was created |
| 10h | DIR_CrtDate | 2 | Date file was created |
| 12h | DIR_LstAccDate | 2 | Last Access Date |
| 14h | DIR_FstClusHI | 2 | High word of the starting cluster number |
| 16h | DIR_WrtTime | 2 | Time of last write |
| 18h | DIR_WrtDate | 2 | Date of last write |
| 1Ah | DIR_FstClusLO | 2 | Low word of the starting cluster number |
| 1Ch | DIR_FileSize | 4 | File size as 32-bit DWord |
The first 11 bytes of each entry consist of the filename and extension in ASCII format. The first byte of the filename can also be used to denote special situations. If the first byte is 00h, this indicates an unused entry and the first unused entry marks the end of the directory entries (utilized by boot program). If the first byte is E5h, this indicates that the entry has been deleted and can be reused (exploited by undelete programs). Filenames shorter than 8 bytes and extensions shorter than 3 bytes are filled to the right with blanks. Long filenames are not pertinent to the boot code and are not discussed here.
The attribute byte is encoded as shown in the following chart. According to Microsoft the upper two bits of the attribute byte are reserved and should always be set to 0 when a file is created and never modified or looked at after that. For long filenames the low 4 bits are all set to 1. (Not used in boot program)
| Bit | Meaning | |||||||
|---|---|---|---|---|---|---|---|---|
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| . | . | . | . | . | . | . | 1 | Read-only |
| . | . | . | . | . | . | 1 | . | Hidden |
| . | . | . | . | . | 1 | . | . | System |
| . | . | . | . | 1 | . | . | . | Volume label |
| . | . | . | 1 | . | . | . | . | Subdirectory |
| . | . | 1 | . | . | . | . | . | Archive |
| . | 1 | . | . | . | . | . | . | Unused |
| 1 | . | . | . | . | . | . | . | Unused |
High word of the starting cluster number. FAT32 cluster numbers are 32 bits in length (actually 28, see FAT32 Entries below) whereas in FAT16, cluster numbers are only 16 bits and do not use this part of the entry. (Used in boot program).
Low word of the starting cluster number for FAT32 cluster numbers. FAT16 cluster numbers use only this Word for the address of the starting cluster. (Used in boot program).
32-bit DWord containing the size of the file in bytes. Same as for FAT16. (Used in boot program).
Go back to the Table of Contents.
Files on a disk are not usually stored in a contiguous area. Each file (and directory) is stored as a series of blocks called clusters. Each cluster is fixed in size, at an integer number of sectors, and a file could consist of several clusters. Since these clusters may not be contiguous it is the job of the FAT to keep track of the chain of clusters for each file. These clusters occupy the space immediately after the last copy of the FAT. The FAT consists of a series of 4-byte values and is found immediately after the reserved area. These 4-byte values are numbered sequentially starting at 0 with each one corresponding to the same numbered cluster and containing the number of the next cluster number in the chain which is also the same number as the next FAT entry. For examples see Windows 98SE, FAT32 Example which also contains a portion of the FAT for the hard drive discussed here.
A FAT32 FAT entry is actually only a 28-bit number. The high 4 bits of each 32-bit entry are reserved. These high 4 bits should be preserved by any program that writes to the FAT. This is also why the boot program masks these high 4 bits when working with a FAT entry.
Some values for a FAT32 entry are reserved for special use. The value 0x0FFFFFF7 usually marks a cluster as bad. The value 0x00000000 indicates that the cluster is free. Since the high 4 bits are not part of the number, the values 0x30000000 and 0xF0000000 would both indicate that the cluster is free. Any 28-bit values >= 0x0FFFFFF8 are considered to be an EOC (End Of Clusterchain) mark and indicate the last cluster of the file. (Boot sector program looks for this EOC mark).
Cluster numbers start at 2, not 0. The corresponding FAT32 entries, the first two, contain special values. The first entry contains the Media Descriptor byte (0xF8 for fixed disks) in the low 8 bits and all other bits (of the 28 bit number) are set to 1. For the present hard drive the first FAT entry is: 0x0FFFFFF8. The second reserved FAT entry is set to the EOC mark, 0x0FFFFFFF.
Go back to the Table of Contents.
From Disassembly of Boot Program concerning the Windows 95 OSR2 Boot Sector, we have the following overview of the first sector. See that reference for detailed code which will not be repeated here since the code in the first sector is identical in both versions.
The MBR code loads the boot sector into memory location 0000:7C00 and uses a RET instruction to transfer execution to the boot sector code.
This will now cover program execution starting at memory location 0000:8000.
Note that the Transfer buffer in READ_LOOP mentioned below is just the memory location where the sectors that are read from disk will be loaded. The BPB (BIOS Parameter Block) is found at memory locations 7C03 to 7C59 and since BP points to 7C00, references [BP+0B] to [BP+2C] refer to entries in the BPB.
The program uses two memory locations for temporary storage; [BP-04] is the LBA address of the first cluster (Cluster #2) which is the beginning of the data area (considered here as the area immediately following the last copy of the FAT) and [BP-08] is the current FAT sector number, initialized to FFFFFFFF (which is not a valid sector number). Previously the Root Directory was fixed in size and located after the last FAT and then came the data area but this distinction is lost under FAT32.
See Disassembly of Boot Program concerning the Windows 95 OSR2 boot code for the previous portion of the following program code.
CONTINUE: CONTINUATION OF BOOT CODE AT 0000:8000
0:8000 FA CLI disable interrupts (turn off)
0:8001 660FB64610 MOVZX EAX,Byte Ptr [BP+10] set EAX = # copies of FAT
0:8006 668B4E24 MOV ECX,DWord Ptr [BP+24] set ECX = # Sectors per FAT
0:800A 66F7E1 MUL ECX EAX = EAX * ECX = Total FAT sectors
0:800D 6603461C ADD EAX,DWord Ptr [BP+1C] Add # of hidden sectors to EAX
0:8011 660FB7560E MOVZX EDX,Word Ptr [BP+0E] set EDX = # of sectors in reserved area
0:8016 6603C2 ADD EAX,EDX EAX = start address of data area as LBA
0:8019 33C9 XOR CX,CX set CX to zero
0:801B 668946FC MOV DWord Ptr [BP-04],EAX save EAX in [BP-04]
0:801F 66C746F8FFFFFFFF MOV DWord Ptr [BP-08],FFFFFFFF initialize [BP-08] to FFFFFFFF
0:8027 FA CLI clear interrupts (turn off)
0:8028 668B462C MOV EAX,DWord Ptr [BP+2C] set EAX = Root Cluster # (FAT32 only)
0:802C 6683F802 CMP EAX,+02 if Root Cluster # < 2 then
0:8030 0F82CFFC JB 7D03 jmp to NOT_FAT32:
0:8034 663DF8FFFF0F CMP EAX,0FFFFFF8 if Root Cluster # >= EOC mark then
0:803A 0F83C5FC JNB 7D03 jmp to NOT_FAT32:
0:803E 660FA4C210 SHLD EDX,EAX,10 set DX = high word of EAX
0:8043 FB STI enable interrupts (turn on)
ROOT_DIR: Determine LBA address of the root directory cluster (jmp from 8097).
0:8044 52 PUSH DX save DX = high Word of Root Cluster #
0:8045 50 PUSH AX save AX = low Word of Root Cluster #
0:8046 FA CLI disable interrupts (turn off)
0:8047 66C1E010 SHL EAX,10 set EAX = DX:AX by
0:804B 660FACD010 SHRD EAX,EDX,10 using two shift operations
0:8050 6683E802 SUB EAX,+02 Cluster numbers start at 2
0:8054 660FB65E0D MOVZX EBX,Byte Ptr [BP+0D] set EBX = # of sectors per cluster
0:8059 8BF3 MOV SI,BX set SI = # of sectors per cluster
0:805B 66F7E3 MUL EBX convert Root Cluster # to sectors
0:805E 660346FC ADD EAX,DWord Ptr [BP-04] EAX = root dir cluster as LBA
0:8062 660FA4C210 SHLD EDX,EAX,10 set AX and DX for LBA in READ_LOOP
0:8067 FB STI enable interrupts (turn on)
READ_DIR: Read next sector of root directory (16 entries) (jmp from 8090).
0:8068 BB0007 MOV BX,0700 address of Transfer buffer (Low Word)
0:806B 8BFB MOV DI,BX DI points to beginning of Transfer buffer
0:806D B90100 MOV CX,0001 set CX = 1 = # of sectors to read
0:8070 E8BEFC CALL 7D31 CALL READ_LOOP (read next sector of Root Dir)
0:8073 0F82AAFC JB 7D21 if READ error, jmp to IO_ERROR:
FIND_SYS: Look for IO.SYS entry in current sector of root dir (jmp from 808D).
0:8077 382D CMP Byte Ptr [DI],CH if filename starts with 0, end of
0:8079 741E JZ 8099 Root Dir, jmp to NO_SYS:
0:807B B10B MOV CL,0B set Count = 11 (length of 8.3 filename)
0:807D 56 PUSH SI save SI = # of sectors per cluster
0:807E BED87D MOV SI,7DD8 SI points to "IO .SYS" in boot record
0:8081 F3A6 REPZ CMPSB check for filename "IO .SYS"
0:8083 5E POP SI restore SI = 8 = # of sectors per cluster
0:8084 7419 JZ 809F if IO.SYS found, jmp to LOAD_SYS:
0:8086 03F9 ADD DI,CX set DI to first byte after filename
0:8088 83C715 ADD DI,+15 set DI to beginning of next filename
0:808B 3BFB CMP DI,BX if DI still points to current dir sector
0:808D 72E8 JB 8077 jmp to FIND_SYS:
0:808F 4E DEC SI if unread sectors in current cluster
0:8090 75D6 JNZ 8068 jmp to READ_DIR: (Read next dir sector)
0:8092 58 POP AX restore AX = low Word of Root Cluster #
0:8093 5A POP DX restore DX = high Word of Root Cluster #
0:8094 E86600 CALL 80FD CALL NEXT_CLUST#: (get next dir cluster #)
0:8097 72AB JB 8044 if not EOC mark, jmp to ROOT_DIR:
NO_SYS: Could not find System file (continuation from 8097 or jmp from 8079).
0:8099 83C404 ADD SP,+04 increase Stack Pointer
0:809C E964FC JMP 7D03 jmp to NOT_FAT32:
LOAD_SYS: Load System file into memory and validate file (jmp from 8084).
0:809F 83C404 ADD SP,+04 reset Stack Pointer (for skipped POPs)
0:80A2 8B7509 MOV SI,Word Ptr [DI+09] set SI = high Word of Starting cluster #
0:80A5 8B7D0F MOV DI,Word Ptr [DI+0F] set DI = low Word of Starting cluster #
0:80A8 8BC6 MOV AX,SI set AX = SI
0:80AA FA CLI disable interrupts (turn off)
0:80AB 66C1E010 SHL EAX,10 set EAX = [SI:DI] = 32-bit
0:80AF 8BC7 MOV AX,DI Starting cluster #
0:80B1 6683F802 CMP EAX,+02 if Starting cluster # < 2
0:80B5 723B JB 80F2 jmp to BAD_FILE:
0:80B7 663DF8FFFF0F CMP EAX,0FFFFFF8 if Starting cluster # >= EOC then
0:80BD 7333 JNB 80F2 jmp to BAD_FILE:
0:80BF 6648 DEC EAX since cluster numbers start at 2,
0:80C1 6648 DEC EAX reduce EAX by 2
0:80C3 660FB64E0D MOVZX ECX,Byte Ptr [BP+0D] set ECX = # of sectors per cluster
0:80C8 66F7E1 MUL ECX EAX = 1st sector of Starting cluster #
0:80CB 660346FC ADD EAX,DWord Ptr [BP-04] EAX = start address of filename as LBA
0:80CF 660FA4C210 SHLD EDX,EAX,10 set AX and DX for LBA address
0:80D4 FB STI enable interrupts (turn on)
0:80D5 BB0007 MOV BX,0700 BX = address of Transfer buffer (Low Word)
0:80D8 53 PUSH BX save BX
0:80D9 B90400 MOV CX,0004 set CX = 4 = # of sectors to read
0:80DC E852FC CALL 7D31 CALL READ_LOOP (read 4 sectors of file)
0:80DF 5B POP BX restore BX
0:80E0 0F823DFC JB 7D21 if READ error, jmp to IO_ERROR:
0:80E4 813F4D5A CMP Word Ptr [BX],5A4D if first 2 bytes of IO.SYS <> MZ
0:80E8 7508 JNZ 80F2 jmp to BAD_FILE:
0:80EA 81BF0002424A CMP Word Ptr [BX+0200],4A42 if first 2 bytes of 2nd sector = BJ
0:80F0 7406 JZ 80F8 jmp to RUN_SYS:
BAD_FILE: Invalid file (jmp from 80B5, 80BD or 80E8).
0:80F2 BE807D MOV SI,7D80 msg = "Invalid system disk"
0:80F5 E90EFC JMP 7D06 jmp to GET_MSG:
RUN_SYS: Continue execution at offset 200 in the System file (jmp from 80F0).
0:80F8 EA00027000 JMP 0070:0200 continue execution with IO.SYS
NEXT_CLUST#: Get next cluster # of Root Dir (CALLed from 8094).
0:80FD 03C0 ADD AX,AX multiply cluster # by 4 (same as two ADDs),
0:80FF 13D2 ADC DX,DX since there are 4 bytes per FAT entry,
0:8101 03C0 ADD AX,AX to compute byte offset of FAT entry
0:8103 13D2 ADC DX,DX for current cluster
0:8105 E81800 CALL 8120 CALL FAT_ENTRY:
0:8108 FA CLI disable interrupts (turn off)
0:8109 26668B01 MOV EAX,DWord Ptr ES:[BX+DI] EAX = next cluster # from FAT entry
0:810D 6625FFFFFF0F AND EAX,0FFFFFFF mask high 4 bits of cluster #
0:8113 660FA4C210 SHLD EDX,EAX,10 set DX = high Word of cluster #
0:8118 663DF8FFFF0F CMP EAX,0FFFFFF8 check for EOC mark in cluster #
0:811E FB STI enable interrupts (turn on)
0:811F C3 RET return from CALL at 8094
FAT_ENTRY: Compute address of FAT entry for current cluster (CALLed from 8105).
0:8120 BF007E MOV DI,7E00 set DI = address to store FAT sector
0:8123 FA CLI disable interrupts (turn off)
0:8124 66C1E010 SHL EAX,10 set EAX = DX:AX = FAT byte offset
0:8128 660FACD010 SHRD EAX,EDX,10 by using two shift operations
0:812D 660FB74E0B MOVZX ECX,Word Ptr [BP+0B] set ECX = # of bytes per sector
0:8132 6633D2 XOR EDX,EDX initialize EDX to 0
0:8135 66F7F1 DIV ECX EAX = FAT Sector, EDX = Sector offset
0:8138 663B46F8 CMP EAX,DWord Ptr [BP-08] if FAT sector same as previous entry,
0:813C 7444 JZ 8182 only need offset, jmp to FAT_OFFSET:
0:813E 668946F8 MOV DWord Ptr [BP-08],EAX save current FAT sector number
0:8142 6603461C ADD EAX,DWord Ptr [BP+1C] Add # of hidden sectors to [EDX:EAX]
0:8146 660FB74E0E MOVZX ECX,Word Ptr [BP+0E] set ECX = # of sectors in reserved area
0:814B 6603C1 ADD EAX,ECX EAX = FAT Sector LBA in first FAT
0:814E 660FB75E28 MOVZX EBX,Word Ptr [BP+28] set EBX = Extended Flags = 0
0:8153 83E30F AND BX,+0F if Bits 0-3 in Ext Flags = 0, use
0:8156 7416 JZ 816E first FAT, jmp to READ_FAT:
Set parameters for alternate FAT
0:8158 3A5E10 CMP BL,Byte Ptr [BP+10] if # of active FAT >= # of copies
0:815B 0F83A4FB JNB 7D03 of FAT, jmp to NOT_FAT32:
0:815F 52 PUSH DX save DX = FAT Sector offset
0:8160 668BC8 MOV ECX,EAX set ECX = FAT Sector LBA in first FAT
0:8163 668B4624 MOV EAX,DWord Ptr [BP+24] set EAX = # Sectors per FAT
0:8167 66F7E3 MUL EBX EAX = FAT Sector in active FAT
0:816A 6603C1 ADD EAX,ECX EAX = FAT Sector LBA in active FAT
0:816D 5A POP DX restore DX = FAT Sector offset
READ_FAT: Read FAT sector for address of next Root Dir cluster (jmp from 8156).
0:816E 52 PUSH DX save DX = FAT Sector Offset
0:816F 660FA4C210 SHLD EDX,EAX,10 set DX = high Word of FAT Sector LBA
0:8174 FB STI enable interrupts (turn on)
0:8175 8BDF MOV BX,DI address of Transfer buffer (Low Word)
0:8177 B90100 MOV CX,0001 set CX = 1 = # of sectors to read
0:817A E8B4FB CALL 7D31 CALL READ_LOOP (read FAT sector)
0:817D 5A POP DX restore DX = FAT Entry Offset
0:817E 0F829FFB JB 7D21 if READ error, jmp to IO_ERROR:
FAT_OFFSET: Set BX to FAT sector offset for FAT entry (jmp from 813C).
0:8182 FB STI enable interrupts (turn on)
0:8183 8BDA MOV BX,DX set BX = DX = FAT sector Offset
0:8185 C3 RET return from CALL at 8105
It is assumed that the code basically follows the Microsoft KB article Q174018, Description of the Windows 95 Startup Process even though that article is based on the original version of Windows 95.
Go back to the Table of Contents.
For comparison with an older version of the boot sector see:
The Microsoft article "Disk Sectors Critical to Startup" contains information on both the MBR and the boot sector including details on the BPB for both FAT16 and FAT32 volumes. This article is part of Chapter 32 "Disk Concepts and Troubleshooting" in the Microsoft Windows 2000 Professional Resource Kit. Thanks to the Starman and Fons Van Assche for keeping me updated on Microsoft's changing links. (updated 7/2/03)
Also see FAT Boot Sector by Alex Verstak for a more detailed description of the boot sector BPB fields for FAT32, FAT16, and FAT12 file systems.
For more information on Interrupt 13 extensions as well as other interrupts:
The disassembly code was checked using the Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual which is part of a three-volume set that describes the architecture and programming environment of all Intel Architecture processors and can be downloaded as a PDF file.
Other Intel documents can be found through Intel's Literature Center
Additional sources of information:
Go back to the Table of Contents.
If you have comments or suggestions, email me at Ray Knights
This page was created on 5 May 2001, last updated on 2 September 2003.