中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) »  How It Works --- Master Boot Record (主启动记录)
作者:
标题:  How It Works --- Master Boot Record (主启动记录) 上一主题 | 下一主题
ko20010214
版主




积分 7294
发帖 1628
注册 2002-10-16
状态 离线
『楼 主』:   How It Works --- Master Boot Record (主启动记录)


          How It Works  --- Master Boot Record (主启动记录)
                           1a版
          作者:Hale Landis (landis@sugs.tware.com)
          译者:qnp(华南木棉)
"How It Works"系列
这是"How It Works"系列中的一篇文档。目前这个系列包括了以下文档:
* How It Works -- CHS Translation
* How It Works -- Master Boot Record
* How It Works -- DOS Floppy Boot Sector
* How It Works -- OS2 Boot Sector
* How It Works -- Partition Tables
  本文是介绍MBR的反编译程序的。MBR是放在硬盘的0柱面,0磁头(head),1扇区的
那一段区。MBR是由FDISK程序创建的。所有操作系统的FDISK程序都会创建类似的MBR
记录。MBR是多个分区的前提,每个MBR中包括了四个分区表记录。在您的计算机加电
之后,INT19被调用了。一般来说,INT19先从第一个软盘驱动器中读启动扇区记录。
如果在软盘中找到了启动的扇区,那么这个扇区的数据就被读入到内存的0000:7c00
地址上,INT19也跳到了这个地址上。但是,如果没有在软盘中找到这个扇区的话,INT
19就从第一个硬盘中去读。同样,如果成功的话,也会把MBR导入到相同的内存地址
0000:7c00,INT19也会跳这个地址。MBR中包括的一段小程序是定出在分区表中的活动分
区。这样的活动分区找到之,那个分区的启动扇区也被读入到0000:7c00地址,MBR程序
也转移到了这个地址。每一个操作系统都有固定的启动扇区的格式。在启动扇区里的程
序要能定出操作系统启动程序的位置(或是核心本身,或者是一个启动管理器),然后
将它读入内存。
另:在Ctrl-Alt-Del键被按下时,INT19也会被调用。在大多数系统中,Ctrl-Alt-Del三?
键同时按下表示热启动您的计算机,回到INT19调用前的状态。
=====
数据存放的位置:
   MBR程序放在偏移为0000的位置。
   MBR消息放在偏移为008b的位置。
   分区表放在偏移为00be的位置。
   签名放在偏移为00fe的位置。
关于谁干什么事的总结:
    如果一个活动分区找到了,这个分区的启动数据被读入到0000:7c00的位置,MBR程
序也跳到0000:7c00的位置。这段程序找到指向分区表的入口,入口描述的是这段分区是
怎样被启动的。启动程序用这些数据来决定用来启动的驱动器和这个驱动器分区在硬盘上
的位置。
    如果没有找到这样的活动分区入口,ROM BASIC会转入INT 18的调用。所有其他的错
误导致系统的挂起,可以看HANG的标记。

注意(非常之重要):
  1)活动分区入口的第一个字节的内容是80h。在INT13被调用之前,这个字节被导
入到DL寄存器中。当INT13被调用时,DL表示的是BIOS的设备号码。因为这个原因,由MBR
程序读的启动扇区只能从BIOS设备号码为80的硬盘中读入。这便是为什么不能从任何硬盘
启动的原因。?

  2)MBR程序是用基于INT 13h (ah=02h)的中断的CHS来读取活动分区的启动扇区位置
的。活动分区的启动扇区内的位置是在分区表内用CHS格式表明的。如果这个驱动器小于
528M,这个CHS一定要是(L-CHS,见BIOS TYPES文档)。在LBA中没有任何地址是有用的。
(另一个LBA不能解决>528M问题的原因)   这点大家别信,西西。


====
    这是一张整个MBR记录的表(hex 和ascii格式)
OFFSET 0 1 2 3  4 5 6 7  8 9 A B  C D E F  *0123456789ABCDEF*
000000 fa33c08e d0bc007c 8bf45007 501ffbfc *.3.....|..P.P...*
000010 bf0006b9 0001f2a5 ea1d0600 00bebe07 *................*
000020 b304803c 80740e80 3c00751c 83c610fe *...<.t..<.u.....*
000030 cb75efcd 188b148b 4c028bee 83c610fe *.u......L.......*
000040 cb741a80 3c0074f4 be8b06ac 3c00740b *.t..<.t.........x....*
0001d0 00000000 00000000 00000000 00000000 *................*
0001e0 00000000 00000000 00000000 00000000 *................*
0001f0 00000000 00000000 00000000 000055aa *..............U.*
====
   这是MBR的反编译程序:
   这个扇区被导入到内存的0000:7c00位置,但是它又马上将自己重定位到0000:0060的
