![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-16 23:07 |
共 47,813 主题排行 / 349,903 发帖 / 今日 0 篇 / 48,259 会员排行 |
| DOS疑难解答 & 问题讨论 (解答室) » 【转载】别人写的新版MBR反汇编分析 |
| 可打印版本 1,720 / 2 |
| 第1楼 starsky | 发表于 2004-08-07 00:00 |
| 初级用户 发帖 22 积分 191 | |
|
【转载】别人写的新版MBR反汇编分析 发信人: 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------------------------------------------------ -- 实迷途其未远,觉今是而昨非 |
|
| 第2楼 starsky | 发表于 2004-08-07 00:00 |
| 初级用户 发帖 22 积分 191 | |
|
文章最后引用的两篇文章挺好的 感觉 ^_^
|
|
| 第3楼 nre | 发表于 2004-08-08 00:00 |
| 银牌会员 发帖 361 积分 1,210 | |
|
支持!!
|
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |