This page concentrates on a commented disassembly of the Windows 2000 MBR. The information below was contributed by Stephan Zaubzer from Austria which is why the MBR error messages are in German. It is assumed that the code will be the same in English versions.
The following is the MBR from the first physical sector (Cylinder 0, Side 0, Sector 1) of a hard drive with Windows 2000 installed.
According to The Starman "... these go way back to NT4 (or even earlier) and are often known as the NT Serial Number! Win2k calls it the Disk Signature and you can find it in many places in the REGISTRY; it's a Quad Word, so you have to reverse all 4 bytes if you want to look for it there... it will be different for every drive and will change if you zero-out the bytes and boot up with an NT/2K/XP system again. Also see his page on An Examination of the Standard MBR.
OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF --------------------------------------------------------------------------- 00000 33 C0 8E D0 BC 00 7C FB - 50 07 50 1F FC BE 1B 7C 3.....|.P.P....| 00010 BF 1B 06 50 57 B9 E5 01 - F3 A4 CB BD BE 07 B1 04 ...PW........... 00020 38 6E 00 7C 09 75 13 83 - C5 10 E2 F4 CD 18 8B F5 8n.|.u.......... 00030 83 C6 10 49 74 19 38 2C - 74 F6 A0 B5 07 B4 07 8B ...It.8,t....... 00040 F0 AC 3C 00 74 FC BB 07 - 00 B4 0E CD 10 EB F2 88 ....t........... 00050 4E 10 E8 46 00 73 2A FE - 46 10 80 7E 04 0B 74 0B N..F.s*.F..~..t. 00060 80 7E 04 0C 74 05 A0 B6 - 07 75 D2 80 46 02 06 83 .~..t....u..F... 00070 46 08 06 83 56 0A 00 E8 - 21 00 73 05 A0 B6 07 EB F...V...!.s..... 00080 BC 81 3E FE 7D 55 AA 74 - 0B 80 7E 10 00 74 C8 A0 ....}U.t..~..t.. 00090 B7 07 EB A9 8B FC 1E 57 - 8B F5 CB BF 05 00 8A 56 .......W.......V 000A0 00 B4 08 CD 13 72 23 8A - C1 24 3F 98 8A DE 8A FC .....r#..$?..... 000B0 43 F7 E3 8B D1 86 D6 B1 - 06 D2 EE 42 F7 E2 39 56 C..........B..9V 000C0 0A 77 23 72 05 39 46 08 - 73 1C B8 01 02 BB 00 7C .w#r.9F.s......| 000D0 8B 4E 02 8B 56 00 CD 13 - 73 51 4F 74 4E 32 E4 8A .N..V...sQOtN2.. 000E0 56 00 CD 13 EB E4 8A 56 - 00 60 BB AA 55 B4 41 CD V......V.`..U.A. 000F0 13 72 36 81 FB 55 AA 75 - 30 F6 C1 01 74 2B 61 60 .r6..U.u0...t+a` 00100 6A 00 6A 00 FF 76 0A FF - 76 08 6A 00 68 00 7C 6A j.j..v..v.j.h.|j 00110 01 6A 10 B4 42 8B F4 CD - 13 61 61 73 0E 4F 74 0B .j..B....aas.Ot. 00120 32 E4 8A 56 00 CD 13 EB - D6 61 F9 C3 55 6E 67 81 2..V.....a..Ung. 00130 6C 74 69 67 65 20 50 61 - 72 74 69 74 69 6F 6E 73 ltige Partitions 00140 74 61 62 65 6C 6C 65 00 - 46 65 68 6C 65 72 20 62 tabelle.Fehler b 00150 65 69 6D 20 4C 61 64 65 - 6E 20 64 65 73 20 42 65 eim Laden des Be 00160 74 72 69 65 62 73 73 79 - 73 74 65 6D 73 00 42 65 triebssystems.Be 00170 74 72 69 65 62 73 73 79 - 73 74 65 6D 20 6E 69 63 triebssystem nic 00180 68 74 20 76 6F 72 68 61 - 6E 64 65 6E 00 00 00 00 ht vorhanden.... 00190 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 001A0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 001B0 00 00 00 00 00 2C 48 6E - 32 B5 32 B5 00 00 80 01 .....,Hn2.2..... 001C0 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00 ......?...K..... 001D0 81 0A 0F FE FF FF 8A F5 - 7F 00 7A AB D1 08 00 00 ..........z..... 001E0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 001F0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 55 AA ..............U.
The program code differs a bit from that discussed in MBR - Program for Windows 95b but performs the same functions.
The MBR sector is initially loaded into memory at 0000:7C00 but it immediately relocates itself to 0000:0600.
NOW AT 0000:7C00. Copying itself to 0000:0600
0000:7C00 33C0 XOR AX,AX Set AX to zero
0000:7C02 8ED0 MOV SS,AX Set SS (Stack Segment) to zero
0000:7C04 BC007C MOV SP,7C00 Set Stack Pointer to 0x7C00 (Stack now at 0000:7C00)
0000:7C07 FB STI Set Interrupt Flag (External Interrupts accepted)
0000:7C08 50 PUSH AX Save AX
0000:7C09 07 POP ES ES (Extra Segment Register) now zero
0000:7C0A 50 PUSH AX Save AX
0000:7C0B 1F POP DS DS (Data Segment Register) now zero
0000:7C0C FC CLD Clear Direction Flag
0000:7C0D BE1B7C MOV SI,7C1B SI (Source Index) now 0x7C1B
0000:7C10 BF1B06 MOV DI,061B DI (Destination Index now 0x61B
0000:7C13 50 PUSH AX Save AX
0000:7C14 57 PUSH DI Save DI
0000:7C15 B9E501 MOV CX,01E5 CX now 0x01E5 (d485)
0000:7C18 F3 REPZ Repeat Next Line decrementing CX until CX = 0
0000:7C19 A4 MOVSB Move [DS:SI] to [ES:DI] and increment SI, DI
0000:7C1A CB RETF Return from far: POP IP, POP CS and jmp to CS:IP (0000:061B)
NOW AT 0000:061B
0000:061B BDBE07 MOV BP,07BE Set BP (Base Pointer) to 07BE (Beginning of Partition Table)
0000:061E B104 MOV CL,04 Fill CL with 04
0000:0620 386E00 CMP [BP+00],CH Compare Bootentry [SS:BP] with CH (zero)
0000:0623 7C09 JL 062E Jmp to OTHER ACTIVE PRT if Bootentry >= 0x80 (Jump Distance indicated by 1 byte in Opcode:09)
0000:0625 7513 JNZ 063A Jmp to INVLD PRT TBL if Bootentry <>0x00
0000:0627 83C510 ADD BP,+10 Point to next Partition Entry
0000:062A E2F4 LOOP 0620 (Jump Distanve indicated by 1 byte, negative distances in 2's complement)
0000:062C CD18 INT 18 No Bootable Partition... Goto Rom Basic
:OTHER ACTIVE PRT?
0000:062E 8BF5 MOV SI,BP SI points now to 1st Byte of active Partitionentry
0000:0630 83C610 ADD SI,+10 now, points to 1st Byte of next Partition
0000:0633 49 DEC CX
0000:0634 7419 JZ 064F Jmp to LABEL 3 If no Partitionenty left...
0000:0636 382C CMP [SI],CH Compare Bootentry of next Partition
0000:0638 74F6 JZ 0630 If zero, test next partition
0000:063A A0B507 MOV AL,[07B5] Fill AL with byte at 0000:07B5 (Pointer to message)
:DISPLAY MESSAGE (Display message, and hang system in infinite loop)
0000:063D B407 MOV AH,07 Fill AH with 0x07
0000:063F 8BF0 MOV SI,AX Fill SI with 0x07** (** for each message different)
:MESSAGE LOOP
0000:0641 AC LODSB Load DS:SI (0000:072C) into AL, Increment SI
:INFINITE LOOP
0000:0642 3C00 CMP AL,00 Compare AL with 0x00
0000:0644 74FC JZ 0642 jmp to INFINITE LOOP if AL zero
0000:0646 BB0700 MOV BX,0007 Set Screen Attributes
0000:0649 B40E MOV AH,0E Fill AH with 0x0E
0000:064B CD10 INT 10 INT 10 AH=0E Print character stored in AL
0000:064D EBF2 JMP 0641 Jmp to MESSAGE LOOP
:LABEL 3
0000:064F 884E10 MOV [BP+10],CL Set beginning of next Partition entry to zero
0000:0652 E84600 CALL 069B PUSH IP, jump to 0000:069B
0000:0655 732A JNB 0681 IF CF = 0 (Bootrecord allready read) jump to ...
0000:0657 FE4610 INC BYTE PTR [BP+10] Increase first byte of next partitiontableentry
0000:065A 807E040B CMP BYTE PTR [BP+04],0B Check if Partition is FAT32
0000:065E 740B JZ 066B Jump if FAT32
0000:0660 807E040C CMP BYTE PTR [BP+04],0C Check if partition is FAT32 LBA Mapped
0000:0664 7405 JZ 066B Jump if FAT32 LBA Mapped
0000:0666 A0B607 MOV AL,[07B6] AL now 48
0000:0669 75D2 JNZ 063D Display Message: "Fehler beim Laden des Betriebssystems"
0000:066B 80460206 ADD BYTE PTR [BP+02],06 increase Sectornumber by 6
0000:066F 83460806 ADD WORD PTR [BP+08],+06 Increase Starting LBA (1st 2 Bytes) by 6
0000:0673 83560A00 ADC WORD PTR [BP+0A],+00 If overflow in last operation, correct
0000:0677 E82100 CALL 069B Call SUBROUTINE
0000:067A 7305 JNB 0681 IF CF = 0 (Bootrecord already read) jump to
0000:067C A0B607 MOV AL,[07B6] AL now now 48
0000:067F EBBC JMP 063D Display Message: "Fehler beim Laden des Betriebssystems"
0000:0681 813EFE7D55AA CMP WORD PTR [7DFE],AA55 Check for MBR Signature
0000:0687 740B JZ 0694 If signature ok, Jump to ...
0000:0689 807E1000 CMP BYTE PTR [BP+10],00 Look if Next Partitionenty = 0
0000:068D 74C8 JZ 0657 If yes, goto 0657, and if Fat32, Read safety boot record
0000:068F A0B707 MOV AL,[07B7] Al now messagepointer (6E)
0000:0692 EBA9 JMP 063D Show message (Betriebssystem nicht vorhanden)
0000:0694 8BFC MOV DI,SP Stackpointer (7C00) now DI
0000:0696 1E PUSH DS Push DS (0000)
0000:0697 57 PUSH DI Push DI (7C00)
0000:0698 8BF5 MOV SI,BP SI points now to Partitionentry begin of first Partition
0000:069A CB RETF Start Bootcode of OS
:DRIVEPARAMETERS (called from 0000:0652 and 0000:0677)
0000:069B BF0500 MOV DI,0005 Fill DI with 0x0005
0000:069E 8A5600 MOV DL,[BP+00] Fill DL with 0x80
0000:06A1 B408 MOV AH,08 Fill AH with 0x08
0000:06A3 CD13 INT 13 Get Drive Parameters
0000:06A5 7223 JB 06CA If Error, jmp to READ SECTOR
0000:06A7 8AC1 MOV AL,CL AL (0-5) max sectornumber, (6-7) high bits of cylinder
0000:06A9 243F AND AL,3F Set Bit 7 and 8 of AL zero (now AL = max Sector number)
0000:06AB 98 CBW Expand AL to AX
0000:06AC 8ADE MOV BL,DH now BL = maximum Head number
0000:06AE 8AFC MOV BH,AH now BH = 00
0000:06B0 43 INC BX now BX = maximum Head number + 1
0000:06B1 F7E3 MUL BX Multiply BX by AX (Sectornumber by Headnumber(+1)) and store it in DX:AX
0000:06B3 8BD1 MOV DX,CX Move CX (maximum cylindernumber and sectornumber) to DX
0000:06B5 86D6 XCHG DL,DH Now, Bits 0-7 = max Cyl number, 8-13 max heads, 14-15 = High cyl-bits.
0000:06B7 B106 MOV CL,06 CL now 0x06
0000:06B9 D2EE SHR DH,CL Shift DH 6 bits to the right
0000:06BB 42 INC DX Now max Cyl-number + 1
0000:06BC F7E2 MUL DX Multiply max Cyl-number(+1) by result of prior multiplication. DX:AX now contains max numbers of Sectors on HD by CHS-Adressing
0000:06BE 39560A CMP [BP+0A],DX Compare DX with Higher Word of Distance of Bootsector of active partition
0000:06C1 7723 JA 06E6 If Partitiontable entry bigger, goto CHECK FOR INT 13 EXT
0000:06C3 7205 JB 06CA If smaller, goto READ SECTOR
0000:06C5 394608 CMP [BP+08],AX Compare lower word
0000:06C8 731C JNB 06E6 If NOT smaller, goto ...
:READ SECTOR (without INT13 Extension)
0000:06CA B80102 MOV AX,0201 Read one sector (???Why read, when error occured while getting drive parameters???
0000:06CD BB007C MOV BX,7C00 to 0000:7C00
0000:06D0 8B4E02 MOV CX,[BP+02] set cylinder and sector number
0000:06D3 8B5600 MOV DX,[BP+00] set drive and head number
0000:06D6 CD13 INT 13 Read Bootsector of Bootpartition
0000:06D8 7351 JNB 072B If successful, jmp to 0000:072B
0000:06DA 4F DEC DI DI now 0x0004
0000:06DB 744E JZ 072B Jump if DI = 0x0000 (5 times tried, NOT successful)
0000:06DD 32E4 XOR AH,AH Set AH zero
0000:06DF 8A5600 MOV DL,[BP+00] DL now 0x80
0000:06E2 CD13 INT 13 Diskreset
0000:06E4 EBE4 JMP 06CA Retry (READ SECTOR)
:CHECK FOR INT 13 EXT
0000:06E6 8A5600 MOV DL,[BP+00] DL now 80
0000:06E9 60 PUSHA PUSH AX, CX, DX, BX, SP, BP, SI and DI
0000:06EA BBAA55 MOV BX,55AA Set BX for Extended INT 13h Check
0000:06ED B441 MOV AH,41 Set AX for Extended INT 13h Check
0000:06EF CD13 INT 13 Check for INT 13h extensions
0000:06F1 7236 JB 0729 Jump to 0729 if NOT supported
0000:06F3 81FB55AA CMP BX,AA55 Check if installed
0000:06F7 7530 JNZ 0729 Jump to 0729 if NOT installed
0000:06F9 F6C101 TEST CL,01 Test if extended Disk Access functions supported
0000:06FC 742B JZ 0729 If not Supported, jump to 0729
: READ SECTOR WITH INT 13 Ext.
0000:06FE 61 POPA POP DI, SI, BP, SP(*), BX, DX, CX, AX, ((*) Doesn't get stored)
0000:06FF 60 PUSHA Push Registers again
0000:0700 6A00 PUSH 00 Push 0x0000 /High DWord of LBA Adress
0000:0702 6A00 PUSH 00 Push 0x0000 \High DWord of LBA Adress
0000:0704 FF760A PUSH WORD PTr [BP+0A] PUSH Starting LBA (High word) /Low DWord of LBA Adress
0000:0707 FF7608 PUSH WORD PTr [BP+08] PUSH Starting LBA (Low word) \Low Dword of LBA Adress
0000:070A 6A00 PUSH 00 Push 0x0000 (Adress of readbuffer)
0000:070C 68007C PUSH 7C00 Push 0x7C00 (Adress of readbuffer) (0000:7C00)
0000:070F 6A01 PUSH 01 Push 0x0001 (number of sectors to read)
0000:0711 6A10 PUSH 10 Push 0x0010
0000:0713 B442 MOV AH,42 AH now 42 For INT 13 Extended read
0000:0715 8BF4 MOV SI,SP DS:SI points to stack for INT13 extended read
0000:0717 CD13 INT 13 Read
0000:0719 61 POPA POP 16 bytes
0000:071A 61 POPA POP 16 bytes
0000:071B 730E JNB 072B If Successful, jump to RET
0000:071D 4F DEC DI Dec DI
0000:071E 740B JZ 072B If Zero, jump to RET
0000:0720 32E4 XOR AH,AH AH now zero (for disk reset)
0000:0722 8A5600 MOV DL,[BP+00] DL now 80
0000:0725 CD13 INT 13 Diskreset
0000:0727 EBD6 JMP 06FF Try Again
0000:0729 61 POPA POP DI, SI, BP, SP(*), BX, DX, CX, AX, ((*)Doesn't get stored)
0000:072A F9 STC Set Carry Flag (Sector not yet read)
0000:072B C3 RET POP IP, goto 0000:IP
------------------------------------------------ END OF BOOTCODE ------------------------------------------------
MESSAGE AREA
0 1 2 3 4 5 6 7 8 9 A B C D E F
------------------------------------------------------------------------------
00000720 | 55 6E 67 81 Ung Invalid Partition Table
00000730 | 6C 74 69 67 65 20 50 61 72 74 69 74 69 6F 6E 73 ltige Partitions
00000740 | 74 61 62 65 6C 6C 65 00 46 65 68 6C 65 72 20 62 tabelle.Fehler b Error loading operating
00000750 | 65 69 6D 20 4C 61 64 65 6E 20 64 65 73 20 42 65 eim Laden des Be system
00000760 | 74 72 69 65 62 73 73 79 73 74 65 6D 73 00 42 65 triebssystems.Be No operating system
00000770 | 74 72 69 65 62 73 73 79 73 74 65 6D 20 6E 69 63 triebssystem nic
00000780 | 68 74 20 76 6F 72 68 61 6E 64 65 6E 00 00 00 00 ht vorhanden....
00000790 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000007A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| MESSAGE POINTERS
000007B0 | 00 00 00 00 00 2C 48 6E 32 B5 32 B5 00 00
| PARTITIONTABLE 80 01 .....,Hn22...
000007C0 | 01 00 07 FE BF 09 3F 00 00 00 4B F5 7F 00 00 00 ....?...K...
000007D0 | 81 0A 0F FE FF FF 8A F5 7F 00 7A AB D1 08 00 00 ...z...
000007E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000007F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............U
LAST WORD (offset 07FE): 55AA (BOOT SECTOR SIGNATURE)
If you have comments or suggestions, email me at Ray Knights or the main author Stephan Zaubzer
This page was created on 5 October 2002, last updated on 2 July 2003.