0xAA55 发表于 2014-1-26 19:39:43

【操作系统】MBR

Legacy引导方式,选择从硬盘引导,一般都是由BIOS载入硬盘主引导扇区看它是否“OK”(也就是判断0xAA55标识)。如果主引导扇区最后两个字节是0xAA55(0x55,0xAA)那么这是个可引导的扇区,BIOS转入入口点。
MBR中的指令一般做什么呢?找到活动分区,把活动分区DBR载入到0x7C00处,转入运行。当然此时的MBR已经把自己转移到内存别处,一般是0x600处。
来一张硬盘结构图。

主引导扇区的指令部份只有446字节,剩下的66字节是4个分区表(DPT)和一个可引导标识0xAA55。
分区表的格式:
BYTE bActive; //只能是MBR_ACTIVE、MBR_INACTIVE,否则非法
BYTE bStartHead; //起始磁头
BYTE bStartSector; //起始扇区
BYTE bStartCylinder; //起始磁道
BYTE bFSType; //文件系统格式
BYTE bEndHead; //结束磁头
BYTE bEndSector; //结束扇区
BYTE bEndCylinder; //结束磁道
DWORD dwLBAStart; //分区起始扇区索引
DWORD dwLBASectors; //分区总扇区数

主引导扇区只有4个分区表,因此你只能给硬盘分4个主分区。
(问:为什么有人电脑有很多分区呢?答:他其实是用了逻辑分区,逻辑分区有个虚拟MBR。详情以后再讲)

可以看到MBR有两种表示分区位置和大小的方式,一种是CHS寻址方式(磁道、磁头、扇区的“3D”寻址方式),一种是LBA寻址方式(整个硬盘是一个“扇区数组”,用一个32位(本来LBA是48位)的扇区索引来表示)。
MBR现在有点过时了,目前流行GPT分区。 MBR用的是32位LBA,因此最大寻址只有2TB的硬盘空间。
bActive的值必须是0x00或0x80,否则不合法。

0xAA55 发表于 2014-1-26 19:48:31

送上自家硬盘反汇编一份。