位?

BEGIN:   #    NOW AT 0000:7C00, RELOCATE
0000:7C00 FA            CLI                     #禁止中断
0000:7C01 33C0          XOR     AX,AX           #设置堆栈段地址为0000
0000:7C03 8ED0          MOV     SS,AX
0000:7C05 BC007C        MOV     SP,7C00         #设置堆栈指针为7c00
0000:7C08 8BF4          MOV     SI,SP           #SI = 7c00
0000:7C0A 50            PUSH    AX
0000:7C0B 07            POP     ES              #ES = 0000:7c00
0000:7C0C 50            PUSH    AX
0000:7C0D 1F            POP     DS              #DS = 0000:7c00
0000:7C0E FB            STI                     #开中断
0000:7C0F FC            CLD                     #清除方向
0000:7C10 BF0006        MOV     DI,0600         #DI = 0600
0000:7C13 B90001        MOV     CX,0100         #移动 256 个word (512 bytes)

0000:7C16 F2            REPNZ                   #把 MBR 从 0000:7c00
0000:7C17 A5            MOVSW                   #移动到 0000:0600
0000:7C18 EA1D060000    JMP     0000:061D       #跳至NEW_LOCATION
NEW_LOCATION:# NOW AT 0000:0600
0000:061D BEBE07      MOV     SI,07BE           #指向入口的第一个字节
0000:0620 B304        MOV     BL,04             #有4个入口
SEARCH_LOOP1: # 查找活动分区
0000:0622 803C80      CMP     BYTE PTR [SI],80  #是不是活动分区?
0000:0625 740E        JZ      FOUND_ACTIVE      #是,栈指针指向7c00
0000:0627 803C00      CMP     BYTE PTR [SI],00  #是不是不活动分区?
0000:062A 751C        JNZ     NOT_ACTIVE        #跳转至NOT_ACTIVE
0000:062C 83C610      ADD     SI,+10            #增量表指针加16
0000:062F FECB        DEC     BL                #减少计数
0000:0631 75EF        JNZ     SEARCH_LOOP1      #循环
0000:0633 CD18        INT     18                #跳至 ROM BASIC
FOUND_ACTIVE: # 找到了活动分区
0000:0635 8B14        MOV     DX,[SI]           #设置DH/DL为INT 13
0000:0637 8B4C02      MOV     CX,[SI+02]        #设置CH/CL为INT 13
0000:063A 8BEE        MOV     BP,SI             #保存表指针
SEARCH_LOOP2: # 确定是一个活动分区
0000:063C 83C610      ADD     SI,+10            #增量表指针加16
0000:063F FECB        DEC     BL                #减少计数
0000:0641 741A        JZ      READ_BOOT         #如果表结束,跳转
0000:0643 803C00      CMP     BYTE PTR [SI],00  #是不是非活动分区
0000:0646 74F4        JZ      SEARCH_LOOP2      #是,循环
NOT_ACTIVE:   #  多于一个活动分区
0000:0648 BE8B06      MOV     SI,068B           #显示 "Invld prttn tbl"
DISPLAY_MSG:  #  显示消息循环
0000:064B AC          LODSB                     #取得消息的字符
0000:064C 3C00        CMP     AL,00             #判断消息的结尾
0000:064E 740B        JZ      HANG              #是
0000:0650 56          PUSH    SI                #保存SI
0000:0651 BB0700      MOV     BX,0007           #屏幕属性
0000:0654 B40E        MOV     AH,0E             #显示一个字符
0000:0656 CD10        INT     10
0000:0658 5E          POP     SI                #恢复SI
0000:0659 EBF0        JMP     DISPLAY_MSG       #循环
HANG:         #挂起系统
0000:065B EBFE        JMP     HANG              #停在这儿
READ_BOOT:   #读活动分区的数据
0000:065D BF0500      MOV     DI,0005        #INT 13 的尝试次数
INT13RTRY:   #INT 13的重试循环
0000:0660 BB007C      MOV     BX,7C00
0000:0663 B80102      MOV     AX,0201           #读入一个扇区
0000:0666 57          PUSH    DI                #保存DI
0000:0667 CD13        INT     13                #把扇区读入0000:7c00
0000:0669 5F          POP     DI                #重存DI
0000:066A 730C        JNB     INT13OK           #没有INT 13,跳转
0000:066C 33C0        XOR     AX,AX             #调用INT 13 ,硬盘重置
0000:066E CD13        INT     13
0000:0670 4F          DEC     DI                #DI--
0000:0671 75ED        JNZ     INT13RTRY         #如果非零,重试
0000:0673 BEA306      MOV     SI,06A3           #显示"Errr ldng systm"
0000:0676 EBD3        JMP     DISPLAY_MSG       #跳转至显示循环
INT13OK: #INT 13 出错
0000:0678 BEC206      MOV     SI,06C2            #"missing op sys"
0000:067B BFFE7D      MOV     DI,7DFE            #指向签名
0000:067E 813D55AA    CMP     WORD PTR [DI],AA55 #签名是否正确?
0000:0682 75C7        JNZ     DISPLAY_MSG        #不正确,跳至显示消息循环
0000:0684 8BF5        MOV     SI,BP              #设置SI
0000:0686 EA007C0000  JMP     0000:7C00          #跳转至启动扇区,SI指向分区
表入
?

