[ Embedded in DMADMIN.EXE,
SPCMDCON.SYS or various other
System files; see Introduction ]
Web Presentation and Text are
Copyright©2003, 2007 by Daniel B. Sedory
NOT to be reproduced in any form without Permission of the Author !
This page examines the Windows 2000 MBR code introduced in 1999 when Microsoft finally released what was supposed to be version 5.0 of their NT OS; which was still being called NT4. Instead, they renamed it to Windows 2000; most likely an effort to refocus customer recognition once again on their more solid Windows trademark rather than the "New Technology" (NT) name. This MBR code is installed on blank hard drives when Disk Management is used by a Windows 2000, XP or 2003 OS. [When dealing with Dynamic Disks, the partition type is set to 42h and the data in the Partition Table may become useless!] Note: Like all other code presented in this series, this MBR code could still be used to boot any OS on an x86 PC if it meets the conditions listed here*. |
IMPORTANT: One of the first things that any PC user should do after setting up
a new hard disk (or creating a new partition with a utility such as Partition Magic) is to make a copy of its MBR; especially if
you have more than one partition on the disk! Why? If you accidentally overwrite this sector, or are infected by a Boot sector virus,
you may never be able to access some or even all of your disk again! Even the most expensive HD utility might not correctly restore
the Partition Table of a multi-partitioned hard disk! Some advice: Save the Partition Table data on floppy disks or write it down on paper(!); it does no good to have the data you need to access your HD on the un-accessible HD itself! There are many ways you can do this... See the MBR Tools Page. Any good Disk Editor will allow you to manually enter data you've written down under an easy to use Partition Table View, or you can use Power Quest's excellent little utility program "MBRutil" (under any version of Windows!) and "MBRUTILD" (under DOS) to save the binary data to a file on a floppy diskette and later restore the MBR from the saved file. |
* | NOTE: Even though we're examining code created by a Microsoft Operating System, this MBR can also be used to start the boot process for any operating system's Boot Record on an x86-CPU based (PC) computer as long as that OS is: 1) on the Primary Master hard drive, 2) set to be the only Active partition and 3) it has a boot loader in the first sector of that partition. Most Linux OS distributions can install LILO or GRUB as a Boot Record rather than in the MBR and following sectors, so even the oldest MBR by Microsoft could still be used to boot Linux; as long as its boot code was at or under the 1024 cylinder limit that is. Furthermore, the CPU itself must be an 80286 or later in order to use the 2000/XP MBR code, since some of the opcodes (see Code below) will only run on an 80286 or later CPU. Windows NT/2000/XP can also boot multiple OSs
using their boot.ini and NTLDR files, so for systems with
multiple OSs, that would be a more practical approach than changing the Active partition in the MBR all the time. |
This page examines the MBR code most likely to be found in a Microsoft® Windows 2000, XP or 2003 installation. All of these operating systems contain the same exact MBR code embedded in files such as DMADMIN.EXE (there are a few more places we didn't list above where either the MBR code or Boot Records can be found; if you're interested in that, read our Where's the code? page). This code will be written to Cylinder 0, Head 0, Sector 1 of a Hard Drive by various OS routines, such as the Disk Management Console, if the drive does not already have an existing MBR sector (recognized by Windows®) when it is installed. [Note: These OSs will still write data to the MBR sector when required (see our Disk Signature comments below).]
For Windows XP (SP2 and SP3), the MBR code is contained inside the
file:
C:\WINNT\system32\dmadmin.exe
This file which is "224,768 bytes"
and has a Modification Date of "Wednesday, August 04, 2004, 4:00:00 AM" (for SP3: Same size, but dated
"Monday, April 14, 2008, 7:00:00 AM") is described as the "Logical Disk Manager service process" with "File version: 2600.2180.503.0" ("2600.5512.503.0" for SP3) and:
"Copyright © 1985-2000 Microsoft Corporation. All rights reserved.
Portions Copyright © 1997-2000 Veritas Software. All rights reserved."
The MBR code itself is found between offsets 34E28h through 35027h (of which only
the last 80 bytes are shown here):
Figure 1. Note that the bytes "2c 44 63"are part of the
MBR's image file in dmadmin.exe
Under the original Windows XP, the MBR code was in the same file, but at offsets 2FFF8h (196,600) through 301F7h (197,111) for its August 23, 2001 5:00:00 AM version of 204,800 bytes. And unlike the very first file under Windows 2000 [see below], its copyright was changed to: "Copyright © 1985-2000 Microsoft Corporation" and only "Portions Copyright © 1997-2000 Veritas Software"; so it appears that Veritas got an offer from Microsoft® they couldn't refuse!
For Windows 2000 (with SP3), the MBR code is contained inside the file C:\WINNT\system32\dmadmin.exe This file which is "147,728 bytes" and has a Modification Date of "Monday, July 22, 2002, 12:05:04 PM" is also described as a "Logical Disk Manager service process"; interestingly enough this file is "Copyright © VERITAS Software 1997" and not Microsoft. The MBR code itself is found between offsets 22A00h through 22BFFh (of which only the last 80 bytes are shown in this Hex editor window):
Figure 2. The bytes "2c 44 63"have always been part of this
MBR's image file for English.
The following is a disk editor view of how the bytes in this MBR are stored on your hard drive's first sector; that's Absolute (or Physical) Sector 0, or CHS 0,0,1. (See Examination of the Code below to find out where this data ends up in Memory when it's executed.)
Absolute Sector 0 (Cylinder 0, Head 0, Sector 1) 0 1 2 3 4 5 6 7 8 9 A B C D E F 0000 33 C0 8E D0 BC 00 7C FB 50 07 50 1F FC BE 1B 7C 3.....|.P.P....| 0010 BF 1B 06 50 57 B9 E5 01 F3 A4 CB BD BE 07 B1 04 ...PW........... 0020 38 6E 00 7C 09 75 13 83 C5 10 E2 F4 CD 18 8B F5 8n.|.u.......... 0030 83 C6 10 49 74 19 38 2C 74 F6 A0 B5 07 B4 07 8B ...It.8,t....... 0040 F0 AC 3C 00 74 FC BB 07 00 B4 0E CD 10 EB F2 88 ..<.t........... 0050 4E 10 E8 46 00 73 2A FE 46 10 80 7E 04 0B 74 0B N..F.s*.F..~..t. 0060 80 7E 04 0C 74 05 A0 B6 07 75 D2 80 46 02 06 83 .~..t....u..F... 0070 46 08 06 83 56 0A 00 E8 21 00 73 05 A0 B6 07 EB F...V...!.s..... 0080 BC 81 3E FE 7D 55 AA 74 0B 80 7E 10 00 74 C8 A0 ..>.}U.t..~..t.. 0090 B7 07 EB A9 8B FC 1E 57 8B F5 CB BF 05 00 8A 56 .......W.......V 00A0 00 B4 08 CD 13 72 23 8A C1 24 3F 98 8A DE 8A FC .....r#..$?..... 00B0 43 F7 E3 8B D1 86 D6 B1 06 D2 EE 42 F7 E2 39 56 C..........B..9V 00C0 0A 77 23 72 05 39 46 08 73 1C B8 01 02 BB 00 7C .w#r.9F.s......| 00D0 8B 4E 02 8B 56 00 CD 13 73 51 4F 74 4E 32 E4 8A .N..V...sQOtN2.. 00E0 56 00 CD 13 EB E4 8A 56 00 60 BB AA 55 B4 41 CD V......V.`..U.A. 00F0 13 72 36 81 FB 55 AA 75 30 F6 C1 01 74 2B 61 60 .r6..U.u0...t+a` 0100 6A 00 6A 00 FF 76 0A FF 76 08 6A 00 68 00 7C 6A j.j..v..v.j.h.|j 0110 01 6A 10 B4 42 8B F4 CD 13 61 61 73 0E 4F 74 0B .j..B....aas.Ot. 0120 32 E4 8A 56 00 CD 13 EB D6 61 F9 C3 49 6E 76 61 2..V.....a..Inva 0130 6C 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 lid partition ta 0140 62 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E ble.Error loadin 0150 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst 0160 65 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 em.Missing opera 0170 74 69 6E 67 20 73 79 73 74 65 6D 00 00 00 00 00 ting system..... 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01B0 00 00 00 00 00 2C 44 63 A8 E1 A8 E1 00 00 80 01 .....,Dc........ 01C0 01 00 07 7F BF FD 3F 00 00 00 C1 40 5E 00 00 00 ......?....@^... 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............U. 0 1 2 3 4 5 6 7 8 9 A B C D E F |
The first 300 bytes (000h through 12Bh) of this 512-byte sector are executable code and the next 80 bytes (12Ch through 17Bh) contain error messages. The last 66 bytes of the sector contain the 64-byte Partition Table (1BEh through 1FDh); data in the Table area will depend upon the size, structure and file systems on each hard disk. The sector ends with the Word-sized signature ID of AA55h (often called the sector's Magic number); on PCs using an Intel (or x86 compatible) CPU, hex Words are stored with the Low-byte first and the High-byte last.
The remaining 66 bytes (between the Error Messages and the Partition Table; 17Ch through 1BDh) begin as padding (which are first filled with all zero-bytes by Win 2000/XP); with the exception of the three bytes (2C 44 63) at 1B5h through 1B7h (described in detail below) that are actually part of the dmadmin.exe file (see Figures 1 and 2 above). However, after a drive has any of the NT-type Operating Systems installed and running, they will write a Disk Signature in the MBR. The four bytes from offsets 1B8h through 1BBh are called the Windows 2000/XP Disk Signature or NT Drive Serial Number (The digits shown in the disk editor view above are only an example and could be anything; but we've noticed a high tendency under Windows 2000/XP for the first and third and the second and fourth bytes to be the same digits, as in the example above: A8 E1 A8 E1. In other NT-type MBRs, we've observed signatures such as these: "87 04 88 04" and "6B 40 6C 40" and "84 1A 85 1A". So there's a high probability that at least the 2nd and 4th bytes will almost always be the same and that some kind of algorithm is being applied by the OS to create these digit patterns. However, we've also seen NT-type MBRs with no discernible pattern at all, such as: "ED 19 EB BF" and "80 EF A0 FB," so we have no idea exactly how these OSs 'decide' to write these kind of Disk Signature digits versus those having patterns as seen above.) See here for details on Disk Signature use in the Registry!
The three bytes at offsets 1B5h through 1B7h ("2C 44 63") are used by Microsoft Windows for a very specific purpose; for English versions of Windows 2000/XP, you'll always see these same Hex values ("2C 44 63") in the MBR. They're used by the MBR code to display Error Messages on your screen. But for those using Windows with a different language, their MBRs may have different values in the second and third bytes depending upon how many characters are in the error messages. If you look in the code section below, starting at offset 063Ah (instruction: "MOV AL,[07B5]"), you'll see these three bytes are used to reference the offset in Memory of the first byte of each Error Message that can be displayed on screen at boot up: 072Ch, 0744h and 0763h. Since the code will always be the same, the first offset (072Ch) should never change. If you had the German (Deutsch) version of Windows 2000 or XP, your error messages and message offsets would look like this:
0120 32 E4 8A 56 00 CD 13 EB D6 61 F9 C3 55 6E 67 81 2..V.....a..Ungü 0130 6C 74 69 67 65 20 50 61 72 74 69 74 69 6F 6E 73 ltige Partitions 0140 74 61 62 65 6C 6C 65 00 46 65 68 6C 65 72 20 62 tabelle.Fehler b 0150 65 69 6D 20 4C 61 64 65 6E 20 64 65 73 20 42 65 eim Laden des Be 0160 74 72 69 65 62 73 73 79 73 74 65 6D 73 00 42 65 triebssystems.Be 0170 74 72 69 65 62 73 73 79 73 74 65 6D 20 6E 69 63 triebssystem nic 0180 68 74 20 76 6F 72 68 61 6E 64 65 6E 00 00 00 00 ht vorhanden.... 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01B0 00 00 00 00 00 2C 48 6E .....,Hn 0 1 2 3 4 5 6 7 8 9 A B C D E F |
Now that you know what the bytes at offsets 1B5h through 1B7h are used for, you could change these error messages to display whatever you wish (as long as they all fit into the space between offsets 12Ch and 1B4h) by counting their character lengths and using a disk editor on the MBR sector to make the appropriate changes.
[ Note: If you ever used PhysTechSoft's old "BootWizard" program, these bytes had a completely different meaning! The first byte was an MBR checksum value, and the next two bytes were a two-byte Hex Word for what it called the structure size. Since the free Disk Editor program PTS-DE (on our Free Tools page) came from PhysTechSoft, it will display these bytes under its "Partition Table View" as if they were from the old "Boot Wizard" software; so keep that in mind if you use the PTS-Disk Editor! ]
Disk Signatures in the Registry
Searching for my Disk Signature in the Registry (both as "a8 e1 a8 e1" and
"e1 a8 e1 a8"; endianness often matters, as well as without any spaces between the bytes, taught me a valuable lesson:
You cannot trust Microsoft's Registry Editor will find all the data you search for. Why? Because much of
what is stored in the Registry is binary (hex) data, and the Registry Editor's search function cannot find binary values or REG_DWORD entries! This
is rather important for us here, because the Disk Signature of any drive connected to your PC is clearly displayed under this Key:
HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices
which also contains information (in the form of GUIDs) to
reference all logical drives ever connected to the computer! This includes removable storage such as USB devices; which may contain their actual physical
serial numbers (see: USB
Serials in Registry).
However, the Disk Signature (or NT Serial Number) as a
four-byte Hex Word ("E1A8E1A8" hex, see example Signature above) can be found with the Registry Editor in these keys:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\STORAGE\Volume
and even
HKLM\SYSTEM\ControlSet001\Control\DeviceClasses\{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
among many others. Keys using Disk Signatures contain a wealth of information about your hard disk's
partitions! For example, one of the SymbolicLink Key Name's value (that begins with \\?\STORAGE#Volume#1& )
continues as:
30a96598&0&SignatureE1A8E1A8Offset7E00Length1AE735E00#
followed by the GUID {53f5630d-b6bf-11d0-94f2-00a0c91efb8b} which you'll see in most of these key values. I'm not exactly sure how the digits in red are used, but I did find them as the Key Value for the Name
ParentIdPrefix under the Key:
HKLM\SYSTEM\CurrentControlSet\Enum\Root\ftdisk\0000.
Interpreting the Data: The "Signature " value should be obvious. The "Offset " value is the hexadecimal equivalent of the number of bytes before the beginning of this partition; thus, 7E00h is 32,256 bytes or 63 sectors (at 512 bytes/sector) which also means this is the first partition on the disk (every Basic Disk leaves the first track unused; except for the MBR sector, so its first partition always begins at CHS 0,1,1), and the "Length" value is the exact number of bytes in the whole partition (1AE735E00h = 7,221,763,584 bytes for about a 6.7 GiB partition size).
After executing the POST (Power-On Self Test), the BIOS loads this sector into memory at 0000:7C00 (as it does any MBR) then transfers control to this code.
Unlike an OS boot sector though, this code must first copy itself into another area of Memory. This is necessary because
the code must also load the Boot Sector of the Active Partition into the same area of Memory that it was first loaded into! But just as we saw
for the Windows 98 MBR, this code doesn't copy any bytes it has already executed before jumping to the new location in Memory; it copies only the 485 bytes
from 7C1Bh through 7DFFh to Memory locations 0000:061B through 0000:07FF, rather than simply copying the whole block of 512 bytes to
0000:0600 and following as the the old Standard MBR code did! For the first 25 instructions, this code is quite similar to that of a Windows 98
(FAT32) MBR, but then diverges into completely new routines.
You can learn a great deal about the instructions used here by obtaining the x86 Opcode Windows Help file and Ralf Brown's Interrupt List from our Intro to Assembly page.
Here's a Listing of the disassembled code (; with comments) after first being loaded into Memory at 0000:7C00 by the BIOS (all Memory locations listed below are in Segment 0000:). If you see an asterisk (*) next to an instruction, it means that MS-DEBUG can not disassemble that code.
7C00 33C0 XOR AX,AX ; Zero out the Accumulator and 7C02 8ED0 MOV SS,AX ; Stack Segment register. 7C04 BC007C MOV SP,7C00 ; Set Stack Pointer to 0000:7C00 7C07 FB STI ; Enable Interrupts 7C08 50 PUSH AX ; (AX=0 at this time) 7C09 07 POP ES ; Zero-out Extra Segment 7C0A 50 PUSH AX ; (AX=0 at this time) 7C0B 1F POP DS ; Zero-out Data Segment 7C0C FC CLD ; Clear Direction Flag 7C0D BE1B7C MOV SI,7C1B ; Source Index: Copy from here... 7C10 BF1B06 MOV DI,061B ; Destination Index: Copy to here: ; Code will begin at: 0000:061B 7C13 50 PUSH AX ; Set up Segment(AX) and Offset(DI) 7C14 57 PUSH DI ; for jump to 0000:061B. 7C15 B9E501 MOV CX,01E5 ; Set up Counter (CX) to copy ; (1E5h) 485 bytes of code. 7C18 F3 REP ; REPeat the following MOVSB ; instruction for 'CX' times. 7C19 A4 MOVSB ; Copy one byte at a time. 7C1A CB RETF ; Use RETF to do Jump to where we ; copied the code: 0000:061B. ; Since the preceding routine copies the remainder of the code to 0000:061B ; through 0000:07FF and continues its execution there, the following ; addresses have been changed to reflect the code's actual location in ; memory at the time of execution. ; This next section of code tries to find an ACTIVE (i.e., bootable) ; entry in the Partition Table. The first byte of an entry indicates ; if it's bootable(an 80h) or not(a 00h); any other values in these ; locations means the Table is invalid! If none of the four entries ; in the Table is active, the 'Invalid' error message is displayed. ; [Previous Microsoft MBR code used the SI register here rather than ; BP which can be seen at offsets 061B, 0620 and 0627 below.] 061B BDBE07 MOV BP,07BE ; Location of first entry ; in the partition table ; (see Sample Table here). 061E B104 MOV CL,04 ; Maximum of four entries. 0620 386E00 CMP [BP+00],CH ; CH=0 (from Counter decrement ; above), so CoMPare first byte ; of entry [BP+00] to Zero. Any- ; thing else will be 'less than'. 0623 7C09 JL 062E ; Found a possible boot entry ; let's check it out more at 062E ; or keep searching here... 0625 7513 JNZ 063A ; -> "Invalid partition table" 0627 83C510 ADD BP,+10 ; Checking the next entry... ; (10h = 16 bytes per entry) 062A E2F4 LOOP 0620 ; Go back & check next Entry... ; unless CL=0 (tried all four). 062C CD18 INT 18 ; Checked all 4; NONE of them ; were bootable, so start ; ROM-BASIC (only available on ; some IBM machines!) Many BIOS ; simply display "PRESS A ; KEY TO REBOOT" when an ; Interrupt 18h is executed. ; An Active partition was found, but we must check all other entries ; for being non-bootable (first byte = 00h), or there's an error! ; (Only one entry in the Partition Table can be marked as 'Active.') 062E 8BF5 MOV SI,BP ; Copy Base Pointer value of 07BE ; into Source Index Register; use 0630 83C610 ADD SI,+10 ; SI,+10 (16 bytes) to see if any ; more partitions are left. 0633 49 DEC CX ; If CX=0, then we're done here, 0634 7419 JZ 064F ; so Jump to ID-type checking! 0636 382C CMP [SI],CH ; Compare entry's first byte [SI] 0638 74F6 JZ 0630 ; to Zero (CH=0). If it's not ; zero, we immediately fall into ; the following error routine: ; Note: When the last character of any Error Message has been displayed ; on screen, the instructions at offsets 0642 and 0644 lock computer's ; execution into an infinite loop! You must reboot the machine. Int 10, ; Function 0Eh (Teletype Output) is used to display the characters. ; 063A A0B507 MOV AL,[07B5] ;[7B5]=2C Together with the '07' 063D B407 MOV AH,07 ; in AH, this gives us an offset 063F 8BF0 MOV SI,AX ; of 72C in the Source Index Reg. ; -> "Invalid partition table" 0641 AC LODSB ; Load character into AL from [SI]. 0642 3C00 CMP AL,00 |; Have we reached end of message |; marker?(00) If so, then lock 0644 74FC JZ 0642 |; execution into infinite loop. 0646 BB0700 MOV BX,0007 ; Display page 0, normal white on ; black characters. 0649 B40E MOV AH,0E ; Teletype Output.. displays only 064B CD10 INT 10 ; one character at a time. 064D EBF2 JMP 0641 ; Go back for another character! The following code is still missing some detailed
comments: 064F 884E10 MOV [BP+10],CL 0652 E84600 CALL 069B ; Load 1st sector of boot ; partition into Memory. 0655 732A JNB 0681 ; (jae short 0681) 0657 FE4610 INC BYTE PTR [BP+10] 065A 807E040B CMP BYTE PTR [BP+04],0B 065E 740B JZ 066B 0660 807E040C CMP BYTE PTR [BP+04],0C 0664 7405 JZ 066B 0666 A0B607 MOV AL,[07B6] ; [7B6] = 44 + 700 -> 744 0669 75D2 JNZ 063D ; Display: "Error loading ; operating system" 066B 80460206 ADD BYTE PTR [BP+02],06 066F 83460806 ADD WORD PTR [BP+08],+06 0673 83560A00 ADC WORD PTR [BP+0A],+00 0677 E82100 CALL 069B 067A 7305 JNB 0681 ; (jae short 0681) 067C A0B607 MOV AL,[07B6] ; [7B6] = 44 + 700 -> 744 067F EBBC JMP 063D ; Display: "Error loading ; operating system" 0681 813EFE7D55AA CMP WORD PTR [7DFE],AA55 ; Check for "Magic Number" 0687 740B JZ 0694 ; at end of sector and ; jump to Boot Record... 0689 807E1000 CMP BYTE PTR [BP+10],00 068D 74C8 JZ 0657 068F A0B707 MOV AL,[07B7] ; [7B7] = 63 + 700 -> 763 0692 EBA9 JMP 063D ; Display: "Missing ; operating system" ========================================================================== ; Set up the CS and IP Registers for Jumping to the Volume Boot Record ; loaded into Memory at 0000:7C00 using a FAR Return instruction (which ; takes IP and then CS off the STACK before jumping to CS:IP); a RETF ; was already used at 7C10 through 7C1A above. 0694 8BFC MOV DI,SP ; STACK Pointer is still 7C00. 0696 1E PUSH DS ; DS is 0000 at this time. 0697 57 PUSH DI ; SP --> DI (now 7C00). 0698 8BF5 MOV SI,BP ; BP (still 07BE) -> SI for ; use by OS Boot Record. 069A CB RETF ; Jumps to VBR at 0000:7C00 ;========================================================================== ; S U B R O U T I N E S for Reading Sectors into Memory ;========================================================================== ; The following code first performs an INT 13 Function 08 BIOS routine ; called "Get Drive Parameters" (if successful, there will be no Carry Flag ; and AH will be zero); returns Max. Head number in DH and the number of ; drives in DL. The Max. Cylinder number must be calculated from bits 7 and ; 6 of CL (two high bits) and CH (low eight bits) to form a 10-bit number; ; thus it can be no larger than 3FFh (or 1023). Bits 5 thru 0 of CL are the ; Max. Sector number -> 3Fh (or 63) is the largest value we can have there. 069B BF0500 MOV DI,0005 ;(Set 'Try Count' to 5 times!) 069E 8A5600 MOV DL,[BP+00] ;| 80 -> DL (First Hard Drive) 06A1 B408 MOV AH,08 ;| INT 13, Function 08 06A3 CD13 INT 13 ;| "Get Drive Parameters" 06A5 7223 JB 06CA 06A7 8AC1 MOV AL,CL 06A9 243F AND AL,3F ; Gives Max. Sectors (bits 5-0) 06AB 98 CBW ; Convert Byte to Word. 06AC 8ADE MOV BL,DH ; Max. Head value -> BL 06AE 8AFC MOV BH,AH 06B0 43 INC BX ; Gives Max. Heads 06B1 F7E3 MUL BX ; AX <- (Max. Heads x Sectors ; = Max. Sectors per Cylinder.) 06B3 8BD1 MOV DX,CX 06B5 86D6 XCHG DL,DH 06B7 B106 MOV CL,06 06B9 D2EE SHR DH,CL 06BB 42 INC DX 06BC F7E2 MUL DX 06BE 39560A CMP [BP+0A],DX 06C1 7723 JA 06E6 ; Check for Extended INT 13. 06C3 7205 JB 06CA 06C5 394608 CMP [BP+08],AX 06C8 731C JNB 06E6 ; Check for Extended INT 13. ; Extended Read Functions not available, so use INT 13 Fundtion 02 : ;======================================================================= 06CA B80102 MOV AX,0201 ;| INT 13, Function 2 06CD BB007C MOV BX,7C00 ;| (ES):BX = Memory Buffer 06D0 8B4E02 MOV CX,[BP+02] ;/ Cyl., Sector, Head & Drive 06D3 8B5600 MOV DX,[BP+00] ;\ values set from code above. 06D6 CD13 INT 13 ;| "Read 1 Sector into Memory" 06D8 7351 JNB 072B ; If CF not set (CF=0), then ; it's a good read, so return! 06DA 4F DEC DI ;/ CF was set, so decrease the ;| 'Try Count' and try again; 06DB 744E JZ 072B ;| unless it's been 5 times! ;| (Note: Calling code is not ;| alerted of any bad reads!) 06DD 32E4 XOR AH,AH ;| INT 13, Function 0 06DF 8A5600 MOV DL,[BP+00] ;| DL=Drive Number 06E2 CD13 INT 13 ;| "Reset DISK System" first 06E4 EBE4 JMP 06CA ;\ Go back and try again... ; The following code is the "INT 13 Extensions Installation Check" : 06E6 8A5600 MOV DL,[BP+00] ;| DL = Drive Number. 06E9 60 * PUSHA ; PUSH all Registers onto Stack. 06EA BBAA55 MOV BX,55AA ;| BX must be set to 55AAh or the ;| Function won't work! 06ED B441 MOV AH,41 ;| INT 13 Function 41h. 06EF CD13 INT 13 ;| "Check for INT 13 Extensions" 06F1 7236 JB 0729 ; Was operation successful? ; If not, Return (with CF set)! 06F3 81FB55AA CMP BX,AA55 ; The contents of BX are changed ; into AA55h if EXTs installed! 06F7 7530 JNZ 0729 ; Are they installed? ; If not, Return (with CF set)! 06F9 F6C101 TEST CL,01 06FC 742B JZ 0729 ; Return (with Carry Flag set)! 06FE 61 * POPA ; POP all Registers from Stack. ; Extended READ Sectors from HDD (Function 42h) follows. To use this function, ; the code must push what's called a "Disk Address Packet" onto the Stack in ; reverse order of how Function 42h will read the 'Packet' data from it, so ; the 00h (Reserved) and 10h bytes are the last to be pushed onto the Stack ; (see instruction at memory location 0711 below): ; ; Offset Size Description of DISK ADDRESS PACKET's Contents ; ------ ----- ------------------------------------------------------------ ; 00h BYTE Size of packet (10h = 16 bytes, or 18h=24 bytes). ; 01h BYTE Reserved (00). ; 02h WORD Number of blocks to transfer (Only 1 sector for this code). ; 04h DWORD Points to -> Transfer Buffer (0000 7C00 for this code). ; 08h QWORD Starting Absolute Sector (get from Partition Table entry: ; (00000000 + DWORD PTR [BP+08]). Remember, the Partition ; Table 'Preceding Sectors' entry can only be a max. of 4 bytes! 06FF 60 * PUSHA ; PUSH all Registers onto Stack. 0700 6A00 * PUSH 0000 ; Push 4 zero-bytes onto Stack to 0702 6A00 * PUSH 0000 ; pad VBR's Starting Sector. 0704 FF760A PUSH [BP+0A] ; High 2 bytes and then the Low 2 0707 FF7608 PUSH [BP+08] ; bytes = Location of VBR Sector. 070A 6A00 * PUSH 0000 ; \ Segment then Offset parts, so: 070C 68007C * PUSH 7C00 ; / Copy to 0x7c00 in Memory. 070F 6A01 * PUSH 0001 ; Copy only 1 sector. 0711 6A10 * PUSH 0010 ; Reserved and Packet Size (16 bytes). 0713 B442 MOV AH,42 ;| INT 13 Function 42h 0715 8BF4 MOV SI,SP ;| (DS):SI = Disk Address Packet ;| which was PUSHed onto STACK ;| to use with this function! 0717 CD13 INT 13 ;| Extended READ of drive sector. ; If successful, CF (Carry Flag) is cleared (0) and AH set to 00h. ; If any errors, CF is set to 1 and AH = error code. In either ; case, DAP's block count field is set to number of blocks actually transferred. 0719 61 * POPA ; POP all Packet values from Stack. 071A 61 * POPA ; POP all Registers from Stack. 071B 730E JNB 072B ; Read OK, so return without Disk Reset. 071D 4F DEC DI ; Error occurred, so try again after Disk Reset: 071E 740B JZ 072B ; If tried 5 times, give up! 0720 32E4 XOR AH,AH ;| INT 13 Function 0 0722 8A5600 MOV DL,[BP+00] ;| DL=Drive Number 0725 CD13 INT 13 ;| "Reset DISK System" 0727 EBD6 JMP 06FF 0729 61 * POPA ; If here, then Extensions Check ; failed, so clean up and return: 072A F9 STC ; SET Carry Flag 072B C3 RET
Location of Error
Messages and
Message Offsets in Memory
C D E F 072C 49 6E 76 61 Inva 0730 6C 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 lid partition ta 0740 62 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E ble.Error loadin 0750 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst 0760 65 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 em.Missing opera 0770 74 69 6E 67 20 73 79 73 74 65 6D 00 00 00 00 00 ting system..... 0780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0790 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 07A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 07B0 00 00 00 00 00 2C 44 63 .....,Dc 0 1 2 3 4 5 6 7 8 9 A B C D E F
Location of Sample
Disk Signature
and Partition Table in Memory
8 9 A B C D E F 07B8 A8 E1 A8 E1 00 00 80 01 ........ 07C0 01 00 07 7F BF FD 3F 00 00 00 C1 40 5E 00 00 00 ......?....@^... 07D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 07E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 07F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............U. 0 1 2 3 4 5 6 7 8 9 A B C D E F
Last Update: March 26, 2018. (26.03.2018)
Updated: 25 May 2007 (25.05.2007); 10 APR 2009 (10.04.2009); 1 AUG 2009 (01.08.2009); 10 OCT 2010 (10.10.2010); 24 May 2017 (24.05.2017); 23 MAR 2018
(23.03.2018).
You can write to me using this: online reply form.
(It opens in a new window.)
The Starman's FREE TOOLS Page
MBR and Boot Records Index
The Starman's Realm Index Page