An Examination of the
NTFS Volume Boot Record

Of Microsoft® Windows2000
(NT5.0) and Windows
XP (NT5.1)
[ It's also found in SPCMDCON.SYS and
other System files; see Introduction below. ]


Web Presentation and Text are Copyright©2004, 2007, 2009 by Daniel B. Sedory
NOT to be reproduced in any form without Permission of the Author !

 

Note: If something you read here is very important to you, it's best to confirm it with your own experiments; especially since the code may be changed by Microsoft at any time. This has already occurred. We refer to:
http://support.microsoft.com/kb/320397
(Windows may not start and you may receive an "NTLDR is missing" error message if Windows is not up-to-date and there are too many files in the root folder) in which you'll find out why Microsoft had to change the Boot Record code for Windows 2000 with Service Pack 4 (SP4) and Windows XP with Service Pack 2 (SP2). Note: Installing Windows XP SP2 or Windows 2000 SP4, will not correct this issue on existing volumes. To update the boot code on existing volumes, you must obtain and run the utility "bcupdate2.exe" (MD5 hash value is: "2e2ed06d9ae54c8d959a534a83284705") from Microsoft, or manually change the boot code using an updated copy. The service pack updates will only write the new boot code for new volumes; they cannot correct old volumes.

You can contact us here if you have a specific question about this page.



 

Introduction

  This page examines the NTFS Boot Record for Windows 2000 (NT5) and Windows XP (NT5.1). Although Windows 2000 and XP can both use the MS-FAT32 File System, I'd advise anyone interested in serious computing to run these operating systems in NTFS formatted partitions (rather than FAT32*) for a number of reasons. Some of those being for better performance, less wasted space and more security. One or more FAT32 partitions can also reside on the same drive if required. For example, if a drive includes a Linux partition or some other OS that cannot write to an NTFS partition, then a FAT32 partition could act as a communications buffer for sharing data with both the NTFS and Linux OSs.
[
There is, however, at least one free application that allows NTFS users to acquire files directly from a Linux partition (e.g., explore2fs by John Newbigin, http://www.chrysocome.net/explore2fs (new site) and a number of Linux versions that can read files directly from NTFS partitions by using kernel drivers from the linux-ntfs project. Unfortunately, the linux-ntfs.org website has remained damaged since about AUG 2007! You can check its earlier contents at the WayBackMachine archive. Many will probably like to review their documentation file here: ntfsdoc.pdf (Note: This is not an exhuastive paper, and it contains at least one error: We will point out below that the NTFS "Backup Boot Sector" is not part of the NTFS Volume, yet their paper incorreclty states: "Hidden at the end of the volume, is a copy of the boot sector (cluster 0)."; it's actually 1 sector beyond the end of the Volume).

But there doesn't appear to be any reliable (and simple) methods of writing files under Linux to an NTFS partition, nor any free programs for writing to Linux from Windows; that we're aware of -- beware some "demo" downloads by commercial companies which are in fact "read only". We were hopeful this dismal situation would soon change. Is the future here? We are presently testing an NTFS disk under a 64-bit Fedora Core 10 install. We used GParted 0.4.3 (with Libparted 1.8.8) to create a new NTFS formatted partition, and it used the command mkntfs -Q -v (that's mkntfs 2.0.0 with libntfs 10:0:0 from the linux-ntfs project's ntfsprogs) to do so.]
__________________
*There's one odd quirk about maintaining FAT partitions under either Windows 2000 or XP you should know about: If you delete a file directly (without sending it to the Recycle Bin; using SHIFT+DEL keys for example), it can be very difficult, if even possible, to recover that file!  For some odd reason, these OSs zero-out  the 'high bits' (upper 16 bits) of any FAT file's starting cluster number! This affects any file deleted directly that's located beyond a starting cluster of 65,535.

 

[Note: You can find copies of the Boot Record code which we are examining here, in many different Windows System files; see “Where's the Code?” for more information on the names and locations of these files.]

All of the NTFS Boot Code:

Although Microsoft's NTFS Boot Record is often described as being a single sector (see the proof below!), the truth is that it would never be able to boot up a Win 2000/XP OS without the next six sectors (so far) that comprise most of an NTFS partition's Boot Code. So, even though an NTFS partition's “Boot Record” is technically only 1 sector in length, we should never forget about the necessity of the “Bootstrap Code” which follows it. Furthermore, Microsoft states that the OS itself allocates the first 16 sectors for the boot sector and the bootstrap code1.” Thus, Microsoft could have created a bootstrap code that was more than twice the size it is now. (I wonder if there are any Assembly programmers working on a way to enhance the present bootstrap code?)

The NTFS Boot Record really is only one sector long!

We carried out an experiment which proves that only the first sector of an NTFS partition is the NTFS Boot Record: In a disk editor under real DOS, every byte of the “Bootstrap Code” for a Win XP NTFS partition (on a second drive) was filled with zero bytes! Upon booting up our Master drive's Windows 2000 OS, we found that all the files in that Win XP partition could still be accessed (both read and write) and used without any problems. So, the "Bootstrap code" really is just that: It's only used to boot up any existing OS in that partition! Even though the phrase "Boot Record" isn't very descriptive for a sector that's only used to access files in the partition, there's an historical precedent for using it this way: The first sector of every floppy disk is also called a "Boot Record" even though it will never be bootable unless you add the correct system boot files to it! You can, of course, remove most of the boot code from either the NTFS or a floppy's Boot Record, since their BPBs are the only thing that an OS needs in order to access their files!! If you look for them, you'll eventually find many floppy disks with a "Boot Record" that contains only a BPB and a very short string of code that displays a message saying that you can not boot-up with that diskette if you try to boot your system with it!

NOTE: If you create a new NTFS partition with a Win 2000/XP OS, the "Bootstrap Code" will always be appended to the Boot Record; though it might be possible to change this 'boot code,' to make it only display a message saying that the partition isn't bootable, there's no practical reason for doing so, and it might lead to serious problems if you ever tried to install a Win2000/XP OS in that partition!

 


Our examination will mostly be limited to just the code in the first sector. Once we began examining the code, we found that the “boot sector” actually loads all 15 of the remaining “bootstrap code” sectors into Memory; even though the last eight sectors are nothing but zero-bytes!

Take this link to see: The NTFS Boot Record as viewed in a Disk Editor. [ Opens in a new window, so you can refer to it later! ] Includes color-highlighting of the code, BPB, Error Messages, etc.

The NTFS Boot Record is loaded into the usual Memory location of 0000:7C00 by the MBR code (see the Windows 2000/XP MBR page for more info). Locations 7C0Bh through 7C53h are filled with the NTFS BPB (Bios Parameter Block), and the next 303 bytes (7C54h through 7D82h) contain this sector's executable code (the main program and various subroutines) which eventually load the N.T.L.D.R. (or “Bootstrap”) sectors into Memory (try not to confuse these sectors with the NTLDR file that's found in the root directory of Win NT/2000/XP/2003 OS partitions).

__________________
1
The Microsoft Windows 2000 Professional Resource Kit, Chapter 32 - Disk Concepts and Troubleshooting, section "Disk Sectors Critical to Startup" under the heading "NTFS Boot Sector" above Table 32.12.

[ Note:  Be aware that many of the Hex numbers in Microsoft's tables and even the text on this page (and others) do not use what we'd call normal Hex representation! They use the symbol "0x" in a nonstandard manner, saying for example, that: "0x3F000000" is "little-endian" for decimal 63. Although they do describe this usage (you have to look hard for it), it's still incorrect according to all programming languages (such as C or C++) that use "0x"; including Microsoft's own compilers! Preceding any value with "0x" should always mean a normal Hexadecimal number. 

For example, if you search for "0x" on this page, the first instance is: "0x55AA" in the main section "Disk Sectors Critical to Startup" in the first paragraph under "Master Boot Record" where this value is called a "signature word or end of sector marker." Yet the very next paragraph, states a disk signature may occur at offset "0x01B8"; which is inconsistent with the first instance of "0x"! If that offset was stored anywhere on a hard disk, it appears Microsoft would have written "0xB801" instead. In "Table 32.2 Partition Table Fields" in the row labeled "0x01C6" under the "Byte Offset" column, you'll find: "0x3F000000" under the "Sample Value" column along with the explanation: "The offset from the beginning of the disk to the beginning of the volume, counting by sectors."  It isn't until you finally read the notes under this table, that its author(s) state: "Numbers larger than one byte are stored in little endian format, or reverse-byte ordering. .... For example, the sample value for the Relative Sectors field in the previous table, 0x3F000000, is a little endian representation of 0x0000003F." After reading that, your very next thought should be: How are we supposed to know when it does or doesn't mean that? The symbol "0x" by itself does not indicate that. Furthermore, a portion of the note which wasn't quoted above, read: "Little endian format is a method of storing a number so that the least significant byte appears first..." and with that we certainly agree, but then their statement adds: "...in the hexadecimal number notation." In the "number notation"? This last phrase is just plain wrong! It had already been agreed that when you prepend "0x" (or append an "h") these symbols indicate hexadecimal rather than decimal-based numbers. Apparently, some Microsoft author(s) decided to make things a bit easier for themselves by using it differently, rather than considering how this might confuse their readers. The term "Little-endian" should only apply to the actual byte-order on a storage medium or in Memory. Rather than confuse people, these authors should drop the "0x" hex indicator, writing a string of bytes with or without spaces between them and let you know that's how the bytes would appear in a disk editor.

Although this insanely inconsistent usage seems to have begun only in this small part of Microsoft's world, we have found other authors copying it; usually when discussing a Boot Record's signature Word 0xAA55 (which is the only correct way to state that using "0x"). It appears the Microsoft authors writing these pages used the symbol "0x" in whatever way suited them at the moment; such as how a particular type of CPU represents a Hex number for a given length of bytes in one sentence, but then in the very next sentence, an offset for locating some byte(s) on a disk is written as a normal Hex number. Imagine the confusion if a stock analyst wrote in a tiny footnote: 'In this report, $100.00 of shares are really worth only $000.01 (1 penny); unless I decide otherwise!' then listed his inflated data that way?  Microsoft texts should not be written like Alice in Wonderland. We're supposed to be dealing with helpful facts, and Microsoft's statement about some special little-endian use of 0x only makes the material more confusing for students trying to understand it!  "0x" should only prepend pure Hex numbers (as understood by humans); independent of their storage medium's endianness! Afterall, we are human beings; there's no intel™ chip inside my brain! But even if there were, it still wouldn't know for sure when "0x" menat a "little-endian number" and when it didn't without an indicator of some kind. We don't believe this is an unreasonable expectation. We do see how such a usage might make things easier for Microsoft® to document their OS, but a standard should be followed.

So, to avoid any further confusion, all our Hex Bytes, Words, Double Words, etc. in the tables below are shown as plain Hex values (without any prepended symbols) in the columns marked "Hex Numbers"; they will be the same Hex numbers no matter which processor you use or how the number is stored in Memory or on a hard disk, unless we need to make their byte-order clear.

NOTE: Due to the confusion such pages have caused for new students in x86 Assembly classes, we've created a new page dealing with the correct way to refer to the Boot Record Signature as a hexadecimal Word on a PC: AA55H.html. ]


Although it actually makes sense in this case (after examining the code for the NTFS Boot Record), to call the first sector theboot sector” and the rest of it the “bootstrap code,” this isn't true of all operating systems. For example, the first sector of the MSWIN4.1 Boot Record's three sectors, cannot be thought of as having a separate function from the code in its third sector (so the phrase “boot sector” does not apply to the MSWIN4.1 Boot Record).

The NTFS Boot Record's “Backup Sector”

The Win 2000/XP OSs make a "backup" of each NTFS volume's Boot Record which they store in the very last sector of its partition!
[ Note: I said "partition" not volume. This is why an NTFS partition's Total Sectors count in the MBR/EBR's Partition Table is always 1 sector more than the "Total Sectors (in Volume)" count found in its Boot Record. Although the words partition and volume are often thought of as being synonymous (we may even use them as such here!), they are definitely not the same thing. ]


 


 

The NTFS Bios Parameter Block

 

"Hex Dump" of a Sample NTFS BPB:

 

        0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

 

 00B0                                   00 02 08 00 00              .....

 0010  00 00 00 00 00 F8 00 00 3F 00 FF 00 3F 00 00 00   ........?...?...

 0020  00 00 00 00 80 00 80 00 AE 39 D7 00 00 00 00 00   .........9......

 0030  04 00 00 00 00 00 00 00 8D EF 00 00 00 00 00 00   ................

 0040  F6 00 00 00 01 00 00 00 FC 5D E1 A4 99 E1 A4 B4   .........]......

 0050  00 00 00 00                                       .....

The following table describes what the values in the "Hex Dump" above mean. Offsets for each field are taken from the beginning (00h) of the Boot Record (which is located at Absolute Sector 63 for the first partition on most hard disks). Microsoft® came up with an entirely new Extended BPB for its NTFS File System. Although it does contain some fields that are used for the same items as previous versions, beginning with offset 28h those are completely cast aside in favor of the much larger (LONG LONG Word) fields that are needed by NTFS!

The
green colored fields contain data that may vary from one computer to the next, whereas, the data in the red and gray fields should never vary between NTFS Systems. The data in the yellow colored fields might possibly be different under some circumstances, but normally should remain the same as shown below:

Offset

Length

Hex
Numbers

Decimal
Equiv. or
Meaning

Description

0Bh

Word

0200

512

 Sector Size (in bytes)

Reference

    " If maximum compatibility is desired, only the value 512 should be used. There is a lot of FAT code in the world that is basically "hard wired" to 512 bytes per sector and doesn’t bother to check this field to make sure it is 512. [So]...values [other than 512] are not recommended."

0Dh

Byte

08

8

 Sectors per Cluster; so
 Cluster size here = 4 KiB

Reference

" Number of sectors per allocation unit. This value must be a power of 2 that is greater than 0. Values of 1, 2, 4, 8 are quite common."
    [
I've seen a value of 4 ( for a Windows XP partition of less than 2GB ), but a value of 8 ( for Windows 2000 and XP ) is probably the most common. ]

0Eh

Word

0000

0

 Reserved Sectors; I've never seen anything but a zero here for NTFS (does your BPB have anything else here?).

After loading into Memory, this location becomes: 7C0Eh, and it's used to store how many sectors of the Boot Record are to be read into Memory; it begins with a value of 16 (decimal) and counts down to zero. (See line: 7C6C below.)

10h

Byte

00

N/A

 Must always be zero for NTFS volumes (originally the number of  FATs for a FAT partition).

11h

2 Bytes

0000

N/A

 Must always be zero for NTFS volumes (originally the Max. Root Directory Entries under FAT12/16).

13h

2 Bytes

0000

N/A

 Most often set to zero, but not used by NTFS (orig. used for the FAT12/16 small sectors count; must be zero for FAT32).

15h

Byte

F8

"Fixed Disk"

   Media Descriptor ID.
( Win 2000/XP do not use it, but other code might so it's set to F8).

16h

2 Bytes

0000

N/A

 Must be set to zero for NTFS volumes (originally for FAT12/16 "Sectors per FAT" value).

18h

Word

003F

63

 Sectors per Track

1Ah

Word

00FF

255

 Number of Heads (Sides)

1Ch

Double Word

0000003F

63

 Number of Hidden
 Sectors (
Cyl=0 Head=0)

Reference

   " Count of hidden sectors preceding the partition that contains this [NTFS] volume. This field is generally only relevant for media visible on interrupt 0x13. This field should always be zero on media that are not partitioned. Exactly what value is appropriate is operating system specific."  [ Although I'm not exactly sure what all the implications are of this quote from Microsoft, I can tell you that this value is definitely used while reading the boot sectors into Memory! See line: 7CCF in the Subroutine below. This value is supposed to be the number of physical sectors on the disk preceding the first sector of this volume; it's obvious why the first entry in a disk's partition table has a 63 here, but it will also be a 63 for each Logical volume on a disk since each Logical volume in an Extended Partition is preceded by its own Extended MBR. So, this value varies only for an NTFS partition that is a 2nd, 3rd or 4th Primary Partition.
    Note: If you see a value of 29 (
1D hex) in this field, it's most likely because the volume was created on a Dynamic Disk.]

Is it safe to change this value for booting a Windows OS? & Can Win 2000/XP boot from an Extended partition?

20h

4 Bytes

00000000

N/A

 Most often set to zero, but not used by NTFS (originally used for the Total Number of Sectors in a FAT32 volume).

After loading into Memory ( and carrying out the instructions in the subroutine at offsets 7C7B and following ), offset 7C20h is used to store the Total Number of Sectors in the partition we're trying to boot ; see line: 7CA5 for the reference.

24h

4 Bytes

80008000

First byte:
80h
is the drive number !

An NTFS OS always
fills these bytes with:
"80008000"

According to most documentation, this area is not supposed to be used by NTFS, but after examining the code in the Boot Record, it seems clear that the first byte of these four bytes is used  to set the drive number! (See offsets: 7C7B and 7CAF).

28h

Long
Long
Word

(
8 Bytes)

00000000
00D739AE

14,105,006

Total Sectors
( in the Volume )
Read following note!

  As we mentioned above, this value will always be 1 sector less than the total number
  of sectors in the volume's partition table entry, because an NTFS "Backup Sector"
  is not considered part of the NTFS Volume.

30h

Long
Long
Word

(
8 Bytes)

00000000
00000004

4

Starting Cluster Number for the $MFT File in this partition ( Logical Sector 32; if  the Sectors per Cluster value is an  8 ).

38h

Long
Long
Word

(
8 Bytes)

00000000
0000EF8D

61,325

 Starting Cluster Number for the $MFTMirror File in this partition.

40h

Signed
(+/-)
Double
Word

000000F6

-10 =>
1024 bytes

 Clusters (or bytes) per
 File Record Segment
 (FRS).

The Number of Clusters for each MFT record, which can be a negative number when the cluster size (8 sectors in this case) is larger than the MFT File Record size! The value F6 hex (which appears as 246 decimal in many utility programs) is in fact a negative 10 (-10 decimal). However, you obviously can not have a negative number of clusters!  So, a negative number here is instead an indicator  that the record length for any MFT File Record should be: 2 to the power of (-1 times "any negative value"); which turns the result into a positive number.  For our example values above, that would be: 2 ^ (-1 x -10) = 2 ^ (10) = 1024 bytes!  This number agrees perfectly with the MFT Record sizes I've seen on real disks. It is most unfortunate that I couldn't find any official Microsoft® documentation for this, yet; and simply had to come to this conclusion as others have. The Linux-NTFS Project now has a new note (c) about this on their page for the: $Boot File .

44h

Double 
Word

00000001

1

 Clusters per Index Block (or Record).

 An Index Record is used by NTFS structures such as a Directory.

48h

Long
Long
Word

(
8 Bytes)

B4A4E199
A4E15DFC

-

NTFS Volume Serial Number.

 

 NOTE: When you use the DIR command and others inside of a CMD/DOS-box under Windows 2000/XP, it will show a Volume Serial Number composed of only the last four bytes of this Long Long Word! Example:
     C:\>dir
     Volume in drive C is Win2000
     Volume Serial Number is A4E1-5DFC
Obviously, we must look into this further to find out how all these bytes are being used by the Operating System!

 It is interesting to note how the (3rd and 4th) and (6th and 7th) bytes repeat here!
 Do you have a Serial Number where these two sets of bytes are not the same?

50h

Double 
Word

00000000

0

 Checksum.

 

 Has anyone ever seen anything other than zeros in this field? I wonder if it's ever used.



_______________
* Detailed Notes Reference:

Microsoft Extensible Firmware Initiative / FAT32 File System Specification
FAT: General Overview of On-Disk Format
Version 1.03, December 6, 2000. [This PDF Document's Information gives the title as: "FAT: General Overview of On-Disk Format" and "Microsoft" is listed as the Author with the Subject as: "FAT on disk format". The date is given as: 12/11/2000 9:51:19AM, Created by Microsoft Word 9.0 with a file size of: 168,960 bytes.]

References for just the NTFS BPB Table Entries :

This data was checked against the Information found in both:
The Microsoft Windows 2000 Professional Resource Kit, Chapter 32 - Disk Concepts and Troubleshooting, section "
Disk Sectors Critical to Startup" heading "NTFS Boot Sector" Table 32.13 "BPB and Extended BPB Fields on NTFS Volumes" and the Boot Record display field names from Power Quest's Partition Info program for Windows NT/2000/XP (PartInNT.exe; 09/16/2002 2:04AM 859,136 bytes MD5 sum: 1f74ca66c42ff49f114b8c471d3ef88a). See below for an example screenshot.


The NTFS$Boot” Sectors

   As stated above, it's been my experience that both the Windows 2000 and Windows XP Boot Record (a single sector) plus the “Bootstrap Code” consists of seven sectors beginning with the one we're examining in detail on this page. But the code itself shows that all 16 sectors of the NTFS Boot Record "area" are loaded into Memory. In NTFS file system terminology, the first 16 sectors of an NTFS partition are known as the $Boot (which occupies Clusters 0 through 1 on most systems; those with 8-sector clusters).

The Second sector always begins with the 16 Hex bytes:

05 00 4E 00 54 00 4C 00 44 00 52 00 04 00 24 00

            N       T       L       D       R                $

which is mostly Unicode for the 5 characters: NTLDR. The Third through Sixth sectors don't really have any outstanding features, and the Seventh sector ends with 138 zero bytes (300 in the original code prior to WindowsXP SP2). On a newly formatted NTFS volume, the $Boot is immediately followed by the $MFT (Master File Table) which usually contains a number of sectors full of FF bytes (often part of $Bitmap) before you can find something which is humanly intelligible! Most NTFS volumes will also contain some Metadata (system files) in the middle of the partition; such as, $MFTMirr (a backup copy of the first four $MFT records) and $LogFile (which is the NTFS journal and can be many megabytes in size). NOTE: On volumes that have had many files added and deleted, and especially those which have come close to running out of space, the Mast File Table may have been relocated.

 


 

An Examination of the Assembly Code

Here's a disassembled copy of the code (; with comments) after being loaded into memory by the MBR at 0000:7C00 (An asterisk '*' in front of any Assembly Instruction listed below means that the instruction can not be disassembled correctly by MS-DEBUG):

 

 

7C00 EB52          JMP     7C54         ; Jump over BPB (Bios Parameter

                                        ;   Block) to beginning of code.

7C02 90            NOP

 

; 7C03 thru 7C0A  'NTFS    '     8-byte OEM ID or System Name.

;

; 7C0B thru 7C53   Bios Parameter Block (BPB) See above for a detailed

;                  explanation of each parameter field in the BPB.

;                (The data here is from a different partition than the

;                 one we used for the Sample "Hex Dump" above!)

 

7C03           4E 54 46 53 20 20 20 20 00 02 04 00 00      NTFS    .....

7C10  00 00 00 00 00 F8 00 00 3F 00 FF 00 3F 00 00 00   ........?...?...

7C20  00 00 00 00 80 00 80 00 F3 90 3B 00 00 00 00 00   ..........;.....

7C30  BF F6 04 00 00 00 00 00 1E 72 07 00 00 00 00 00   .........r......

7C40  F6 00 00 00 02 00 00 00 DB 05 66 38 2B 66 38 1A   ..........f8+f8.

7C50  00 00 00 00                                       ....

 

7C54 FA            CLI                  ; Disable maskable Interrupts.

7C55 33C0          XOR     AX,AX        ; Zero out both the Accumulator

7C57 8ED0          MOV     SS,AX        ;   and Stack Segment Registers.

7C59 BC007C        MOV     SP,7C00      ; Set Stack Pointer to 0000:7C00

7C5C FB            STI                  ; Enable Interrupts again.

 

; NOTE: Since the next two instructions change the (DS) Data Segment

;       Register from 0000 to 07C0, all references below to Data offsets

;       (such as [0024]) are still to the same bytes in the BPB above!

 

7C5D B8C007        MOV     AX,07C0      ;|-> This is important to know!

7C60 8ED8          MOV     DS,AX        ;|Set DS to 7C0 hex (with Segment=

                                        ;| 07C0, an offset such as [0024]

                                        ;| is the same as 0000:7C24), then

7C62 E81600        CALL    7C7B         ;  "Get Drive Parameters" and try

                                        ;   to determine Total Sectors!

7C65 B8000D        MOV     AX,0D00      ;|

7C68 8EC0          MOV     ES,AX        ;|Set Extra Segment to D00 hex.

7C6A 33DB          XOR     BX,BX        ; Zero-out the Base Register.

 

7C6C C6060E0010    MOV     BYTE PTR [000E],10   ; 16 decimal -> 0000:7C0E

                                       ;

7C71 E85300        CALL    7CC7        ; Read all Boot Sectors into Memory

                                       ; beginning at 0D00:0000 (see below)

 

7C74 68000D      * push    0D00         ; Segment where Code Sectors were

                                        ; stored by subroutine above. 

7C77 686A02      * push    026A         ; (Offset in new Code Segment.)

 

7C7A CB            RETF                 ; Use FAR RETURN instruction to

                                        ; jump to 0D00:026A (or 0000:D26A)

                                        ; which is where execution resumes

                                        ; with the NTLDR Section!

 


; Subroutine to Calculate Total Sectors in
; the Boot Partition (using only CHS)

7C7B 8A162400      MOV     DL,[0024]    ; -> 80h (which is the First HDD)

                                        ; See BPB chart for Offset 24h.

7C7F B408          MOV     AH,08        ; Function 08h of INT13

7C81 CD13          INT     13           ; "Get Drive Parameters"

 

;            After executing INT 13 Function 08h:

;             AH = 00h and CF is cleared (set to 0) if successful.

; +-------------------------------------------------------+

; |           CH =  Low 8 bits of Maximum Cylinder Number |

; |CL (bits 7-6) = High 2 bits of    "       "       "    |

; +-------------------------------------------------------+

;  CL (bits 5-0) = Maximum Sector Number.

;             DH = Maximum   Head Number.

;             DL = Number of drives on the system.

 

7C83 7305          JNB     7C8A    ; Jump if successful, CF=0 (NoCarry)

                                   ;    we have an easy partition here!

7C85 B9FFFF        MOV     CX,FFFF ; Otherwise: Set CX = FFFFh and

7C88 8AF1          MOV     DH,CL   ;                DH = FFh which will

                                   ;   result in a count of 00FC0000h or

                                   ; 16,515,072 sectors being placed into

                                   ; [0000:7C20] and following.

7C8A 660FB6C6    * movzx   eax,dh  ; Move with Zero Extend DH -> EAX

7C8E 40            INC     AX      ; Maximum Head number + 1 = Total Heads

7C8F 660FB6D1    * movzx   edx,cl  ; CL = Maximum Sector number (bits 5-0)

7C93 80E23F        AND     DL,3F   ; Pick up only bits 5 through 0 and

7C96 F7E2          MUL     DX      ;    mutiply by the number of Heads.

                                   ; EAX now equals [Sectors * Heads].

7C98 86CD          XCHG    CL,CH   ; Put the low bits of Maximum Cylinder

                                   ; Number at the end of the CX register,

7C9A C0ED06      * shr     ch,06   ; and shift bits 7-6 of CL next to them

                                   ; so that CX now equals Max Cyl number!

7C9D 41            INC     CX      ; CX + 1 = Total Cylinders.

7C9E 660FB7C9    * movzx   ecx,cx  ; Move with Zero Extend CX -> ECX

7CA2 66F7E1      * mul     ecx     ; EAX = [Sectors * Heads] * Cylinders

                                   ;     = Total Number of Sectors.

7CA5 66A32000    * mov     [0020],eax   ; Store Total Number of Sectors

                                        ; in [0000:7C20] (4-byte Word).

7CA9 C3            RET

 

; NOTE: A 4-byte Word for Total Sectors allows for almost 2048 Binary GB!

;        ( FFFFFFFFh = 4,294,967,295 sectors = 2,199,023,255,040 bytes! )

; However, this subroutine can return a Maximum of only about 8.45 GB;

; [ 63 sectors * 255 heads * 1024 cylinders (2 + 8 bits -> 3FFh) =

; 16,450,560 sectors = 8,422,686,720 bytes (or only about 7.8 Binary GB)].

; (Also see my Disk Terms page for a reality note about a 'bug' in MS-DOS!)

; So, if there's an error in determining the Sector Count, this subroutine

; returns a count of: 63 * 256 * 1024 = 16,515,072 sectors; which is not

; really possible using only CHS notation and standard BIOS functions.


; Subroutine to test for INT13 Extensions

7CAA B441          MOV     AH,41        ; Function 41h of INT 13:

7CAC BBAA55        MOV     BX,55AA      ; (with BX = 55AAh) is a check for

                                        ;  the "Installation of the INT 13

                                        ;  BIOS Extensions" in Memory.

7CAF 8A162400      MOV     DL,[0024]    ; -> 80h (for First drive).

7CB3 CD13          INT     13

 

7CB5 720F          JB      7CC6             ; Return

7CB7 81FB55AA      CMP     BX,AA55

7CBB 7509          JNZ     7CC6             ; Return

7CBD F6C101        TEST    CL,01

7CC0 7404          JZ      7CC6             ; Return

7CC2 FE061400      INC     BYTE PTR [0014]

7CC6 C3            RET


; Subroutine to Read all 16 Sectors of Boot Code into Memory

7CC7 6660        * pushad           ; Push all "Double" Registers onto the

                                    ;  stack: EAX, ECX, EDX, EBX, original

                                    ;         ESP, EBP, ESI, and EDI.

7CC9 1E            PUSH    DS

7CCA 06            PUSH    ES

7CCB 66A11000    * mov     eax,[0010] ; "Must always be zero for NTFS!"

7CCF 6603061C00  * add     eax,[001C] ;  Number of "Hidden Sectors"

7CD4 663B062000  * cmp     eax,[0020] ;  Apparent Sectors in partition.

7CD9 0F823A00    * jb      7D17       ;  Can't have more "Hidden Sectors"

                                      ;   than the total you start with!

7CDD 1E            PUSH    DS

7CDE 666A00      * push    00000000

7CE1 6650        * push    eax

7CE3 06            PUSH    ES

7CE4 53            PUSH    BX

7CE5 6668100001  * push    00010010

     00

7CEB 803E140000    CMP     BYTE PTR [0014],00

7CF0 0F850C00    * jnz     7D00

7CF4 E8B3FF        CALL    7CAA         ; Check for Extended INT13 code.

7CF7 803E140000    CMP     BYTE PTR [0014],00

7CFC 0F846100    * jz      7D61         ; Extensions are not installed.

                                        ; -> "A disk read error..." etc.

 

7D00 B442          MOV     AH,42        ; Function 42h of INT 13:

                                        ;    " Extended Read "

7D02 8A162400      MOV     DL,[0024]    ; -> "80h" (first hard drive).

7D06 16            PUSH    SS

7D07 1F            POP     DS

7D08 8BF4          MOV     SI,SP

7D0A CD13          INT     13

 

7D0C 6658        * pop     eax

7D0E 5B            POP     BX

7D0F 07            POP     ES

7D10 6658        * pop     eax

7D12 6658        * pop     eax

7D14 1F            POP     DS

7D15 EB2D          JMP     7D44

 

7D17 6633D2      * xor     edx,edx

7D1A 660FB70E18  * movzx   ecx,word [0018]  ; [7C18] = Sectors per Track

     00

7D20 66F7F1      * div     ecx

7D23 FEC2          INC     DL

7D25 8ACA          MOV     CL,DL

7D27 668BD0      * mov     edx,eax

7D2A 66C1EA10    * shr     edx,10

7D2E F7361A00    * div     word [001A]   ; [7C1A] = Number of Heads

7D32 86D6          XCHG    DL,DH

7D34 8A162400      MOV     DL,[0024]     ; [7C24] = Hard Drive Number

7D38 8AE8          MOV     CH,AL

7D3A C0E406      * shl     ah,06

7D3D 0ACC          OR      CL,AH

7D3F B80102        MOV     AX,0201       ; Function 02h of INT 13:

7D42 CD13          INT     13            ; "Read Sector into Memory"

 

7D44 0F821900    * jb      7D61          ; -> "A disk read error..." etc.

7D48 8CC0          MOV     AX,ES

7D4A 052000        ADD     AX,0020       ; Add another 200h (512 bytes) to

7D4D 8EC0          MOV     ES,AX         ;    the Segment pointer in ES.

7D4F 66FF061000  * inc     dword [0010]    ;

7D54 FF0E0E00      DEC     WORD PTR [000E] ; Decrement the Count of how

                                           ; many Sectors are left to read

7D58 0F856FFF    * jnz     7CCB

7D5C 07            POP     ES

7D5D 1F            POP     DS

7D5E 6661        * popad

7D60 C3            RET


7D61 A0F801        MOV     AL,[01F8]   ; Contains 83h (Pointer value for

                                       ; all Languages to Message Area.)

                                       ; -> "A disk read error occurred"

7D64 E80900        CALL    7D70        ; DISPLAY MESSAGE

7D67 A0FB01        MOV     AL,[01FB]   ; Contains C9h (for English string).

                                       ; -> "Press Ctrl+Alt+Del to restart"

7D6A E80300        CALL    7D70        ; DISPLAY MESSAGE

7D6D FB            STI

7D6E EBFE          JMP     7D6E        ; Endless Loop -> Lock-up System,

                                       ;       so a reboot is necessary!

 

7D70 B401          MOV     AH,01       ; An alternate method to add 100h to

                                       ; the AX register for the Message

7D72 8BF0          MOV     SI,AX       ; Offsets in AL -> Error Messages.

7D74 AC            LODSB               ; Load Error Message strings 1 byte

                                       ;    at a time and INC SI pointer.

7D75 3C00          CMP     AL,00       ; Look for Zero-byte terminator in

                                       ;    the Error Message strings.

7D77 7409          JZ      7D82        ; Return (done)

7D79 B40E          MOV     AH,0E       ; Function 0Eh of INT 10:

                                       ; "Teletype Output" (One Character)

7D7B BB0700        MOV     BX,0007     ; (BH=Page Zero; BL=Normal display)

7D7E CD10          INT     10

7D80 EBF2          JMP 7D74            ; Do it all over again . . .

7D82 C3            RET

 

 


Location of Error Messages and
Message Offsets in Memory

 

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

7D83           0D 0A 41 20 64 69 73 6B 20 72 65 61 64      ..A disk read

7D90  20 65 72 72 6F 72 20 6F 63 63 75 72 72 65 64 00    error occurred.

7DA0  0D 0A 4E 54 4C 44 52 20 69 73 20 6D 69 73 73 69   ..NTLDR is missi

7DB0  6E 67 00 0D 0A 4E 54 4C 44 52 20 69 73 20 63 6F   ng...NTLDR is co

7DC0  6D 70 72 65 73 73 65 64 00 0D 0A 50 72 65 73 73   mpressed...Press

7DD0  20 43 74 72 6C 2B 41 6C 74 2B 44 65 6C 20 74 6F    Ctrl+Alt+Del to

7DE0  20 72 65 73 74 61 72 74 0D 0A 00 00 00 00 00 00    restart........

7DF0  00 00 00 00 00 00 00 00 83 A0 B3 C9 00 00 55 AA   ..............U.


Free Boot Record Tools

See my Free Tools page for a link to PQ's Partition Info Tools (Power Quest's Partition Information viewer will list all the fields in an NTFS Bios Parameter Block). The following is a display similar to what you'll see using PQ's Partition Info program for NT (after clicking on the "Boot Record" button):

Entries 1, 2 and 23 are in the first sector of the Boot Record, but are not part of the BPB or Extended BPB. All of the red colored boxes show entries which must be zero in order for this to be an NTFS Boot Record. Note the eight-byte Serial Number in the pink box. Although documentation from Microsoft indicates that the data in the 'white' boxes (5, 8, 14 and 15) is unused by NTFS systems, I've seen nothing but zeros and the '80 00 80 00' entry in box 15.

 

Updated: June 6, 2007 (2007.06.06).
Updated: Jan. 29, 2009 (29.01.2009); Feb. 1, 2009; Mar. 1, 2009.
Last Update: March 8, 2009 (08.03.2009).


You can write to me using this: contact page (opens in a new window).

MBR and Boot Records Index

The Starman's Realm Index Page