主引导扇区及主引导记录MBR的详细说明-程序员宅基地

技术标签: 操作系统  

引导扇区在每个分区里都存在,但是我们常说的*主引导扇区*是硬盘的 
第一物理扇区。它由两个部分组成:即主引导记录MBR和硬盘分区表DPT。在 
总共512字节的主引导分区里其中MBR占446个字节(偏移0--偏移1BDH),DPT 
占64个字节(偏移1BEH--偏移1FDH),最后两个字节“55,AA”(偏移1FEH 
偏移1FFH)是分区的结束标志。大致的结构如下图: 
0000 |------------------------------------------------| 
| | 
| | 
| Main Boot Record | 
| | 
| | 
| 主引导记录(446字节) | 
| | 
| | 
| | 
01BD | | 
01BE |------------------------------------------------| 
| | 
01CD | 分区信息 1(16字节) | 
01CE |------------------------------------------------| 
| | 
01DD | 分区信息 2(16字节) | 
01DE |------------------------------------------------| 
| | 
01ED | 分区信息 3(16字节) | 
01EE |------------------------------------------------| 
| | 
01FD | 分区信息 4(16字节) | 
|------------------------------------------------| 
| 01FE | 01FF | 
| 55 | AA | 
|------------------------------------------------| 
图一:主引导扇区结构图 
主引导记录中包含了硬盘的一系列参数和一段引导程序。引导程序主要 
是用来在系统硬件自检完后引导具有激活标志的分区上的操作系统。它执行 
到最后的是一条JMP指令跳到操作系统的引导程序去。这里往往是引导型病 
毒的注入点,也是各种多系统引导程序的注入点。但是由于引导程序本身完 
成的功能比较简单,所以我们可以完全地判断该引导程序的合法性(看JMP 
指令的合法性),因而也易于修复。象命令fdisk/mbr可以修复MBR和KV300 
这类软件可以查杀任意类型的引导型病毒,就是这个原因。 
往下来是硬盘的分区表,由4个16字节的分区信息表组成。每个信息表的 
结构如下: 
偏移 长度 所表达的意义 
0 字节 分区状态: 如0-->非活动分区 
80--> 活动分区 
1 字节 该分区起始头(HEAD) 
2 字 该分区起始扇区和起始柱面 
4 字节 该分区类型:如82--> Linux Native分区 
83--> Linux Swap 分区 
5 字节 该分区终止头(HEAD) 
6 字 该分区终止扇区和终止柱面 
8 双字 该分区起始绝对分区 
C 双字 该分区扇区数 
最后的两个标志“55 AA”是分区表的结束标志,如果这两个标志被修改 
(有些病毒就会修改这两个标志),则系统引导时将报告找不到有效的分区表。

