Sponsored by:

Fully Managed Technology Services

 

An Examination of the
Windows 2000 ( NT5.0 )
and
Windows XP ( NT5.1 )
MBR ( Master Boot Record )

[ 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*.


Other Microsoft MBR pages:
  An Examination of the Standard MBR created by MS-DOS FDISK
  The MBR created by MS-Windows 95B/98/98SE and ME's FDISK

And Microsoft OS Volume Boot Records:
  An Examination of the MS-Windows 95B/98/98SE/Me OS Boot Record (MSWIN4.1)
  An Examination of the MS-Windows 2000/XP OS Boot Record (NTFS)

Confused? Send me an email if you have a specific question about the MBR or any Boot Records...

 

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.

There have been many MBRs or IPLs (Initial Program Loaders) created for booting an OS and even for booting multiple OSs. See Multi-OS Booting on my "Tools and References" Page for some alternative code and Boot Managers.

 

 



Introduction


Figure 1. Note that the bytes "2c 44 63"are part of the MBR's image file in dmadmin.exe


Figure 2. The bytes "2c 44 63"have always been part of this MBR's image file for English.

 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


An Examination of the Assembly 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