中国DOS联盟论坛

中国DOS联盟

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

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

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS疑难解答 & 问题讨论 (解答室) » 【转载】别人写的新版MBR反汇编分析
作者:
标题: 【转载】别人写的新版MBR反汇编分析 上一主题 | 下一主题
starsky
初级用户




积分 191
发帖 22
注册 2004-7-30
状态 离线
『楼 主』:  【转载】别人写的新版MBR反汇编分析 使用 LLM 解释/回答一下


发信人: SeaPeak (登老和兮小浙大), 信区: AsmDos
标 题: mbr 反汇编分析
发信站: 飘渺水云间 (Sun Jul 4 15:55:51 2004), 转信

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 主引导记录(MBR)的反汇编分析
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MBR代码分析网上早就有了,但我找到的都是针对老版MBR的分析。这里所谓的
老版MBR,指的是早期的MBR,那时大容量硬盘还没有出现,MBR使用传统的
Int 13h接口访问硬盘。随着硬盘容量越来越大,传统的Int 13h已经无法完全
访问硬盘上所有扇区(Int 13h接口理论上可访问的最大硬盘容量约为8G)。因此,
扩展Int 13h规范出台以适应这种变化。MBR的代码也必须相应改动,必要时采
用扩展Int 13h来加载引导扇区。我称之为新版MBR。本篇分析的就是新版MBR。

MBR其实并不复杂,但要完全理解也需要一些底层的系统知识。code里的一些
技巧值得借鉴。

seapeak@88 转载时就保持完整
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;
; 设置栈SS:SP = 0:7C00
;
0000:7C00 xor ax, ax
0000:7C02 mov ss, ax
0000:7C04 mov sp, 7C00h
0000:7C07 sti
;
; DS = ES = 0
;
0000:7C08 push ax
0000:7C09 pop es
0000:7C0A push ax
0000:7C0B pop ds
;
; 将后面的代码复制到低端内存,为加载
; 活动分区的引导扇区腾出空间,因为引导
; 扇区也必须加载到0:7C00
;
0000:7C0C cld
0000:7C0D mov si, 7C1Bh
0000:7C10 mov di, 61Bh

0000:7C13 push ax
0000:7C14 push di
0000:7C15 mov cx, 1E5h
0000:7C18 repe movsb
;
; 跳到低端内存的代码继续执行
;
0000:7C1A retf

;
; 开始扫描分区表(Partition Table),寻找活动分区
;
0000:061B mov bp, 7BEh ; 600h+1BEh,分区表起始偏移为1BEh
0000:061E mov cl, 4 ; 分区表中有4个分区表项

loc_620:
0000:0620 cmp , ch ; 是活动分区吗?(此时ch中的值为0)
0000:0623 jl loc_62E ; 活动分区的标志是80h,如果解释成有符号
数,则小于0
0000:0625 jnz loc_63A ; 引导标志的合法值只能是0和80h,其它的值
则出错
0000:0627 add bp, 10h ; 指向下一个表项(每一个表项的长度为10h字

节)
0000:062A loop loc_620 ; 依次扫描所有分区表项
;
; 没有发现活动分区,无法启动OS,按照规范调用Int 18h
; 早期的BIOS的Int 18h中断服务程序就是启动ROM-Basic,
; 现在的BIOS一般是打印错误信息
;
0000:062C int 18h

;
; 找到活动分区后,还要检查剩余分区的启动标志是否为0
; 不允许存在多个活动分区
;
loc_62E:
0000:062E mov si, bp

loc_630:
0000:0630 add si, 10h ; 下一个分区表项
0000:0633 dec cx
0000:0634 jz loc_64F ; 所以剩余分区都扫描完
0000:0636 cmp , ch ; 启动标志是否为0?
0000:0638 jz loc_630 ; 是则合法,检查下一分区


;
; 分区启动标志不合法,打印错误信息
; "Invalid partition table"
;
loc_63A:
0000:063A mov al, byte_7B5

loc_63D:
0000:063D mov ah, 7
0000:063F mov si, ax