说明:硬盘主引导记录独立于操作系统,但又和操作系统息息相关——很多时候它又是由 
; 操作系统所提供的工具所生成(例外的情况是您使用了其他的分区工具,不过它又运行在 
; 什么操作系统中呢?;()。 

; 如果您安装了Windows 98(我现在暂时不能接触95下的主引导记录,总不能用95重装我的 
; 系统吧?)操作系统,那您机器上的主引导记录已经与以前的大有不同了,通过下面的分析 
; 您一定能对Windows 98为什么要更改主引导记录有所了解——它已经开始支持扩展Int13h 
; 了!并且这个主引导记录的编程技巧更是我们应该学习的。 

; 主引导记录包括代码、数据两部分。它在被BIOS中断Int19h装入内存后获得控制权。数据 
; 部分最重要的当然是分区表了!彻底熟悉主引导记录,可以帮助我们了解系统的引导过程, 
; 处理因主引导记录损坏所造成的无法引导故障,消除引导型计算机病毒,更使我们能通过 
; 修改主引导记录完成我们希望的工作:如多重引导,系统加软锁等... 

; BIOS中断总是把主引导记录所在扇区(硬盘的0头0道1扇区)的内容(包括代码和数据) 
; 装入内存0000:7C00起始的区域,然后检验该扇区内容的最后两个字节是不是“AA55”, 
; 如果不是,那么对不起,Int19h将不把控制权交给主引导记录;若是,则下面的主引导记录 
; 才能获得了控制权了(Int19通过跳转指令交转控制权): 

; 二进制形式的主引导记录: 
0000:0600 33 C0 8E D0 BC 00 7C FB-50 07 50 1F FC BE 1B 7C 3.....|.P.P....| 
0000:0610 BF 1B 06 50 57 B9 E5 01-F3 A4 CB BE BE 07 B1 04 ...PW........... 
0000:0620 38 2C 7C 09 75 15 83 C6-10 E2 F5 CD 18 8B 14 8B 8,|.u........... 
0000:0630 EE 83 C6 10 49 74 16 38-2C 74 F6 BE 10 07 4E AC ....It.8,t....N. 
0000:0640 3C 00 74 FA BB 07 00 B4-0E CD 10 EB F2 89 46 25 <.t...........F% 
0000:0650 96 8A 46 04 B4 06 3C 0E-74 11 B4 0B 3C 0C 74 05 ..F...<.t...<.t. 
0000:0660 3A C4 75 2B 40 C6 46 25-06 75 24 BB AA 55 50 B4 :[email protected]%.u$..UP. 
0000:0670 41 CD 13 58 72 16 81 FB-55 AA 75 10 F6 C1 01 74 A..Xr...U.u....t 
0000:0680 0B 8A E0 88 56 24 C7 06-A1 06 EB 1E 88 66 04 BF ....V$.......f.. 
0000:0690 0A 00 B8 01 02 8B DC 33-C9 83 FF 05 7F 03 8B 4E .......3.......N 
0000:06A0 25 03 4E 02 CD 13 72 29-BE 2D 07 81 3E FE 7D 55 %.N...r).-..>.}U 
0000:06B0 AA 74 5A 83 EF 05 7F DA-85 F6 75 83 BE 1A 07 EB .tZ.......u..... 
0000:06C0 8A 98 91 52 99 03 46 08-13 56 0A E8 12 00 5A EB ...R..F..V....Z. 
0000:06D0 D5 4F 74 E4 33 C0 CD 13-EB B8 00 00 80 49 12 00 .Ot.3........I.. 
0000:06E0 56 33 F6 56 56 52 50 06-53 51 BE 10 00 56 8B F4 V3.VVRP.SQ...V.. 
0000:06F0 50 52 B8 00 42 8A 56 24-CD 13 5A 58 64 10 72 PR..B.V$..ZX.d.r 
0000:0700 0A 40 75 01 42 80 C7 02-E2 F7 F8 5E C3 EB 74 B7 [email protected]......^..t. 
0000:0710 D6 C7 F8 B1 ED CE DE D0-A7 00 BC D3 D4 D8 B2 D9 ................ 
0000:0720 D7 F7 CF B5 CD B3 CA B1-B3 F6 B4 ED 00 4D 69 73 .............Mis 
0000:0730 73 69 6E 67 20 6F 70 65-72 61 74 69 6E 67 20 73 sing operating s 
0000:0740 79 73 74 65 6D 00 00 00-00 00 00 00 00 00 00 00 ystem........... 
0000:0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0760 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0770 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0780 00 00 00 8B FC 1E 57 8B-F5 CB 00 00 00 00 00 00 ......W......... 
0000:0790 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:07B0 00 00 00 00 00 00 00 00-86 D8 00 00 00 00 80 01 ................ 
0000:07C0 01 00 06 3F 3F FD 3F 00-00 00 41 A0 0F 00 00 00 ...??.?...A..... 
0000:07D0 01 FE 05 3F FF FE 80 A0-0F 00 C0 4F 2F 00 00 00 ...?.......O/... 
0000:07E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:07F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U. 

; 反汇编结果 

; 0000:7C00~0000:7C1A:初始化各个段寄存器、堆栈指针,最后将主引导记录在内存中搬家,腾出其所占内 
; 存空间以供装入分区引导记录。 
0000:7C00 33C0 XOR AX,AX ;AX寄存器清0 
0000:7C02 8ED0 MOV SS,AX ;SS=0 
0000:7C04 BC007C MOV SP,7C00 ;装填栈指针——SS:SP=0000:7C00 
0000:7C07 FB STI ;开中断(装填栈指针时为避免硬件中断引起栈混乱应关中断) 
0000:7C08 50 PUSH AX ; 
0000:7C09 07 POP ES ;装填附加数据段寄存器ES=0 
0000:7C0A 50 PUSH AX ; 
0000:7C0B 1F POP DS ;装填数据段寄存器DS=0 
0000:7C0C FC CLD ;规定其后的串操作为正向串操作 
0000:7C0D BE1B7C MOV SI,7C1B ;源指针 
0000:7C10 BF1B06 MOV DI,061B ;目的指针 
0000:7C13 50 PUSH AX ; 
0000:7C14 57 PUSH DI ;看看0000:7C1A——构造一个跳转 
0000:7C15 B9E501 MOV CX,01E5 ; 
0000:7C18 F3 REPZ ; 
0000:7C19 A4 MOVSB 
; ;0000:7C1B起始的CX字节传送至0000:061B起始的区域 
0000:7C1A CB RETF ;跳转到0000:061B(这是一种技巧跳转) 

; 为直观起见,下面的地址按实际运行时的地址给出。 
; 0000:061B~0000:062B:对分区表进行初步检验,一旦检测到某分区表项状态字节大于等于80h,就通过(当 
; 然,在此之前如果检测到某项分区表的状态字节小于80h,就转错误处理。当然,如果四个分区项的状态字节 
; 都为零,主引导记录就会调用BIOS-ROM的INT 18h,显示"PRESS A KEY TO REBOOT"信息等待你的操作。 
0000:061B BEBE07 MOV SI,07BE ;SI指向第一个分区表项,这时CX=0 
0000:061E B104 MOV CL,04 ;分区表共四个表项 
0000:0620 382C CMP [SI],CH ; 
0000:0622 7C09 JL 062D ;大于等于80h转[注意JL指令:(SF xor OF)=1则转] 
0000:0624 7515 JNZ 063B ;不为0则[SI]一定小于80h,只能转错误处理了! 
0000:0626 83C610 ADD SI,+10 ;为零则检查下一表项 
0000:0629 E2F5 LOOP 0620 ;检查下一表项 
0000:062B CD18 INT 18 ;四表项的状态字节都为0,则系统只好调用INT 18h了! 

; 0000:062D~0000:0639:检查剩余的分区表项——状态字节必须为零,否则显示错误信息“分区表无效”然 
; 后当机!拜托,微软搞错没有,怎么用中文提示信息?真TM傻得可爱! 
; 这里还有个小BUG,前面放行原则是只要状态字节大于等于80h,那么如果这个字节是诸如A0h、E5h之类数值 
; 呢?嘿嘿,这个引导记录统统认为是有效的可引导分区了! 
0000:062D 8B14 MOV DX,[SI] ;为读分区引导记录做准备:磁头号→DH,驱动器号→DL 
0000:062F 8BEE MOV BP,SI ;SI→BP,保存可引导分区表项的指针 

0000:0631 83C610 ADD SI,+10 ;其余的分区表项还要检查检查的 
0000:0634 49 DEC CX ; 
0000:0635 7416 JZ 064D ;CX=0则检查顺利通过,转继续 
0000:0637 382C CMP [SI],CH ; 
0000:0639 74F6 JZ 0631 ;为零,是合法表项,再查下一表项 

; 0000:063B~0000:064B:执行错误处理——报告错误信息后当机 
0000:063B BE1007 MOV SI,0710 ;错误信息字符串偏移+1→SI 
0000:063E 4E DEC SI ;SI-1→SI 
0000:063F AC LODSB ;SI+1→SI 
0000:0640 3C00 CMP AL,00 ; 
0000:0642 74FA JZ 063E ;AL=0则表明一条错误信息显示完毕,系统陷入一个死循环 
0000:0644 BB0700 MOV BX,0007 ;字符方式显示 
0000:0647 B40E MOV AH,0E ; 
0000:0649 CD10 INT 10 ;以写电传方式显示信息(只显示一个字符) 
0000:064B EBF2 JMP 063F ;显示下一个字符,直到遇到提示信息结束为止 

; 0000:064D~0000:0662:判断可引导分区的分区类型,然后转相应处理程序。 
0000:064D 894625 MOV [BP+25],AX ;BP=指向第一个可引导分区表项的指针,这时AX=0000h 
;使用长度最短的指令将[BP+25]起始的两个单元清零 
;这两个单元将被用来存放中间变量 
0000:0650 96 XCHG SI,AX ;此时SI清零的最佳指令选择(仅1字节),将服务于0000:06B8 
0000:0651 8A4604 MOV AL,[BP+04] ;取分区类型(本例是“06”喽——FAT16主DOS分区) 
0000:0654 B406 MOV AH,06 ;为扩展INT 13h无法使用做好更改分区类型的准备 
0000:0656 3C0E CMP AL,0E ;0Eh:需要用扩展INT 13h访问的FAT16主DOS分区 
0000:0658 7411 JZ 066B ;0Eh类型的分区转066Bh 
0000:065A B40B MOV AH,0B ; 
0000:065C 3C0C CMP AL,0C ;0Ch:需要用扩展INT 13h访问的FAT32分区 
0000:065E 7405 JZ 0665 ;0Ch类型的分区转0665h先行预处理 
0000:0660 3AC4 CMP AL,AH ;0Bh:用传统INT 13h就可以访问的FAT32分区 
0000:0662 752B JNZ 068F ;其他类型的分区转068Fh 

; 0000:0664~0000:06A1:根据分区类型和分区表表项内容进行读取分区引导记录前的处理工作 
0000:0664 40 INC AX &nbs 
p; ;★★★0Bh类型的分区由此开始处理,此条指令用意是清ZF位 
0000:0665 C6462506 MOV BYTE PTR [BP+25],06 ;★★★0Ch类型的分区由此开始处理 
;为什么取值06,一时没有自圆我说的解释,请耐心几天吧。 
0000:0669 7524 JNZ 068F ;请注意上面指令对ZF位的影响:0Bh类型分区转,0Ch则不转 
; 0000:066B~0000:068C这段代码仅当分区类型是0Ch、0Eh才有获得执行的机会 
0000:066B BBAA55 MOV BX,55AA ;★★★0Eh类型的分区由此开始处理 
0000:066E 50 PUSH AX ; 
0000:066F B441 MOV AH,41 ;扩展INT 13h功能,检测BIOS是否已经支持扩展INT13h 
0000:0671 CD13 INT 13 ;入口参数:BX=55AAh,DL=驱动器号,AH=41h 
0000:0673 58 POP AX ;执行完恢复AX为060Eh 
0000:0674 7216 JB 068C ;不支持则转 
0000:0676 81FB55AA CMP BX,AA55 ; 
0000:067A 7510 JNZ 068C ;扩展INT13h不可用也转 
0000:067C F6C101 TEST CL,01 ;测试扩展盘访问是否被支持 
0000:067F 740B JZ 068C ;不支持还转 
; 因为扩展INT13h方式读盘与标准INT13h方式读盘有很大差别,所以0000:0686处指令修改其后的代码以保证按 
; 照扩展读方式读分区引导扇区时能正确跳转到相应的处理程序中。 
0000:0681 8AE0 MOV AH,AL ;分区类型→AH 
0000:0683 885624 MOV [BP+24],DL ;保存驱动器号→[BP+24] 
0000:0686 C706A106EB1E MOV WORD PTR [06A1],1EEB ;修改0000:06A1处代码为"JMP 06C1" 
0000:068C 886604 MOV [BP+04],AH ;注意:如果扩展INT13h不能使用则A改分区类型为06,但如果 
;扩展INT13h能使用,则仍保持原分区类型不变 
0000:068F BF0A00 MOV DI,000A ;★★★其它类型分区由此开始处理。此条指令初始化计数器 
0000:0692 B80102 MOV AX,0201 ;AH:读操作,AL:读取1个扇区的内容 
0000:0695 8BDC MOV BX,SP ;SP=7C00→BX,指定分区引导记录装入内存的位置偏移 
0000:0697 33C9 XOR CX,CX ;CX清零 
0000:0699 83FF05 CMP DI,+05 ;注意5 
0000:069C 7F03 JG 06A1 ;大于则转去读由分区表指定的分区引导扇区 
0000:069E 8B4E25 MOV CX,[BP+25] ;小于则证明所读分区表指定的引导扇区无合法的引导记录, 
;改按???再读,毕竟多一种选择多一次机会嘛!;) 
; 以下标有①②者请注意它们的地址都是一样的,就是说实际运行中只可能是二者之一,但为了分析之方便,我 
; 把两者都列了出来以供对比,阅读时千万别看成是两条指令了啊! 
①0000:06A1 034E02 ADD CX,[BP+02] ;获取分区引导扇区所在的柱面号和物理扇区号 
②0000:06A1 EB1E JMP 06C1 ;如果分区类型是0Ch、0Eh而且扩展读能使用则执行该指令 