00007C00 33C0       xor ax,ax
00007C02 8ED0       mov ss,ax
00007C04 BC007C      mov sp,0x7c00
00007C07 8EC0       mov es,ax
00007C09 8ED8       mov ds,ax
00007C0B BE007C      mov si,0x7c00
00007C0E BF0006      mov di,0x600
00007C11 B90002      mov cx,0x200
00007C14 FC        cld
00007C15 F3A4       rep movsb
00007C17 50        push ax
00007C18 681C06      push word 0x61c
00007C1B CB        retf
0000061C FB        sti
0000061D B90400      mov cx,0x4
00000620 BDBE07      mov bp,0x7be
00000623 807E0000     cmp byte ,0x0
00000627 7C0B       jl 0x634
00000629 0F850E01     jnz word 0x73b
0000062D 83C510      add bp,byte +0x10
00000630 E2F1       loop 0x623
00000632 CD18       int 0x18
00000634 885600      mov ,dl
00000637 55        push bp
00000638 C6461105     mov byte ,0x5
0000063C C6461000     mov byte ,0x0
00000640 B441       mov ah,0x41
00000642 BBAA55      mov bx,0x55aa
00000645 CD13       int 0x13
00000647 5D        pop bp
00000648 720F       jc 0x659
0000064A 81FB55AA     cmp bx,0xaa55
0000064E 7509       jnz 0x659
00000650 F7C10100     test cx,0x1
00000654 7403       jz 0x659
00000656 FE4610      inc byte
00000659 6660       pushad
0000065B 807E1000     cmp byte ,0x0
0000065F 7426       jz 0x687
00000661 666800000000   push dword 0x0
00000667 66FF7608     push dword
0000066B 680000      push word 0x0
0000066E 68007C      push word 0x7c00
00000671 680100      push word 0x1
00000674 681000      push word 0x10
00000677 B442       mov ah,0x42
00000679 8A5600      mov dl,
0000067C 8BF4       mov si,sp
0000067E CD13       int 0x13
00000680 9F        lahf
00000681 83C410      add sp,byte +0x10
00000684 9E        sahf
00000685 EB14       jmp short 0x69b
00000687 B80102      mov ax,0x201
0000068A BB007C      mov bx,0x7c00
0000068D 8A5600      mov dl,
00000690 8A7601      mov dh,
00000693 8A4E02      mov cl,
00000696 8A6E03      mov ch,
00000699 CD13       int 0x13
0000069B 6661       popad
0000069D 731C       jnc 0x6bb
0000069F FE4E11      dec byte
000006A2 750C       jnz 0x6b0
000006A4 807E0080     cmp byte ,0x80
000006A8 0F848A00     jz word 0x736
000006AC B280       mov dl,0x80
000006AE EB84       jmp short 0x634
000006B0 55        push bp
000006B1 32E4       xor ah,ah
000006B3 8A5600      mov dl,
000006B6 CD13       int 0x13
000006B8 5D        pop bp
000006B9 EB9E       jmp short 0x659
000006BB 813EFE7D55AA   cmp word ,0xaa55
000006C1 756E       jnz 0x731
000006C3 FF7600      push word
000006C6 E88D00      call word 0x756
000006C9 7517       jnz 0x6e2
000006CB FA        cli
000006CC B0D1       mov al,0xd1
000006CE E664       out 0x64,al
000006D0 E88300      call word 0x756
000006D3 B0DF       mov al,0xdf
000006D5 E660       out 0x60,al
000006D7 E87C00      call word 0x756
000006DA B0FF       mov al,0xff
000006DC E664       out 0x64,al
000006DE E87500      call word 0x756
000006E1 FB        sti
000006E2 B800BB      mov ax,0xbb00
000006E5 CD1A       int 0x1a
000006E7 6623C0      and eax,eax
000006EA 753B       jnz 0x727
000006EC 6681FB54435041  cmp ebx,0x41504354
000006F3 7532       jnz 0x727
000006F5 81F90201     cmp cx,0x102
000006F9 722C       jc 0x727
000006FB 666807BB0000   push dword 0xbb07
00000701 666800020000   push dword 0x200
00000707 666808000000   push dword 0x8
0000070D 6653       push ebx
0000070F 6653       push ebx
00000711 6655       push ebp
00000713 666800000000   push dword 0x0
00000719 6668007C0000   push dword 0x7c00
0000071F 6661       popad
00000721 680000      push word 0x0
00000724 07        pop es
00000725 CD1A       int 0x1a
00000727 5A        pop dx
00000728 32F6       xor dh,dh
0000072A EA007C0000    jmp word 0x0:0x7c00
0000072F CD18       int 0x18
00000731 A0B707      mov al,
00000734 EB08       jmp short 0x73e
00000736 A0B607      mov al,
00000739 EB03       jmp short 0x73e
0000073B A0B507      mov al,
0000073E 32E4       xor ah,ah
00000740 050007      add ax,0x700
00000743 8BF0       mov si,ax
00000745 AC        lodsb
00000746 3C00       cmp al,0x0
00000748 7409       jz 0x753
0000074A BB0700      mov bx,0x7
0000074D B40E       mov ah,0xe
0000074F CD10       int 0x10
00000751 EBF2       jmp short 0x745
00000753 F4        hlt
00000754 EBFD       jmp short 0x753
00000756 2BC9       sub cx,cx
00000758 E464       in al,0x64
0000075A EB00       jmp short 0x75c
0000075C 2402       and al,0x2
0000075E E0F8       loopne 0x758
00000760 2402       and al,0x2
00000762 C3        ret
00000763 49        dec cx
00000764 6E        outsb
00000765 7661       jna 0x7c8
00000767 6C        insb
00000768 6964207061    imul sp,,word 0x6170
0000076D 7274       jc 0x7e3
0000076F 6974696F6E    imul si,,word 0x6e6f
00000774 207461      and ,dh
00000777 626C65      bound bp,
0000077A 004572      add ,al
0000077D 726F       jc 0x7ee
0000077F 7220       jc 0x7a1
00000781 6C        insb
00000782 6F        outsw
00000783 61        popaw
00000784 64696E67206F   imul bp,,word 0x6f20
0000078A 7065       jo 0x7f1
0000078C 7261       jc 0x7ef
0000078E 7469       jz 0x7f9
00000790 6E        outsb
00000791 67207379     and ,dh
00000795 7374       jnc 0x80b
00000797 656D       gs insw
00000799 004D69      add ,cl
0000079C 7373       jnc 0x811
0000079E 696E67206F    imul bp,,word 0x6f20
000007A3 7065       jo 0x80a
000007A5 7261       jc 0x808
000007A7 7469       jz 0x812
000007A9 6E        outsb
000007AA 67207379     and ,dh
000007AE 7374       jnc 0x824
000007B0 656D       gs insw
000007B2 0000       add ,al
000007B4 00637B      add ,ah
000007B7 9A1F45E0A7    call word 0xa7e0:0x451f
000007BC 670000      add ,al
000007BF 0000       add ,al
000007C1 0000       add ,al
000007C3 0000       add ,al
000007C5 0000       add ,al
000007C7 0000       add ,al
000007C9 0000       add ,al
000007CB 0000       add ,al
000007CD 0000       add ,al
000007CF 0000       add ,al
000007D1 0000       add ,al
000007D3 0000       add ,al
000007D5 0000       add ,al
000007D7 0000       add ,al
000007D9 0000       add ,al
000007DB 0000       add ,al
000007DD 0000       add ,al
000007DF 0000       add ,al
000007E1 0000       add ,al
000007E3 0000       add ,al
000007E5 0000       add ,al
000007E7 0000       add ,al
000007E9 0000       add ,al
000007EB 0000       add ,al
000007ED 0000       add ,al
000007EF 0000       add ,al
000007F1 0000       add ,al
000007F3 0000       add ,al
000007F5 0000       add ,al
000007F7 0000       add ,al
000007F9 0000       add ,al
000007FB 0000       add ,al
000007FD 0055AA      add ,dl

0xAA55 发表于 2014-1-26 19:49:42

可以看到这个MBR先把自己移动到0x600处,用BP指向当前DPT,循环查找活动分区,没找到活动分区则INT 0x18,否则继续,检测INT 0x13扩展磁盘功能是否可用,如果可用就用LBA寻址读取分区DBR,否则用CHS寻址读取DBR。读取DBR到0x7C00,判断签名是否为0xAA55,如果不是继续读取,如果是,转入运行。如果都不能运行,打印文本“分区表无效”、“没有操作系统”、“引导出错”,最后当机。
循环节用得不像一个汇编玩得好的人写的,难道是用TC写的?


这个MBR用BIOS中断0x10功能0xE输出字符到屏幕,详见:
http://www.ctyme.com/intr/rb-0106.htm
检查过BIOS的扩展读取功能,使用了BIOS中断0x13功能0x41(BX=0x55AA,注意不是0xAA55),详见:
http://www.ctyme.com/intr/rb-0706.htm
用过BIOS扩展LBA寻址读取功能INT 0x13功能0x42,详见:
http://www.ctyme.com/intr/rb-0708.htm
也用过BIOS普通CHS寻址读取功能INT 0x13功能0x2,详见:
http://www.ctyme.com/intr/rb-0607.htm

0xAA55 发表于 2015-12-11 17:12:05

附上一份自己写的MBR引导代码。org 0x600
bits 16

Start:
;定位段
xor ax,ax
mov ds,ax
mov es,ax
mov ss,ax;建立栈
mov sp,0x7c00

;移动自身到0x600
cld
mov si,0x7c00
mov di,0x600
mov cx,256
rep movsw;按字拷贝,256个字
jmp 0x600+(NewStart-Start);绝对

;低位内存的指令开始的位置
NewStart:

;寻找可引导分区
FindPart:
mov cx,4;4个分区表项
mov bx,DPT1
test byte,0x80
jnz GetPart
.BadPart:
add bx,16;每分区表项16字节
loop FindPart

NoBootPart:
;没找到可引导分区
mov si,NoPartMsg
mov cx,NoPartMsgLen
call ShowStr
xor ax,ax
int 0x16
int 0x18

GetPart:
;已找到可引导分区,bx指向分区表头
mov ax,
mov ,ax
mov ax,
mov ,ax
mov ah,0x42
mov si,DAP
;dl的值本来就是这个磁盘的序号。一开始就没改变过它。
int 0x42
cmp word,0xAA55
jnz FindPart.BadPart
jmp 0x7c00

;过程:显示字符串
;参数:
;si 字符串指针
;cx 字符串长度
ShowStr:
mov ah,0xe
mov bx,0x0007
.CharOut:
lodsb
or al,al
jz .NoMoreChar
int 0x10
loop .CharOut
.NoMoreChar:
ret

DAP:                ;磁盘地址包,用于读取硬盘
.SizeOf:
dw .End-DAP        ;包大小
.NbPacket:
dw 1                ;要传输的块数量
.Buf:                ;缓冲区
dw 0x7c00        ;偏移
dw 0                ;段
.LBA:
dq 0
.End:

NoPartMsg db "Invalid system disk."
NoPartMsgLen equ $-NoPartMsg

;到分区表前的部分填充0
times (510-64)-($-$$) db 0

;分区表,共64个字节
DPT1: times 16 db 0
DPT2: times 16 db 0
DPT3: times 16 db 0
DPT4: times 16 db 0

Sign dw 0xAA55;签名

55AA 发表于 2017-10-11 23:05:37

这个要Mark

BUG菌 发表于 2020-2-20 15:59:30

计算机相关的计数原理还是要学习一个的。Mark了
页: [1]
查看完整版本: 【操作系统】MBR