#这儿是消息
0000:0680 ........ ........ ......49 6e76616c *           Inval*
0000:0690 69642070 61727469 74696f6e 20746162 *id partition tab*
0000:06a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading*
0000:06b0 206f7065 72617469 6e672073 79737465 * operating syste*
0000:06c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat*
0000:06d0 696e6720 73797374 656d00.. ........ *ing system.     *
#无用的数据
0000:06d0 ........ ........ ......00 00000000 *           .....*
0000:06e0 00000000 00000000 00000000 00000000 *................*
0000:06f0 00000000 00000000 00000000 00000000 *................*
0000:0700 00000000 00000000 00000000 00000000 *................*
0000:0710 00000000 00000000 00000000 00000000 *................*
0000:0720 00000000 00000000 00000000 00000000 *................*
0000:0730 00000000 00000000 00000000 00000000 *................*
0000:0740 00000000 00000000 00000000 00000000 *................*
0000:0750 00000000 00000000 00000000 00000000 *................*
0000:0760 00000000 00000000 00000000 00000000 *................*
0000:0770 00000000 00000000 00000000 00000000 *................*
0000:0780 00000000 00000000 00000000 00000000 *................*
0000:0790 00000000 00000000 00000000 00000000 *................*
0000:07a0 00000000 00000000 00000000 00000000 *................*
0000:07b0 00000000 00000000 00000000 0000.... *............    *
#分区表从0000:07be开始。每一个分区表入口是16个字节这个表定义了一个单个的主分
区并
是活动分区。
0000:07b0 ........ ........ ........ ....8001 *            ....*
0000:07c0 0100060d fef83e00 00000678 0d000000 *......>....x....*
0000:07d0 00000000 00000000 00000000 00000000 *................*
0000:07e0 00000000 00000000 00000000 00000000 *................*
0000:07f0 00000000 00000000 00000000 0000.... *............    *
#最后两个字节一定包括了55aah的数据。
0000:07f0 ........ ........ ........ ....55aa *..............U.*

(本文采用S-Term文章拷贝脚本拷贝)
==================================================
KO的话:
以前我找到过这个的英文版,本来想翻译它的,无奈太长了。。。想用编程的方法去翻译嘛,又不会编程,:-(  ,用软件智能翻译吧,软件却都不怎么智能,校对工作几乎和翻译工作的时间一样长,可能还要更长。。。
现在找到一篇现成的,呵呵。。。



[此贴子已经被作者于2003-6-1 14:35:20编辑过]






ko20010214
=================================
大功告成,打个Kiss!
ko20010214@MSN.com
神州优雅Q300C
Intel CeleronM 370处理器 | 256MbDDR内存
40G硬盘 | USB2.0 | IEEE 1394
13.3 ' WXGA 宽屏(16:10) | COMBO光驱
10/100M网卡 | 四合一读卡器
2003-6-1 00:00
查看资料  发送邮件  发短消息 网志  OICQ (16959102)  编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: