3

As we know, the master boot record (MBR) starts with 440 bytes of boot code. From what I read, it initiates the boot process and loads the operating system's boot loader.

But for an external hard drive, which is used for file storage only and is completely not bootable, why is there still boot code?

I have a 1 TB HP P900 SSD with an MBR, an ext4 partition, and an exFAT partition. All partitions are for file storage only, and again they are not bootable, but why in the MBR raw bytes, is there still boot code?

Here is the entire MBR's raw bytes in hexadecimal (as output by xxd -a):

00000000: fab8 0010 8ed0 bc00 b0b8 0000 8ed8 8ec0  ................
00000010: fbbe 007c bf00 06b9 0002 f3a4 ea21 0600  ...|.........!..
00000020: 00be be07 3804 750b 83c6 1081 fefe 0775  ....8.u........u
00000030: f3eb 16b4 02b0 01bb 007c b280 8a74 018b  .........|...t..
00000040: 4c02 cd13 ea00 7c00 00eb fe00 0000 0000  L.....|.........
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
000001b0: 0000 0000 0000 0000 69d0 e830 0000 0020  ........i..0... 
000001c0: 2100 83fe c2ff 0008 0000 0060 f624 00fe  !..........`.$..
000001d0: c2ff 07fe c2ff 0068 f624 0068 4552 0000  .......h.$.hER..
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.
james
  • 615

1 Answers1

6

The current diskpart command included with Windows 10 and 11 will write BIOS boot code to the MBR, when the following commands are issued after selecting a disk.

clean 
convert mbr

The same is true, if the following commands are issued.

clean
create partition

So finding boot code in the MBR should not be usual. If you wanted to create a MBR with an empty partition table and no boot code, then enter the following commands.

clean 
convert gpt
convert mbr

Below is a copy of the boot code from your question. I truncated the trailing zeros.

fab800108ed0bc00b0b800008ed88ec0fbbe007cbf0006b90002f3a4ea21060000bebe073804750b83c61081fefe0775f3eb16b402b001bb007cb2808a74018b4c02cd13ea007c0000ebfe

If you copy and paste into the Online Assembler and Disassembler, you get the following disassembly for x86 (16). Note that I needed to do this twice. The first part of the boot code runs at a offset of 0x7C00 and the remaining part runs at an offset of 0x600.

0x0000000000007c00:  FA                cli       
0x0000000000007c01:  B8 00 10          mov       ax, 0x1000
0x0000000000007c04:  8E D0             mov       ss, ax
0x0000000000007c06:  BC 00 B0          mov       sp, 0xb000
0x0000000000007c09:  B8 00 00          mov       ax, 0
0x0000000000007c0c:  8E D8             mov       ds, ax
0x0000000000007c0e:  8E C0             mov       es, ax
0x0000000000007c10:  FB                sti       
0x0000000000007c11:  BE 00 7C          mov       si, 0x7c00
0x0000000000007c14:  BF 00 06          mov       di, 0x600
0x0000000000007c17:  B9 00 02          mov       cx, 0x200
0x0000000000007c1a:  F3 A4             rep movsb byte ptr es:[di], byte ptr [si]
0x0000000000007c1c:  EA 21 06 00 00    ljmp      0:0x621
0x0000000000000621:  BE BE 07          mov  si, 0x7be
0x0000000000000624:  38 04             cmp  byte ptr [si], al
0x0000000000000626:  75 0B             jne  0x633
0x0000000000000628:  83 C6 10          add  si, 0x10
0x000000000000062b:  81 FE FE 07       cmp  si, 0x7fe
0x000000000000062f:  75 F3             jne  0x624
0x0000000000000631:  EB 16             jmp  0x649
0x0000000000000633:  B4 02             mov  ah, 2
0x0000000000000635:  B0 01             mov  al, 1
0x0000000000000637:  BB 00 7C          mov  bx, 0x7c00
0x000000000000063a:  B2 80             mov  dl, 0x80
0x000000000000063c:  8A 74 01          mov  dh, byte ptr [si + 1]
0x000000000000063f:  8B 4C 02          mov  cx, word ptr [si + 2]
0x0000000000000642:  CD 13             int  0x13
0x0000000000000644:  EA 00 7C 00 00    ljmp 0:0x7c00
0x0000000000000649:  EB FE             jmp  0x649

This is very old BIOS boot code which relies the CHS (Cylinder, Head, Sector) part of the MBR table. The LBA (Logical Block Addressing) part of the MBR table is ignored. Below is a explanation of what the instructions do.

Code          Comment
7c00: cli
7c01: mov ax, 0x1000
7c04: mov ss, ax
7c06: mov sp, 0xb000
7c09: mov ax, 0
7c0c: mov ds, ax
7c0e: mov es, ax
7c10: sti
Clear interupt flag.
Set the Stack location.
Set segment registers to zero.
Set interupt flag.
7c11: mov si, 0x7c00
7c14: mov di, 0x600
7c17: mov cx, 0x200
7c1a: rep movsb byte ptr es:[di], byte ptr [si]
Copy all 512 bytes of itself to new location starting at 0x600.
7c1c: ljmp 0:0x621 Jump to continue execution at the new location.
0621: mov si, 0x7be
0624: cmp byte ptr [si], al
0626: jne 0x633
0628: add si, 0x10
062b: cmp si, 0x7fe
062f: jne 0x624
0631: jmp 0x649
Search each of the 4 partition table entries for a nonzero status byte. The code assumes a nonzero value means the partition is active. If found, goto 0x633. Otherwise, jump to an infinite loop at 0x649.
0633: mov ah, 2
0635: mov al, 1
0637: mov bx, 0x7c00
063a: mov dl, 0x80
063c: mov dh, byte ptr [si + 1]
063f: mov cx, word ptr [si + 2]
0642: int 0x13
Execute an INT 13h AH=02h: Read Sectors From Drive.
The starting CHS 3 byte value from the active MBR partition table entry is passed to the BIOS as the starting location to read from the first HDD. The 512 bytes read then overwrite the original MBR placed in memory at location 0x7C00 by the BIOS.
0644: ljmp 0:0x7c00 Jump to continue execution at 0x7C00.
0649: jmp 0x649 Execute an infinite loop. This can happen when no partition is flagged as active.

A disassembly of the MBR BIOS boot code currently used by Microsoft can be found in the appendix of this answer. Note the following with repect to the disassembled current MBR BIOS boot code.