Windows 7 MBR 부트코드 영문 분석자료
-----------------------------------------------------------------------------------------

MBR 영역별 분석 : base index 0000:7C00
An Examination of the Assembly Code
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.
Note: If you compare this code to that of the Windows Vista MBR, you'll find there's only a slight variation due to changing two jump instructions from 32-bit to 16-bit at Memory locations 06A2 and 06C9; allowing for the insertion of a CLI instruction immediately after it, and an STI instruction at 06E1. Due to these changes various offset bytes also needed to be adjusted. (For those interested, the first byte difference from the Vista MBR code occurs at Memory location 062B, where the location to jump to changes from 073D to 073B. The next adjustment doesn't occur until 069E; just a few bytes before all of the same code bytes become shifted by 1 to 4 bytes when compared to Vista's MBR.)
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 8EC0 MOV ES,AX ; Since AX=0, zero-out Extra Segment,
7C09 8ED8 MOV DS,AX ; and zero-out Data Segment.
7C0B BE007C MOV SI,7C00 ; Source Index: Copy from here...
7C0E BF0006 MOV DI,0600 ; Destination Index: Copy to here:
; Code will begin at: 0000:0600
7C11 B90002 MOV CX,0200 ; Set up Counter (CX) to copy all
; (200h) 512 bytes of the code.
7C14 FC CLD ; Clear Direction Flag
7C15 F3 REP ;/ REPeat the following MOVSB
;| instruction for 'CX' times;
7C16 A4 MOVSB ;\ copying one byte at a time.
; Note: Some debuggers disassemble the last two instructions above as:
; REP MOVSB BYTE PTR ES:[DI], BYTE PTR DS:[SI]
; making clear the source [SI] and destination [DI] of the bytes being copied.
; CX will count down from 200h to zero while DI increases in step up to 800h.
7C17 50 PUSH AX ; Set up Segment(AX) and Offset(DI)
7C18 681C06 * PUSH 061C ; for jump to 0000:061C.
7C1B CB RETF ; Use RETF to do Jump into where we
; copied all the code: 0000:061C.
; Since the preceding routine not only copies the MBR code to a new location, but
; also jumps there to continue its execution, 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. [Microsoft MBR code prior to 2000/XP used the SI register here
; rather than BP; which can be seen at offsets 0620, 0623 and 062D below.]
061C FB STI ; Enable Interrupts
061D B90400 MOV CX,0004 ; Maximum of four entries.
0620 BDBE07 MOV BP,07BE ; Location of first entry
; in the partition table
; (see Sample Table here).
0623 807E0000 CMP BYTE PTR [BP+00],00 ; CoMPare first byte of entry at
; SS:[BP+00] to Zero. Anything from
; 80h to FFh will be less than, which means:
0627 7C0B JL 0634 ; We found a possible boot entry, so we
; check on it in more detail at 0634h
0629 0F850E01 * JNZ 073B ; But if it's not zero (and greater than),
; then we have an Error! (Because we must
; have found a 01h through 79h byte.) So:
; -> "Invalid partition table"
; Otherwise, we found a zero; so we keep on
062D 83C510 ADD BP,+10 ; searching: Check the next entry ...
; (there are 10h = 16 bytes per entry)
0630 E2F1 LOOP 0623 ; Go back & check next Entry ...
; unless CL = 0 (we tried all four).
0632 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.
Just like most of the MBR code we've studied here, if you were to load a copy of the Win7 MBR with an empty partition table (or one that has no Active Boot Flag for any of its entries) as a *.bin file into MS-DEBUG (e.g., debug mbr.bin), move all the code to offset 0x0600 (-m 100 2ff 600), set the IP to 0x061C (-rip then 61c) and run it (-g; Note: Although MS-DEBUG cannot step through the code at 0x0629 since it doesn't understand instructions beyond the 8086 through 8088 processors, when you enter 'g' it will simply pass all the code it encounters to Win XP/Vista/Win7's NTVDM program; under which you are actually running DEBUG, without trying to disassemble it), you would then see the following error message on your screen:

Because NTVDM was never programmed to handle an 18h Interrupt any further than displaying this message. If you Ignore it, the NTVDM program might warn you one more time about accessing the hard disk, but it will eventually freeze or go off into oblivion if you Ignore it again; and you'll have to use Task Manager to close the DOS Prompt window gracefully.
0634 885600 MOV [BP+00],DL ; DL=0 first time we arrive here.
; So if we had 80h it becomes 0h.
0637 55 PUSH BP ; Save Base Pointer on Stack.
0638 C6461105 MOV BYTE PTR [BP+11],05 ;
063C C6461000 MOV BYTE PTR [BP+10],00 ; Used as a flag and/or counter
; for the INT13 Extensions being
; installed; see 0656 and 065B below.
0640 B441 MOV AH,41 ;/
0642 BBAA55 MOV BX,55AA ;|
0645 CD13 INT 13 ;| INT13, Function 41h (with BX=55AAh):
;| Check for Int 13 Extensions in BIOS.
;| If CF flag cleared and [BX] changes to AA55h, they are installed; Major
;\ version is in AH: 01h=1.x; 20h=2.0/EDD-1.0; 21h=2.1/EDD-1.1; 30h=EDD-3.0.
0647 5D POP BP ; Get back original Base Pointer.
0648 720F JB 0659 ; Below? If so, CF=1 (not cleared)
; so no INT 13 Ext. & do jump!
064A 81FB55AA CMP BX,AA55 ; Did contents of BX change? If
064E 7509 JNZ 0659 ; not, jump to offset 0659.
0650 F7C10100 TEST CX,0001 ; Have we checked all four entries?
0654 7403 JZ 0659 ; If Yes, jump over next line...
0656 FE4610 INC BYTE PTR [BP+10] ; or increase [BP+10h] by one.
0659 6660 * PUSHA ; Save all 16-bit Registers on
; the Stack.
065B 807E1000 CMP BYTE PTR [BP+10],00 ;/ CoMPare [BP+10h] to zero;
065F 7426 JZ 0687 ;\ if 0, can't use Extensions.
The following code is missing some comments, but all the instructions are here for you to study.
; The following code uses INT 13, Function 42h (Extended Read)
0661 666800000000 * PUSH 00000000
0667 66FF7608 * PUSH DWORD PTR [BP+08]
066B 680000 * PUSH 0000
066E 68007C * PUSH 7C00
0671 680100 * PUSH 0001
0674 681000 * PUSH 0010
0677 B442 MOV AH,42
0679 8A5600 MOV DL,[BP+00]
067C 8BF4 MOV SI,SP
067E CD13 INT 13
0680 9F LAHF ; Load Status flags into AH
0681 83C410 ADD SP,+10
0684 9E SAHF ; Save AH into flags register
0685 EB14 JMP 069B
; The MBR uses the standard INT 13 "Read Sectors" function here, because
; no INT 13 Extended functions were found in the BIOS code above (065F):
0687 B80102 MOV AX,0201 ; Function 02h, read only 1 sector.
068A BB007C MOV BX,7C00 ; Buffer for read starts at 7C00.
068D 8A5600 MOV DL,[BP+00] ; DL = Disk Drive
0690 8A7601 MOV DH,[BP+01] ; DH = Head number (never use FFh).
0693 8A4E02 MOV CL,[BP+02] ; Bits 0-5 of CL (max. value 3Fh)
; make up the Sector number.
0696 8A6E03 MOV CH,[BP+03] ; Bits 6-7 of CL become highest two
; bits (8-9) with bits 0-7 of CH to
; make Cylinder number (max. 3FFh).
0699 CD13 INT 13 ; INT13, Function 02h: READ SECTORS
; into Memory at ES:BX (0000:7C00).
; Whether Extensions are installed or not, both routines end up here:
069B 6661 * POPA ; Restore all 16-bit Registers from
; the Stack which we saved at 0659.
069D 731C JNB 06BB
069F FE4E11 DEC BYTE PTR [BP+11] ; Begins with 05h from 0638.
06A2 750C JNZ 06B0 ; If 0, tried all 4 entries!
06A4 807E0080 CMP BYTE PTR [BP+00],80
06A8 0F848A00 * JZ 0736 ; -> "Error loading
; operating system"
06AC B280 MOV DL,80
06AE EB82 JMP 0634
06B0 55 PUSH BP
06B1 32E4 XOR AH,AH
06B3 8A5600 MOV DL,[BP+00]
06B6 CD13 INT 13
06B8 5D POP BP
06B9 EB9E JMP 0659
06BB 813EFE7D55AA CMP WORD PTR [7DFE],AA55
06C1 756E JNZ 0731 ; If we don't see it, Error!
; -> "Missing operating system"
06C3 FF7600 PUSH WORD PTR [BP+00]
; =====================================================================
; All of the code from 06C6 through 0726 is related to discovering if
; TPM version 1.2 interface support is operational on the system, since
; it could be used by BitLocker for validating the integrity of a PC's
; early startup components before allowing the OS to boot. The spec for
; the TPM code below states "There MUST be no requirement placed on the
; A20 state on entry to these INT 1Ah functions." (p.83) We assume here
; Microsoft understood this to mean access to memory over 1 MiB must be
; made available before entering any of the TPM's INT 1Ah functions.
; The following code is actually a method for gaining access to Memory
; locations above 1 MiB (also known as enabling the A20 address line).
;
; Each address line allows the CPU to access ( 2 ^ n ) bytes of memory:
; A0 through A15 can give access to 2^16 = 64 KiB. The A20 line allows
; a jump from 2^20 (1 MiB) to 2^21 = 2 MiB in accessible memory. But
; our computers are constructed such that simply enabling the A20 line
; also allows access to any available memory over 1 MiB if both the CPU
; and code can handle it (once outside of "Real Mode"). Note: With only
; a few minor differences, this code at 06C6-06E1 and the Subroutine at
; 0756 ff. are the same as rather old sources we found on the Net.
06C6 E88D00 CALL 0756
06C9 7517 JNZ 06E2
06CB FA CLI ; Clear IF, so CPU ignores maskable interrupts.
06CC B0D1 MOV AL,D1
06CE E664 OUT 64,AL
06D0 E88300 CALL 0756
06D3 B0DF MOV AL,DF
06D5 E660 OUT 60,AL
06D7 E87C00 CALL 0756
06DA B0FF MOV AL,FF
06DC E664 OUT 64,AL
06DE E87500 CALL 0756
06E1 FB STI ; Set IF, so CPU can respond to maskable interrupts
; again, after the next instruction is executed.
; Comments below checked with the document, "TCG PC Client Specific
; Implementation Specification For Conventional BIOS" (Version 1.20
; FINAL/Revision 1.00/July 13, 2005/For TPM Family 1.2; Level 2), §
; 12.5, pages 85 ff. TCG and "TCG BIOS DOS Test Tool" (MSDN).
06E2 B800BB MOV AX,BB00 ; With AH = BBh and AL = 00h
06E5 CD1A INT 1A ; Int 1A -> TCG_StatusCheck
06E7 6623C0 * AND EAX,EAX ;/ If EAX does not equal zero,
06EA 753B JNZ 0727 ;\ then no BIOS support for TCG.
06EC 6681FB544350+ * CMP EBX,41504354 ; EBX must also return ..
; the numerical equivalent
; of the ASCII character string "TCPA" ("54 43 50 41") as a further
; check. (Note: Since hex numbers are stored in reverse order on PC
; media or in Memory, a TPM BIOS would put 41504354h in EBX.)
06F3 7532 JNZ 0727 ; If not, exit TCG code.
06F5 81F90201 CMP CX,0102 ; Version 1.2 or higher ?
06F9 722C JB 0727 ; If not, exit TCG code.
; If TPM 1.2 found, perform a: "TCG_CompactHashLogExtendEvent".
06FB 666807BB0000 * PUSH 0000BB07 ; Setup for INT 1Ah AH = BB,
; AL = 07h command (p.94 f).
0701 666800020000 * PUSH 00000200 ;
0707 666808000000 * PUSH 00000008 ;
070D 6653 * PUSH EBX ;
070F 6653 * PUSH EBX ;
0711 6655 * PUSH EBP ;
0713 666800000000 * PUSH 00000000 ;
0719 6668007C0000 * PUSH 00007C00 ;
071F 6661 * POPAD ;
0721 680000 * PUSH 0000 ;
0724 07 POP ES ;
0725 CD1A INT 1A
; On return, "(EAX) = Return Code as defined in Section 12.3" and
; "(EDX) = Event number of the event that was logged".
; =====================================================================
0727 5A POP DX
0728 32F6 XOR DH,DH ;
072A EA007C0000 JMP 0000:7C00 ; Jump to Volume Boot Record code
; loaded into Memory by this MBR.
072F CD18 INT 18 ; This instruction is prob. here to
; meet a specification of TPM v 1.2 ?
; Note: When the last character of any Error Message has been displayed, the
; instructions at offsets 0748, 0753 and 0754 lock computer's execution into
; a never ending loop! You must reboot the machine. INT 10, Function 0Eh
; (Teletype Output) is used to display each character of these error messages.
0731 A0B707 MOV AL,[07B7] ; [7B7] = 9A + 700 -> 79A h
0734 EB08 JMP 073E ; Displays: "Missing operating system"
0736 A0B607 MOV AL,[07B6] ; [7B6] = 7B + 700 -> 77B h
0739 EB03 JMP 073E ; Displays: "Error loading operating
; system"
073B A0B507 MOV AL,[07B5] ; [7B5] = 63 + 700 -> 763 h
; which will display: "Invalid
; partition table"
073E 32E4 XOR AH,AH ; Zero-out AH.
0740 050007 ADD AX,0700 ; Add 700h to offsets from above.
0743 8BF0 MOV SI,AX ; Offset of message -> Source Index Reg.
0745 AC LODSB ; Load character into AL from [SI].
0746 3C00 CMP AL,00 ;/ Have we reached end of message
;| marker?(00) If so, then
0748 7409 JZ 0753 ;
074A BB0700 MOV BX,0007 ; Display page 0, normal white on black
; characters.
074D B40E MOV AH,0E ;/ Teletype Output.. displays only
074F CD10 INT 10 ;\ one character at a time.
0751 EBF2 JMP 0745 ; Go back for another character...
0753 F4 HLT
0754 EBFD JMP 0753 ; And just in case an NMI occurs,
; we jump right back to HLT again!
; -----------------------------------------------------------------------
; SUBROUTINE - Part of A20 Line Enablement code (see 06C6 ff. above);
; This routine checks/waits for access to KB controller.
; -----------------------------------------------------------------------
0756 2BC9 SUB CX,CX ; Sets CX = 0.
0758 E464 IN AL,64 ; Check port 64h.
075A EB00 JMP 075C ; Seems odd, but this is how it's done.
075C 2402 AND AL,02 ; Test for only 'Bit 1' *not* set.
075E E0F8 LOOPNE 0758 ; Continue to check (loop) until
; CX = 0 (and ZF=1); it's ready.
0760 2402 AND AL,02
0762 C3 RET
Location of Error Messages and Message Offsets in Memory
3 4 5 6 7 8 9 A B C D E F
0763 49 6E 76 61 6C 69 64 20 70 61 72 74 69 Invalid parti
0770 74 69 6F 6E 20 74 61 62 6C 65 00 45 72 72 6F 72 tion Table.Error
0780 20 6C 6F 61 64 69 6E 67 20 6F 70 65 72 61 74 69 loading operati
0790 6E 67 20 73 79 73 74 65 6D 00 4D 69 73 73 69 6E ng system.Missin
07A0 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst
07B0 65 6D 00 00 00 63 7B 9A em...c{.
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 D4 34 A0 2E 00 00 80 20 .4.....
07C0 21 00 07 DF 13 0C 00 08 00 00 00 20 03 00 00 DF !.......... ....
07D0 14 0C 07 FE FF FF 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
This is how it would be seen in a disk editor that can interpret Partition Table data:
Partition Active Starting Loc Ending Loc Relative Number of
Type Boot Cyl Head Sec Cyl Head Sec sectors sectors
------------- ------ ------------ ------------- -------- ---------
NTFS Yes 0 32 33 12 223 19 2048 204800
NTFS No 12 223 20 1023 254 63 206848 nnnnnnnnn
[Note: Cylinders and heads start counting at ZERO; sectors at 1. So, a CHS of
0,32,33 gives us 32 'full' heads of 63 sectors each, or 32 x 63 = 2016; the
33rd head including only up to sector 33, for a total of: 2016 + 33 = 2049, or
Absolute Sector 2048 as the sector where Win7 partitions begin on the disk;
with 2048 sectors preceding.
12,223,20 gives us 12 'full' cylinders of 255 x 63 = 16065 sectors each, or
12 x 16065 = 192780 sectors. The 13th cylinder being only 223 'full' heads or
14049; the 224th head including only up to sector 20, for a total of:
192780 + 14049 + 20 = 206849, or Absolute Sector 206848 as the sector where
this disk's second primary partition begins.]
덧글