Windows 98 SE (Second Edition) Boot Sector


Abstract

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.

Table of Contents


Introduction

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.

Boot Record - Layout

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.

Boot Record (bootable) - Hex view

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.


BIOS Parameter Block (BPB)

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.

Selected BPB Fields for the Current Volume

Selected BPB Fields for the Current Volume
Hex Offset from
Start of Entry

Length

Value

Description
0Bh2 bytes0002 = 0200h = 512d Number of bytes per sector
0Dh1 byte08h = 8d Number of sectors per cluster
0Eh2 bytes2000 = 0020h = 32d Number of sectors in reserved area
10h1 byte02Number of copies of FAT
1Ah2 bytesFF00 = 00FFh = 255d Number of heads (sides)
1Ch4 bytes0000003Fh = 63d Number of hidden sectors
20h4 bytes00F3E7E4h = 15,984,612d Large Sectors if Small Sectors = 0
FAT32 BPB fields ONLY
24h4 bytes00003CDCh = 15,580d Sectors per FAT (FAT32 only)
28h2 bytes0000h Extended Flags (FAT32 only)
2Ch4 bytes00000002h = 2d Root Cluster Number (FAT32 only)
30h2 bytes0001h File System Information Sector Number (FAT32 only)
Extended BPB Fields for FAT32 Volumes
43h4 bytesDA112D46 = 462D11DAh Volume serial number
47h11 bytesDISK1PART00Volume label

Extended Flags (FAT32 only)

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.

Bits0-3--Zero-based number of active FAT. Only valid if mirroring is disabled.
Bits4-6--Reserved.
Bit7--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.
Bits8-15--Reserved.

Root Cluster Number (FAT32 only)

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.

File System Information Sector Number (FAT32 only)

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.

FAT32 FSInfo Sector Structure

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.

FAT32 FSInfo Sector Structure
NameHex Offset from
Start of Sector
Size
in bytes
Description
FSI_LeadSig04Value 0x41615252. This lead signature is used to validate that this is in fact an FSInfo Sector
FSI_Reserved14480This 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_StrucSig1E44Value 0x61417272. Another signature that is more localized in the sector to the location of the fields that are used.
FSI_Free_Count1E84Contains 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_Free1EC4This 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_Reserved21F012This 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_TrailSig1FC4Value 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.

FAT32 Root Directory Structure

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.

Directory Entry Fields
Hex Offset from
Start of Entry
Name Size (bytes)Description
00hDIR_Name8Filename (ASCII characters)
08hDIR_Ext3Filename extension (ASCII characters)
0BhDIR_Attr1Attribute byte (Bit coded)
0ChDIR_NTRes1Reserved for use by Windows NT
0DhDIR_CrtTimeTenth1Millisecond stamp at file creation time (tenths of a second).
0EhDIR_CrtTime2Time file was created
10hDIR_CrtDate2Date file was created
12hDIR_LstAccDate2Last Access Date
14hDIR_FstClusHI2High word of the starting cluster number
16hDIR_WrtTime2Time of last write
18hDIR_WrtDate2Date of last write
1AhDIR_FstClusLO2Low word of the starting cluster number
1ChDIR_FileSize4File size as 32-bit DWord

Filename and extension

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.

Attribute

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 fields of the Attribute byte
BitMeaning
7654321 0
....... 1Read-only
......1 .Hidden
.....1. .System
....1.. .Volume label
...1... .Subdirectory
..1.... .Archive
.1..... .Unused
1...... .Unused

First Cluster High

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).

First Cluster Low

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).

File Size

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.

FAT32

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.

FAT32 Entries

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.

Special Values

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).

Reserved FAT32 Entries

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.

Boot Record - Program

Overview of Boot Program

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.

  1. Save address of Diskette Parameter Table (DPT) pointed to by INT 1Eh.
  2. Change INT 1E so that it will point to the altered DPT at 0000:0522.
  3. Copy DPT to 0000:0522.
  4. Alter the copy of the Diskette Parameter Table.
  5. If fixed disk, read MBR and fetch System Indicator for current partition.
  6. Load next 2 boot sectors into memory location 0000:7E00 (ending at 0000:81FF)
  7. Continue execution at memory location 0000:8000 since the FSInfo Sector occupies memory locations 0000:7E00 to 0000:7FFF. The FSInfo area will be overwritten by the program, which uses it as temporary storage for FAT sectors when following the root directory cluster chain.

This will now cover program execution starting at memory location 0000:8000.

  1. Compute start address of first cluster as LBA.
  2. Check that the Root Cluster # from BPB is valid.
  3. Determine LBA address of the root directory cluster.
    1. Read next sector of root directory (16 entries if no LFNs).
    2. Look for IO.SYS entry in current sector of root directory.
    3. If found go to step 4.
    4. If unread sectors in current cluster, loop to step 3a.
    5. Else compute LBA address and sector offset of FAT entry for current cluster
      Note that each FAT entry is 4 bytes so we need to know which sector and then where (the offset) in the sector the entry is located.
    6. Load FAT sector into memory location 7E00.
    7. If READ error, display "Disk I/O error" and stop.
    8. Extract 4-byte number from FAT entry offset.
    9. Mask high 4 bits to produce next cluster number of root directory.
    10. If end of root directory, display "Invalid system disk" and stop.
    11. Else loop back to step 3.
  4. Extract the Starting cluster # of IO.SYS from the root directory entry.
  5. Check that the Starting cluster # is valid.
  6. If invalid cluster number, display "Invalid system disk" and stop.
  7. Else compute LBA address of the Starting cluster of IO.SYS.
  8. Load the first 4 sectors of IO.SYS into memory location 0000:0700.
  9. Valid IO.SYS file must have "MZ" at offset 0 and "BJ" at offset 200.
  10. If not valid IO.SYS file, display "Invalid system disk" and stop.
  11. Else continue execution at offset 200 in IO.SYS.

Disassembly of Additional Boot Code

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

Final Step in Boot Process

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.

On Line References

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.


MBR/Boot Index

Home Page

This page was created on 5 May 2001, last updated on 19 March 2010.