; 0000:06A4:将可引导分区的分区引导记录装入内存指定区域 
; 入口参数:AH=功能号,02为读盘操作;AL=一次读取的扇区数 
; ES:BX=读入内存的起始地址 
; CH=10位柱面号的低8位;CL:高两位是10位柱面号的高两位,低6位是物理扇区号 
; DH=磁头号;DL=驱动器号,最高位(即位7)为0是软盘,为1是硬盘 
0000:06A4 CD13 INT 13 ;读分区引导记录到0000:7C00起始的区域 


0000:06A6 7229 JB 06D1 ;不成功转 
0000:06A8 BE2D07 MOV SI,072D ;错误信息字符串偏移→SI 
0000:06AB 813EFE7D55AA CMP WORD PTR [7DFE],AA55 ;分区引导记录合法吗? 
0000:06B1 745A JZ 070D ;合法则转(这是主引导记录唯一的正常出口) 
0000:06B3 83EF05 SUB DI,+05 ;不合法则为换读其他扇区做准备 
0000:06B6 7FDA JG 0692 ;只有一次换读扇区的机会! 

; 0000:06B8~0000:06BF:错误预处理 
0000:06B8 85F6 TEST SI,SI ;测试SI值是否为0,其意义在于确定该显示哪条信息 
0000:06BA 7583 JNZ 063F ;不为0则转错误处理,显示“Missing operating system” 
0000:06BC BE1A07 MOV SI,071A ;错误信息字符串偏移→SI 
0000:06BF EB8A JMP 064B ;转错误处理,显示“加载操作系统时出错” 

; 0000:06C1~0000:06CF:整理扩展读所需入口参 
p; ;★★★0Bh类型的分区由此开始处理,此条指令用意是清ZF位 
0000:0665 C6462506 MOV BYTE PTR [BP+25],06 ;★★★0Ch类型的分区由此开始处理 
;为什么取值06,一时没有自圆我说的解释,请耐心几天吧。 
0000:0669 7524 JNZ 068F ;请注意上面指令对ZF位的影响:0Bh类型分区转,0Ch则不转 
; 0000:066B~0000:068C这段代码仅当分区类型是0Ch、0Eh才有获得执行的机会 
0000:066B BBAA55 MOV BX,55AA ;★★★0Eh类型的分区由此开始处理 
0000:066E 50 PUSH AX ; 
0000:066F B441 MOV AH,41 ;扩展INT 13h功能,检测BIOS是否已经支持扩展INT13h 
0000:0671 CD13 INT 13 ;入口参数:BX=55AAh,DL=驱动器号,AH=41h 
0000:0673 58 POP AX ;执行完恢复AX为060Eh 
0000:0674 7216 JB 068C ;不支持则转 
0000:0676 81FB55AA CMP BX,AA55 ; 
0000:067A 7510 JNZ 068C ;扩展INT13h不可用也转 
0000:067C F6C101 TEST CL,01 ;测试扩展盘访问是否被支持 
0000:067F 740B JZ 068C ;不支持还转 
; 因为扩展INT13h方式读盘与标准INT13h方式读盘有很大差别,所以0000:0686处指令修改其后的代码以保证按 
; 照扩展读方式读分区引导扇区时能正确跳转到相应的处理程序中。 
0000:0681 8AE0 MOV AH,AL ;分区类型→AH 
0000:0683 885624 MOV [BP+24],DL ;保存驱动器号→[BP+24] 
0000:0686 C706A106EB1E MOV WORD PTR [06A1],1EEB ;修改0000:06A1处代码为"JMP 06C1" 
0000:068C 886604 MOV [BP+04],AH ;注意:如果扩展INT13h不能使用则A改分区类型为06,但如果 
;扩展INT13h能使用,则仍保持原分区类型不变 
0000:068F BF0A00 MOV DI,000A ;★★★其它类型分区由此开始处理。此条指令初始化计数器 
0000:0692 B80102 MOV AX,0201 ;AH:读操作,AL:读取1个扇区的内容 
0000:0695 8BDC MOV BX,SP ;SP=7C00→BX,指定分区引导记录装入内存的位置偏移 
0000:0697 33C9 XOR CX,CX ;CX清零 
0000:0699 83FF05 CMP DI,+05 ;注意5 
0000:069C 7F03 JG 06A1 ;大于则转去读由分区表指定的分区引导扇区 
0000:069E 8B4E25 MOV CX,[BP+25] ;小于则证明所读分区表指定的引导扇区无合法的引导记录, 
;改按???再读,毕竟多一种选择多一次机会嘛!;) 
; 以下标有①②者请注意它们的地址都是一样的,就是说实际运行中只可能是二者之一,但为了分析之方便,我 
; 把两者都列了出来以供对比,阅读时千万别看成是两条指令了啊! 
①0000:06A1 034E02 ADD CX,[BP+02] ;获取分区引导扇区所在的柱面号和物理扇区号 
②0000:06A1 EB1E JMP 06C1 ;如果分区类型是0Ch、0Eh而且扩展读能使用则执行该指令 

; 0000:06A4:将可引导分区的分区引导记录装入内存指定区域 
; 入口参数:AH=功能号,02为读盘操作;AL=一次读取的扇区数 
; ES:BX=读入内存的起始地址 
; CH=10位柱面号的低8位;CL:高两位是10位柱面号的高两位,低6位是物理扇区号 
; DH=磁头号;DL=驱动器号,最高位(即位7)为0是软盘,为1是硬盘 
0000:06A4 CD13 INT 13 ;读分区引导记录到0000:7C00起始的区域 


0000:06A6 7229 JB 06D1 ;不成功转 
0000:06A8 BE2D07 MOV SI,072D ;错误信息字符串偏移→SI 
0000:06AB 813EFE7D55AA CMP WORD PTR [7DFE],AA55 ;分区引导记录合法吗? 
0000:06B1 745A JZ 070D ;合法则转(这是主引导记录唯一的正常出口) 
0000:06B3 83EF05 SUB DI,+05 ;不合法则为换读其他扇区做准备 
0000:06B6 7FDA JG 0692 ;只有一次换读扇区的机会! 

; 0000:06B8~0000:06BF:错误预处理 
0000:06B8 85F6 TEST SI,SI ;测试SI值是否为0,其意义在于确定该显示哪条信息 
0000:06BA 7583 JNZ 063F ;不为0则转错误处理,显示“Missing operating system” 
0000:06BC BE1A07 MOV SI,071A ;错误信息字符串偏移→SI 
0000:06BF EB8A JMP 064B ;转错误处理,显示“加载操作系统时出错” 

; 0000:06C1~0000:06CF:整理扩展读所需入口参 
数,然后调用扩展读子程序 
; 这段代码只有在以扩展读方式读取分区引导记录时才有机会获得执行 
0000:06C1 98 CBW ;转换字节AL为字AX,执行后,AX中是一次要读的扇区数 
0000:06C2 91 XCHG CX,AX ;AX→CX,CX→AX,执行后,CX中是一次要读的扇区数 
0000:06C3 52 PUSH DX ; 
0000:06C4 99 CWD ;将字AX转换为双字→DX,AX 
0000:06C5 034608 ADD AX,[BP+08] ; 
0000:06C8 13560A ADC DX,[BP+0A] ;执行后,DX:AX=LBA绝对物理扇区号 
0000:06CB E81200 CALL 06E0 ;调用扩展读子程序 
0000:06CE 5A POP DX ; 
0000:06CF EBD5 JMP 06A6 ; 

; 0000:06D1~0000:06D8分区引导记录装入失败时的处理 
0000:06D1 4F DEC DI ;计数器减1 
0000:06D2 74E4 JZ 06B8 ;五次读盘均未成功则转错误处理(注意这时SI=0) 
0000:06D4 33C0 XOR AX,AX ;置功能号 
0000:06D6 CD13 INT 13 ;复位磁盘系统 
0000:06D8 EBB8 JMP 0692 ;再读 


0000:06DA 00 00 80 49 12 00 ...I.. 

; 0000:06E0~0000:070C:使用扩展INT 13h功能读取分区引导记录的子程序 
; 调用时,SP=7BFE。这段程序利用压栈寄存器方式构造了一个磁盘地址包,请注意体会。另外,0000:06FC处 
; 的一条指令就释放了几乎全部由本段程序占用的栈空间,构思之巧妙,绝对需要我们学习! 
; 所以,分析该段程序,一个重点应放在栈的变化上。 
0000:06E0 56 PUSH SI ;保存SI——注意,这次压栈并不构造磁盘地址包 
0000:06E1 33F6 XOR SI,SI ;清零 
0000:06E3 56 PUSH SI ; 
0000:06E4 56 PUSH SI ; 
0000:06E5 52 PUSH DX ; 
0000:06E6 50 PUSH AX ;以上四条指令压栈的是扇区LBA号码*2 
0000:06E7 06 PUSH ES ;压栈内存目标缓冲区首址段址 
0000:06E8 53 PUSH BX ;压栈内存目标缓冲区首址偏移 
0000:06E9 51 PUSH CX ;压栈所读扇区数 
0000:06EA BE1000 MOV SI,0010 ;注意SI的高8位对应着磁盘地址包的保留字节,必须为0 
0000:06ED 56 PUSH SI ;压栈磁盘地址包包长,执行完本条指令一个包已经构造完毕 
0000:06EE 8BF4 MOV SI,SP ;规定磁盘地址包偏移指针,这时SP=7BEA 
0000:06F0 50 PUSH AX ;保存AX 
0000:06F1 52 PUSH DX ;保存DX 
0000:06F2 B80042 MOV AX,4200 ;置扩展读功能号 
0000:06F5 8A5624 MOV DL,[BP+24] ;取驱动器号,参照0000:0683 
; 入口参数:AH=功能号,02为读盘操作;DL=驱动器号 
; DS:SI=16字节磁盘地址包——第0字节:包长度(固定为10h);第1字节:保留,必须为0; 
; 第2、3字节:所读扇区数;第4~5字节:内存目标缓冲区首址偏移; 
; 第6~7字节:内存目标缓冲区首址段址; 第8~15字节:扇区LBA号码 
; 出口参数:成功则AH=0;错误则AH=错误代码 
0000:06F8 CD13 INT 13 ;执行扩展读操作 
0000:06FA 5A POP DX ; 
0000:06FB 58 POP AX ; 
0000:06FC 8D6410 LEA SP,[SI+10] ;7BEA+10h=7BFA→SP(注意是取偏移而不是取单元内容) 
0000:06FF 720A JB 070B ;扩展读不成功转 
0000:0701 40 INC AX ; 
0000:0702 7501 JNZ 0705 ; 
0000:0704 42 INC DX ;AX加1溢出时(比如0FFFFh+1)DX才加1 
0000:0705 80C702 ADD BH,02 ;调整BX,使偏移量增加512字节(刚好一扇区) 
0000:0708 E2F7 LOOP 0701 ;0701~0708一段代码暂未明白其真实意图! 
0000:070A F8 CL 
C ; 
0000:070B 5E POP SI ; 
0000:070C C3 RET ; 