loc_641:
0000:0641 lodsb
0000:0642
0000:0642 loc_642:
0000:0642 cmp al, 0
0000:0644 jz loc_642 ; 打印完错误信息后,进入死循环
0000:0646 mov bx, 7
0000:0649 mov ah, 0Eh
0000:064B int 10h ; 调用Int10h显示一个字符
0000:064D jmp short loc_641


;
; 开始加载活动分区的引导扇区
;
loc_64F:
;
; 将一个标志的初始值清0。这个标志表示是否尝试过备份的引导扇区
; 的字节肯定是没用的空间
;
0000:064F mov , cl
0000:0652 call sub_69B
0000:0655 jnb loc_681

loc_657:
0000:0657 inc byte ptr ; 标志已经尝试过加载备份的引导扇

;
; 如果活动分区是FAT32分区,尝试加载备份的引导扇区
;
0000:065A cmp byte ptr , 0Bh ;FAT32
0000:065E jz loc_66B
0000:0660 cmp byte ptr , 0Ch ;FAT32(需用扩展Int 13h访问)

0000:0664 jz loc_66B
;
; 加载引导扇区失败,显示错误信息
; "Error loading operating system"
;
0000:0666 mov al, byte_7B6
0000:0669 jnz loc_63D

loc_66B:
;
; FAT32的备份引导扇区号=引导扇区号+6
;
0000:066B add byte ptr , 6
0000:066F add word ptr , 6
0000:0673 adc word ptr , 0
0000:0677 call sub_69B
0000:067A jnb loc_681
;
; 连备份的引导扇区也坏了,就没辙了!
;
0000:067C mov al, byte_7B6
0000:067F jmp short loc_63D


;
; 在把控制权交给引导扇区前,要先检查引导扇区的签名(signature)
; 防止把控制权交给已经损坏的引导扇区
;
0000:0681 loc_681:
0000:0681 cmp word ptr ds:, 0AA55h ;签名就是扇区最后的2个字节
0000:0687 jz loc_694
;
; 引导扇区损坏,则尝试用备份引导扇区
;
0000:0689 cmp byte ptr , 0 ;已经是备份的引导扇区?
0000:068D jz loc_657
;
; 备份引导扇区也坏了,死翘翘
;
0000:068F mov al, byte_7B7
0000:0692 jmp short loc_63D

;
; 交权给引导扇区,让它去完成OS的引导
;

0000:0694 loc_694:
0000:0694 mov di, sp ; di = sp = 7C00h
0000:0696 push ds
0000:0697 push di
0000:0698 mov si, bp ; 把活动分区表项指针传给引导扇区
0000:069A retf ; 跳到0:7C00

;
; 读取引导扇区的子过程
;
sub_69B proc near
0000:069B mov di, 5 ; 磁盘I/O错允许重试次数为5次
;
; 取硬盘的磁道参数
;
0000:069E mov dl, ; 分区的启动标志其实就是硬盘号
0000:06A1 mov ah, 8
0000:06A3 int 13h
0000:06A5 jb loc_6CA ; 如果取参数失败,认为BIOS肯定不支持扩展
Int 13h
; 只好用传统Int 13h
;

; 计算用传统Int 13h能访问的最大逻辑扇区号
; 计算公式为:(最大磁头号+1)*每道扇区数*(最大磁道号+1)
; 注意这个计算次序是有讲究的,因为(最大磁头号+1)*每道扇区数
; 的结果可以用16位寄存器就可以存放。如果先用磁道号来计算,
; 乘的结果就必须用两个寄存器来存放,导致第二步乘计算复杂化
;
0000:06A7 mov al, cl
0000:06A9 and al, 3Fh
0000:06AB cbw ; ax中为第道扇区数
0000:06AC mov bl, dh
0000:06AE mov bh, ah ; bh = 0,ah肯定为0
0000:06B0 inc bx
0000:06B1 mul bx ; (最大磁头号+1)*每道扇区数
0000:06B3 mov dx, cx
0000:06B5 xchg dl, dh
0000:06B7 mov cl, 6
0000:06B9 shr dh, cl ; dx中为(最大磁道号+1)
0000:06BB inc dx
0000:06BC mul dx ; (最大磁头号+1)*每道扇区数*(最大磁道号
+1)
;
; 判断引导扇区是否可以用传统Int 13h来访问

; 如果引导扇区的逻辑扇区号 >= 刚才算出的扇区号,必须用扩展Int
13h来读取
; 否则就用传统Int 13h来访问
;
; 注意一下双字数的比较方法!
;
0000:06BE cmp , dx
0000:06C1 ja loc_6E6
0000:06C3 jb loc_6CA
0000:06C5 cmp , ax
0000:06C8 jnb loc_6E6
0000:06CA ;
; 用传统Int 13h来读引导扇区
;
loc_6CA:
0000:06CA mov ax, 201h
0000:06CD mov bx, 7C00h
0000:06D0 mov cx,
0000:06D3 mov dx,
0000:06D6 int 13h
0000:06D8 jnb locret_72B
;

; 读取失败可以重试,试完规定的次数后还失败就没办法了
;
0000:06DA dec di
0000:06DB jz locret_72B
;
; 重试前重置一下磁盘系统
;
0000:06DD xor ah, ah
0000:06DF mov dl,
0000:06E2 int 13h
0000:06E4 jmp short loc_6CA

;
; 检查BIOS是否支持扩展Int 13h
;
0000:06E6 loc_6E6:
0000:06E6 mov dl,
0000:06E9 pusha
0000:06EA mov bx, 55AAh
0000:06ED mov ah, 41h
0000:06EF int 13h
0000:06F1 jb loc_729

0000:06F3 cmp bx, 0AA55h
0000:06F7 jnz loc_729
0000:06F9 test cl, 1 ;必须支持Fixed disk access这个功能子集
0000:06FC jz loc_729
0000:06FE popa
;
; 扩展Int 13h读扇区
;
0000:06FF loc_6FF:
0000:06FF pusha
;
; 在栈中构造磁盘地址包(Disk Address Packet)
;
0000:0700 push 0
0000:0702 push 0
0000:0704 push word ptr
0000:0707 push word ptr ; 要读扇区的LBA地址(4个word)
0000:070A push 0
0000:070C push 7C00h ; 引导扇区读到0:7C00h
0000:070F push 1 ; 读一个扇区
0000:0711 push 10h ; 包长度16个字节
0000:0713 mov ah, 42h

0000:0715 mov si, sp
0000:0717 int 13h
0000:0719 popa ; 这里用了一个小技巧,一下子从栈中弹出8
个word
; (地址包刚好是8个word)
0000:071A popa ; 这才是真正的恢复保存的通用寄存器的值
0000:071B jnb locret_72B
0000:071D dec di ; 不成功有重试的机会
; 注意这里也有个小技巧:dec指令不改变CF
的状态
0000:071E jz locret_72B ; 直到所有重试次数用完
;
; 重试前重置磁盘系统
;
0000:0720 xor ah, ah
0000:0722 mov dl,
0000:0725 int 13h
0000:0727 jmp short loc_6FF

loc_729:
0000:0729 popa
0000:072A stc


locret_72B:
0000:072B retn
sub_69B endp

0000:072C db 'Invalid partition table',0
0000:0744 db 'Error loading operating system',0
0000:0763 db 'Missing operating system',0

0000:07B5 byte_7B5 db 2Ch
0000:07B6 byte_7B6 db 44h
0000:07B7 byte_7B7 db 63h

0000:07FE dw 0AA55h ;MBR的signature

--------------------------------------------------------------------------------
---------
References:
* Enhanced Disk Drive Specification Ver 3.0,
http://www.phoenix.com/resources/specs-edd30.pdf.
* BIOS Boot Specification Version 1.01,
http://www.phoenix.com/resources/specs-bbs101.pdf.

------------------------------End of
file------------------------------------------------
--

实迷途其未远,觉今是而昨非




2004-8-7 00:00
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
starsky
初级用户




积分 191
发帖 22
注册 2004-7-30
状态 离线
『第 2 楼』:   使用 LLM 解释/回答一下

文章最后引用的两篇文章挺好的 感觉 ^_^


2004-8-7 00:00
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
nre
银牌会员

nre


积分 1210
发帖 361
注册 2002-12-28
状态 离线
『第 3 楼』:   使用 LLM 解释/回答一下

支持!!





Teamwork !
2004-8-8 00:00
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复

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


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



论坛跳转: