An
Examination of the
NTFS Volume Boot Record
Of Microsoft® Windows™ 2000
(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! |
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 the “boot 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! |
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 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 |
Decimal |
Description |
|
0Bh |
Word |
0200 |
512 |
Sector
Size (in bytes) |
|
" 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 |
|
|
" 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." |
||||
|
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. |
|
16h |
2
Bytes |
0000 |
N/A |
Must be set to zero for NTFS volumes (originally for FAT12/16 "Sectors
per FAT" value). |
|
18h |
Word |
|
63 |
Sectors
per Track |
|
1Ah |
Word |
00FF |
255 |
Number
of Heads (Sides) |
|
1Ch |
|
63 |
Number
of Hidden |
|
|
"
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. Is it safe to change this value for booting a Windows OS? & Can Win 2000/XP boot from an Extended partition? |
||||
|
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 |
An NTFS
OS always |
|
|
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 |
00000000 |
14,105,006 |
Total Sectors |
|
|
As we mentioned
above, this value will always be 1 sector less than the total number |
||||
|
30h |
Long |
00000000 |
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 |
00000000 |
61,325 |
Starting
Cluster Number for the $MFTMirror File in this partition. |
|
40h |
Signed |
000000F6 |
-10 => |
Clusters
(or bytes) per |
|
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: |
||||
|
44h |
Double |
00000001 |
1 |
Clusters per Index Block (or Record). |
|
An Index Record is used by
NTFS structures such as a Directory. |
||||
|
48h |
Long |
B4A4E199 |
- |
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: It is interesting to note how the (3rd and 4th) and
(6th and 7th) bytes repeat here! |
|||
|
50h |
Double |
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 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 (
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
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
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
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
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
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 7DA0 0D 0A 4E 54 7DB0 6E 67 00 0D 0A
4E 54 7DC0 6D 70 72 65 73 73 65 64 00 0D 0A
50 72 65 73 73 mpressed...Press 7DD0 20 43 74 72 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
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