; 0000:070D:中继跳转 
0000:070D EB74 JMP 0783 ; 

; 070F~0745是错误信息!果然是中文Windows98生成的主引导记录,所以我要特别 
; “感谢”微软这个傻B,真难为它竟然用中文表述前两个信息!可惜真需显示的时 
; 候鬼才能看懂是什么呢!!!我K!——耍弄我们耶!? 
; 070F~0718:“分区表无效”中文信息 
; 071A~072B:“加载操作系统时出错”中文信息 
; 072D~0744:“Missing operating system”英文信息 
0000:070F B7 . 
0000:0710 D6 C7 F8 B1 ED CE DE D0-A7 00 BC D3 D4 D8 B2 D9 ................ 
0000:0720 D7 F7 CF B5 CD B3 CA B1-B3 F6 B4 ED 00 4D 69 73 .............Mis 
0000:0730 73 69 6E 67 20 6F 70 65-72 61 74 69 6E 67 20 73 sing operating s 
0000:0740 79 73 74 65 6D 00 00 00-00 00 00 00 00 00 00 00 system.......... 
0000:0750 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0760 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0770 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:0780 00 00 00 ... 

; 0000:0783~0000:0789:控制权移交 
0000:0783 8BFC MOV DI,SP ; 
0000:0785 1E PUSH DS ; 
0000:0786 57 PUSH DI ;构造一个跳转地址 
0000:0787 8BF5 MOV SI,BP ; 
0000:0789 CB RETF ;交控制权给分区引导记录(0000:7C00) 


0000:078A 00 00 00 00 00 00 ...... 
0000:0790 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:07A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 

; 07B8~07BB四个字节的内容用于什么呢?(不同机器此四字节均不同) 
; 07BE~07FD为分区表,内含四个分区表项(每表项10h字节) 
0000:07B0 00 00 00 00 00 00 00 00-86 D8 00 00 00 00 80 01 ................ 
0000:07C0 01 00 06 3F 3F FD 3F 00-00 00 41 A0 0F 00 00 00 ...??.?...A..... 
0000:07D0 01 FE 05 3F FF FE 80 A0-0F 00 C0 4F 2F 00 00 00 ...?.......O/... 
0000:07E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 
0000:07F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U. 
*1:因为物理扇区号总是从1排列而起 
*2:由此可见,就是使用LBA扩展读的功能,主引导记录却限制了分区引导扇区必须在LBA绝对物理扇区 
0FFFFFFFFh之前才有可能从该分区引导系统!

原创内容,转载请注明出处!
原文:http://www.cnblogs.com/maoshichong/articles/1857084.html

转载于:https://www.cnblogs.com/simpman/archive/2013/05/29/3105550.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34391854/article/details/94694214

智能推荐

海康威视网络摄像头开发流程(五)------- 直播页面测试_ezuikit 测试的url-程序员宅基地

文章浏览阅读3.8k次。1、将下载好的萤石js插件,添加到SoringBoot项目中。位置可参考下图所示。(容易出错的地方,在将js插件在html页面引入时,发生路径错误的问题)所以如果对页面中引入js的路径不清楚,可参考下图所示存放路径。2、将ezuikit.js引入到demo-live.html中。(可直接将如下代码复制到你创建的html页面中)<!DOCTYPE html><html lan..._ezuikit 测试的url

如何确定组态王与多动能RTU的通信方式_组态王ua-程序员宅基地

文章浏览阅读322次。第二步,在弹出的对话框选择,设备驱动—>PLC—>莫迪康—>ModbusRTU—>COM,根据配置软件选择的协议选期期,这里以此为例,然后点击“下一步”。第四步,把使用虚拟串口打勾(GPRS设备),根据需要选择要生成虚拟口,这里以选择KVCOM1为例,然后点击“下一步”设备ID即Modbus地址(1-255) 使用DTU时,为下485接口上的设备地址。第六步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“第五步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“_组态王ua

npm超详细安装(包括配置环境变量)!!!npm安装教程(node.js安装教程)_npm安装配置-程序员宅基地

文章浏览阅读9.4k次,点赞22次,收藏19次。安装npm相当于安装node.js,Node.js已自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西_npm安装配置

火车头采集器AI伪原创【php源码】-程序员宅基地

文章浏览阅读748次,点赞21次,收藏26次。大家好,小编来为大家解答以下问题,python基础训练100题,python入门100例题,现在让我们一起来看看吧!宝子们还在新手村练级的时候,不单要吸入基础知识,夯实自己的理论基础,还要去实际操作练练手啊!由于文章篇幅限制,不可能将100道题全部呈现在此除了这些,下面还有我整理好的基础入门学习资料,视频和讲解文案都很齐全,用来入门绝对靠谱,需要的自提。保证100%免费这不,贴心的我爆肝给大家整理了这份今天给大家分享100道Python练习题。大家一定要给我三连啊~

Linux Ubuntu 安装 Sublime Text (无法使用 wget 命令,使用安装包下载)_ubuntu 安装sumlime text打不开-程序员宅基地

文章浏览阅读1k次。 为了在 Linux ( Ubuntu) 上安装sublime,一般大家都会选择常见的教程或是 sublime 官网教程,然而在国内这种方法可能失效。为此,需要用安装包安装。以下就是使用官网安装包安装的教程。打开 sublime 官网后,点击右上角 download, 或是直接访问点击打开链接,即可看到各个平台上的安装包。选择 Linux 64 位版并下载。下载后,打开终端,进入安装..._ubuntu 安装sumlime text打不开

CrossOver for Mac 2024无需安装 Windows 即可以在 Mac 上运行游戏 Mac运行exe程序和游戏 CrossOver虚拟机 crossover运行免安装游戏包-程序员宅基地

文章浏览阅读563次,点赞13次,收藏6次。CrossOver24是一款类虚拟机软件,专为macOS和Linux用户设计。它的核心技术是Wine,这是一种在Linux和macOS等非Windows操作系统上运行Windows应用程序的开源软件。通过CrossOver24,用户可以在不购买Windows授权或使用传统虚拟机的情况下,直接在Mac或Linux系统上运行Windows软件和游戏。该软件还提供了丰富的功能,如自动配置、无缝集成和实时传输等,以实现高效的跨平台操作体验。

随便推点

一个用聊天的方式让ChatGPT写的线程安全的环形List_为什么gpt一写list就卡-程序员宅基地

文章浏览阅读1.7k次。一个用聊天的方式让ChatGPT帮我写的线程安全的环形List_为什么gpt一写list就卡

Tomcat自带的设置编码Filter-程序员宅基地

文章浏览阅读336次。我们在前面的文章里曾写过Web应用中乱码产生的原因和处理方式,旧文回顾:深度揭秘乱码问题背后的原因及解决方式其中我们提到可以通过Filter的方式来设置请求和响应的encoding,来解..._filterconfig selectencoding

javascript中encodeURI和decodeURI方法使用介绍_js encodeur decodeurl-程序员宅基地

文章浏览阅读651次。转自:http://www.jb51.net/article/36480.htmencodeURI和decodeURI是成对来使用的,因为浏览器的地址栏有中文字符的话,可以会出现不可预期的错误,所以可以encodeURI把非英文字符转化为英文编码,decodeURI可以用来把字符还原回来_js encodeur decodeurl

Android开发——打包apk遇到The destination folder does not exist or is not writeable-程序员宅基地

文章浏览阅读1.9w次,点赞6次,收藏3次。前言在日常的Android开发当中,我们肯定要打包apk。但是今天我打包的时候遇到一个很奇怪的问题Android The destination folder does not exist or is not writeable,大意是目标文件夹不存在或不可写。出现问题的原因以及解决办法上面有说报错的中文大意是:目标文件夹不存在或不可写。其实问题就在我们的打包界面当中图中标红的Desti..._the destination folder does not exist or is not writeable

Eclipse配置高大上环境-程序员宅基地

文章浏览阅读94次。一、配置代码编辑区的样式 <1>打开Eclipse,Help —> Install NewSoftware,界面如下: <2>点击add...,按下图所示操作: name:随意填写,Location:http://eclipse-color-th..._ecplise高大上设置

Linux安装MySQL-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle.tar_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_6-程序员宅基地

文章浏览阅读2.8k次。一,下载mysql:http://dev.mysql.com/downloads/mysql/; 打开页面之后,在Select Platform:下选择linux Generic,如果没有出现Linux的选项,请换一个浏览器试试。我用的谷歌版本不可以,换一个别的浏览器就行了,如果还是不行,需要换一个翻墙的浏览器。 二,下载完后解压缩并放到安装文件夹下: 1、MySQL-client-5.6.2_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle