无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
查看: 3120|回复: 5
打印 上一主题 下一主题

[发布] NT52 MBR 反汇编注释与程序流程图

[复制链接]
跳转到指定楼层
1#
发表于 2012-6-13 17:23:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原创作品,全部是自己分析,绝非网上抄袭.

NT52 MBR 的反汇编代码与注释:
反汇编的注释特别多,看别人的程序不是一件容易的事,有许多没有用过的指令,会更加糊涂,注释多了点,但讲解的足够详细.
以下是源代码与注释:


:0001.0000 33C0                   xor ax, ax      ;ax置0,重置标志寄存器
:0001.0002 8ED0                   mov ss, ax      ;SS=0
:0001.0004 BC007C                 mov sp, 7C00    ;设置堆栈 0:7c00
:0001.0007 FB                     sti             ;开中断,允许响应外部可屏蔽中断
:0001.0008 50                     push ax         ;入栈AX的值
:0001.0009 07                     pop es          ;出栈栈中数据赋值给ES,使ES=0
:0001.000A 50                     push ax         ;入栈AX
:0001.000B 1F                     pop ds          ;出栈栈中数据赋值给DS,使DS=0
:0001.000C FC                     cld             ;设置数据串操作方向为正方向,使SI DI的值递增
:0001.000D BE1B7C                 mov si, 7C1B    ;SI=7c1b
:0001.0010 BF1B06                 mov di, 061B    ;DI=061B
:0001.0013 50                     push ax         ;入栈AX
:0001.0014 57                     push di         ;入栈DI
:0001.0015 B9E501                 mov cx, 01E5    ;CX=01E5    十进制 485
:0001.0018 F3                     repz           
:0001.0019 A4                     movsb           ;进行内存复制操作把DS:SI 指向的内容复制到ES:DI指向的位置
                                                  ;根据CX的值进行按字节循环复制,一共复制485个字节
                                                  ;7C1B正好是 RETF指令后面的语句,也就是 mov bp,07be 这条语句
                                                  ;此处进行的操作是 把程序代码移动位置,然后从新的位置继续执行指令
                                                  ;硬盘的MBR被BIOS载入到内存0:7C00的位置,并从此处执行指令
:0001.001A CB                     retf            ;出栈栈中的数据设置CS:IP,使CPU从0:061B执行指令

:0001.001B BDBE07                 mov bp, 07BE    ;移动位置后的程序,此处是061B 该语句使BP=07BE
                                                  ;07BE指向的正好是分区表的开始
                                                  ;07BE-0600=1BE  1BE正好是分区表的开始
:0001.001E B104                   mov cl, 04      ;CL=4
:0001.0020 386E00                 cmp [bp+00], ch ;SS:[BP+00]的值与CH的值进行比较
                                                  ;注意CH的值为0 上面根据CX的值进行内存复制操作,执行完以后CX=0
:0001.0023 7C09                   jl 002E         ;如果ss:[bp+00]的值小于0跳转到002E 执行
                                                  ;JL是针对有符号数的判断,分区激活标志为80H,二进制数为10000000B
                                                  ;二进制数10000000当作有符号数是 -128(十进制)

:0001.0025 7513                   jne 003A        ;不为0跳到003A执行
                                                  ;分区激活标志既不是80H,也不是0,则跳转到3A执行

:0001.0027 83C510                 add bp, 0010   ;BP的值加10H,也就是加16指向下一分区表的开始
:0001.002A E2F4                   loop 0020      ;根据CX的值进行循环,也就是遍历分区表,查找活动分区
:0001.002C CD18                   int 18         ;调用INT18 从下一启动设备启动
                                                 ;如果一直没有找到活动分区,调用INT18H
*******************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0023(C)
|                                                反汇编工具的提示: 从0023有一条跳转到此处的条件转移指令
*******************************************************************************************************************
:0001.002E 8BF5                   mov si, bp     ;SI=BP  假设BP=7BEH,所以SI=7BEH 假设第一分区表项是激活状态

*******************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0038(C)
|                                  反汇编工具的提示: 0038有一条条件转移指令跳转到0030
*******************************************************************************************************************
:0001.0030 83C610                 add si, 0010   ;si+10H   SI=下一分区表开始
:0001.0033 49                     dec cx         ;CX的值减1
:0001.0034 7419                   je 004F        ;如果CX=0,跳转到4F执行
                                                 ;假设该语句在第一次执行时,条件即被满足,那么CX在DEC CX语句之前=1
                                                 ;也就是最后一个分区表是激活状态时,跳转到4F执行
                                                 ;假设该语句不是第一次执行时条件得到满足,但只要是能够满足条件
                                                 ;分区表必定是有一个是激活状态,其余全部为0,此时跳转到4F执行
                                                 ;总结来说,跳转到4F执行的条件是:
                                                 ;分区表有一个表项是激活状态(至少小于0,为负),其余分区表项都为0
                                                
:0001.0036 382C                   cmp [si], ch   ;判断DS:[SI]的值是不是0
:0001.0038 74F6                   je 0030        ;如果是0跳转到0030 进行循环
                                                 ;正常情形下,假设第一分区表是激活状态,那么后面的分区表项应该是0(非激活)
                                                 ;假设第一分区是激活状态,后面的都是0,那么此处会进行3次循环
                                                 ;最后一次会跳转到4F去执行

**************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0025(C)
|                                  反汇编工具的提示: 0025有一条条件转移指令跳转到003A
**************************************************************************************************************************
:0001.003A A0B507                 mov al, [07B5] ; 把DS:[07B5]的值赋给al
                                                 ; 07b5-600=1b5 实机值是2C
                                                 ; 01b5的值实机是 2c 44 63
                                                 ; 跳转到此处或者执行到此处的条件是: 分区表激活标志不规范
                                                 ; 0025处有一个判断,如果分区表激活标志不小于0,又不等于0会跳转到此处
                                                 ; 0038处的判断,如果找到一个分区表项的激活标志小于0,但是下一表项的激活标志
                                                 ;不为0,也就是说存在多个激活标志或者不规范的取值,都会跳转到此处执行
                                                 ; 总结,跳转到003A的条件是:
                                                 ; A 激活标志不小于0 (取值范围不在80H~FFH) 又不等于0
                                                 ; B 找到一个小于0的激活标志,但下一分区激活标志不等于0
                                                 ; A与B 只要有一条符合都会跳到此处执行


**************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0069(C), :0001.007F(U), :0001.0092(U)
|                                 反汇编工具的提示
**************************************************************************************************************************
:0001.003D B407                   mov ah, 07     ;ah=7
:0001.003F 8BF0                   mov si, ax     ;si=ax 假设si=072c
                                                 ;此处的目的是把SI指向一个字符串的开始

**************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.004D(U)
|                                 反汇编工具的提示: : 004D有一条条件转移指令跳转到此处: 0041
**************************************************************************************************************************
:0001.0041 AC                     lodsb         ;把si指向的存储单元读入累计器al 此时串操作方向是正方向DF=0
                                                ;072c-0600=12c 指向的正好是一个字符串的开始
                                                ; Invalid partition table

**************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0044(C)
|                                反汇编工具的提示: 0044有一条条件转移指令跳转到此处: 0042
**************************************************************************************************************************
:0001.0042 3C00                   cmp al, 00    ;判断al的值是不是0,实际是判断字符串是否结束
:0001.0044 74FC                   je 0042       ;如果结束跳转到42执行
:0001.0046 BB0700                 mov bx, 0007  ;bx=7
:0001.0049 B40E                   mov ah, 0E    ;ah=0e
:0001.004B CD10                   int 10        ;调用INT10H 在屏幕上显示字符
:0001.004D EBF2                   jmp 0041      ;跳转到0041 执行,此处是一个小循环,用于显示字符串
                                                ;INT 10H调用说明: ah=0e 功能选择 al=要显示的字符 bh=页符 bl=前景色
                                                ;程序执行到003A以后,此处程序即会在屏幕上显示 Invalid partition table
                                                ;显示完提示信息以后,会进入一个人为制造的死循环 0042 0044构造了一个循环



************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0034(C)
|                                 反汇编工具的提示: 0034有一条条件转移指令跳转到此处:004F  
|                                 跳转到此处的条件是: 分区表四个表项有一个表项的激活标志取值小于0,其他全为0
************************************************************************************************************************
:0001.004F 884E10                 mov [bp+10], cl ;把CL的值写到ss:[bp+10]  bp的值是激活分区的开始地址               
                                                  ;BP+10的值是激活分区后面下一个分区的开始
                                                  ;cl的值是0

   
:0001.0052 E84600                 call 009B       ;调用009B
:0001.0055 732A                   jnb 0081        ;CF不等于1跳转到0081执行
                                                  ;判断调用是否成功,成功跳转到0081执行
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.008D(C)
|
:0001.0057 FE4610                 inc byte ptr [bp+10]  ;ss:[bp+10]的值加1
:0001.005A 807E040B               cmp byte ptr [bp+04], 0B ;比较[bp+04],也就是分区属性值是否是0B
:0001.005E 740B                   je 006B                  ;分区属性是0B跳转到6B执行
:0001.0060 807E040C               cmp byte ptr [bp+04], 0C ;检查分区属性是否是0C
:0001.0064 7405                   je 006B                  ;是0C跳转到6B执行
:0001.0066 A0B607                 mov al, [07B6]           ;al=[07b6]=44h
:0001.0069 75D2                   jne 003D                 ;如果分区属性不为0C跳转到003D
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.005E(C), :0001.0064(C)
|
:0001.006B 80460206               add byte ptr [bp+02], 06   ;[bp+02]的值加6
                                                             ;[bp+02]对应分区表项扇区项S  扇区加6
:0001.006F 83460806               add word ptr [bp+08], 0006 ;[bp+08]的值加6
                                                             ;[bp+08]对应分区表项起始LBA的低16位
:0001.0073 83560A00               adc word ptr [bp+0A], 0000 ;分区起始LBA的高16位加上来自前面运算的进位
:0001.0077 E82100                 call 009B                  ;调用009B
:0001.007A 7305                   jnb 0081                   ;执行成功,跳转到0081
:0001.007C A0B607                 mov al, [07B6]             ;AL=44H
:0001.007F EBBC                   jmp 003D                   ;跳转到003D

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0055(C), :0001.007A(C)
|
:0001.0081 813EFE7D55AA           cmp word ptr [7DFE], AA55   ;比较 ds:[7DFE]的值是不是AA55
:0001.0087 740B                   je 0094                     ;是AA55跳转到0094执行
:0001.0089 807E1000               cmp byte ptr [bp+10], 00    ;检查 ss:[bp+10]的值是否是0
:0001.008D 74C8                   je 0057                     ;结果为0 跳转到0057执行
:0001.008F A0B707                 mov al, [07B7]              ;al=63H
:0001.0092 EBA9                   jmp 003D                    ;跳转到003D执行

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0087(C)
|
:0001.0094 8BFC                   mov di, sp   ;DI=SP            
:0001.0096 1E                     push ds      ;入栈DS的值
:0001.0097 57                     push di      ;入栈DI的值
:0001.0098 8BF5                   mov si, bp   ;SI=BP
:0001.009A CB                     retf         ;执行RETF指令,移交控制权

* Referenced by a CALL at Addresses:
|:0001.0052, :0001.0077
|
:0001.009B BF0500                 mov di, 0005     ;di=5
:0001.009E 8A5600                 mov dl, [bp+00]  ;dl=ss:[bp]  假设第一分区激活,BP=7BE dl=80
:0001.00A1 B408                   mov ah, 08       ;ah=8
:0001.00A3 CD13                   int 13           ;调用INT 13H
                                                   ;int13h ah=8 用于读取驱动器参数
:0001.00A5 7223                   jb 00CA          ;检查返回值,失败跳转到00CA执行
                                                   ; AH=8 功能调用 成功返回值: DH=磁头 DL=驱动器数 CL低6位=扇区
:0001.00A7 8AC1                   mov al , cl      ;al=cl  
:0001.00A9 243F                   and al, 3F       ; "与运算" 取AL的低6位也就是扇区数
:0001.00AB 98                     cbw              ;符号扩展指令,把AL的符号扩展到AH
:0001.00AC 8ADE                   mov bl , dh      ;bl=dh=磁头数
:0001.00AE 8AFC                   mov bh, ah       ;bh=ah=0 AL进行"与运算"之后,符号位肯定是0 AH=0
:0001.00B0 43                     inc bx           ;BX加1 BX=磁盘总的磁头数
:0001.00B1 F7E3                   mul bx           ;乘法运算 ax*bx=dx:ax  DX是乘法的高16位 AX是乘法的低16位
                                                   ;实际是进行扇区*磁头的运算
                                                   ;bx最大值为255 AX值最大为63 结果最大为3EC1H,所以DX的值为0
:0001.00B3 8BD1                   mov dx, cx       ;dx=cx
:0001.00B5 86D6                   xchg dh, dl      ;交换DH DL的值
:0001.00B7 B106                   mov cl, 06       ;cl=6
:0001.00B9 D2EE                   shr dh, cl       ;移位运算dh向右移6位
:0001.00BB 42                     inc dx           ;DX加1
                                                   ;DX的值为总的柱面数
:0001.00BC F7E2                   mul dx           ;乘法运算 dx*ax=总的扇区数*总的磁头数*总的柱面数,得到磁盘的最大容量
                                                   ;DX:AX的值为磁盘的总扇区数
                                                   ;分析: 因为INT 13H/AH=8的返回值得到的最大CHS值为1024/255/63
                                                   ;1024*255*63=16450560=FB0400H DX的最大值为FB
:0001.00BE 39560A                 cmp [bp+0A], dx  ;比较SS:[BP+0A] 与DX的值
                                                   ;DX的值为总扇区数的高16位
                                                   ;BP+0A 的偏移是分区表起始LBA的高16位
:0001.00C1 7723                   ja 00E6          ;ja进行无符号数比较 如果分区表起始LBA高16位的值大于DX的值跳转到00E6
                                                   ;也就是分区的起始LBA大于8G
:0001.00C3 7205                   jb 00CA          ;分区起始LBA地址的高16位小于DX的值跳转到00CA执行
:0001.00C5 394608                 cmp [bp+08], ax  ;比较 SS:[BP+08] 与AX的值 AX的值为总扇区数的低16位
                                                   ;BP+08 的偏移是分区起始LBA的低16位
:0001.00C8 731C                   jnb 00E6         ;不低于AX的值跳转到00E6 执行
                                                   ;也就是说分区的起始LBA小于8G跳转到00CA执行
                                                   ;分区起始LBA高16位等于DX的值,低16位不小于AX的值,也就是大于等于8G跳转到E6

************************************************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00A5(C), :0001.00C3(C), :0001.00E4(U)
|                                 反汇编工具提示: 00A5处有一条条件转移指令跳转到此处00CA
************************************************************************************************************************
:0001.00CA B80102                 mov ax, 0201      ;AH=02 读功能 AL=01一个扇区
:0001.00CD BB007C                 mov bx, 7C00      ;BX=7C00 数据缓冲区
:0001.00D0 8B4E02                 mov cx, [bp+02]   ;CX=SS:[BP+02] 假设BP=7BE SS:[07D0]指向分区表项的第二个字节
                                                 ;柱面加扇区 CH=柱面数 CL=扇区数  CL的高2位+CH的8位=柱面数 CL的低6位=扇区数
                                                 ;CX的值正好对应分区表部分的取值
:0001.00D3 8B5600                 mov dx, [bp]   ;SS:[BP]是分区表的开始,DL是驱动器号,DH对应磁头数
:0001.00D6 CD13                   int 13         ;调用INT13H读扇区功能
:0001.00D8 7351                   jnb 012B       ;如果INT13H读扇区成功,跳转到12B执行.
:0001.00DA 4F                     dec di         ;di的值减1 初始值为5
:0001.00DB 744E                   je 012B        ;检查结果是否为0,等于0 跳转到12B 执行  12B是一条返回指令
:0001.00DD 32E4                   xor ah, ah     ;ah清0
:0001.00DF 8A5600                 mov dl, [bp+00];dl=SS:[BP],假设等于80H
:0001.00E2 CD13                   int 13         ;再次调用INT13H  
                                                 ;INT 13H /ah=00h 磁盘系统复位 DL=驱动器号
:0001.00E4 EBE4                   jmp 00CA       ;跳转到00CA执行 此处是一个小循环,重复4次调用INT13读扇区功能



* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00C1(C), :0001.00C8(C)
|
:0001.00E6 8A5600                 mov dl, [bp+00] ;dl=80H 假设
:0001.00E9 60                     pusha           ;通用寄存器全部入栈      
:0001.00EA BBAA55                 mov bx, 55AA    ;bx=55aa
:0001.00ED B441                   mov ah, 41      ;ah=41h 扩展INT13H调用
:0001.00EF CD13                   int 13          ;检查驱动器是否支持扩展INT 13H
:0001.00F1 7236                   jb 0129         ;检测CF是否为1 为1则不支持扩展INT13H,跳转到0129执行
:0001.00F3 81FB55AA               cmp bx, AA55    ;比较BX的值,同样是检查扩展INT13H
:0001.00F7 7530                   jne 0129        ;失败跳转到129执行
:0001.00F9 F6C101                 test cl, 01     ;检查CL的最低位是否为1
:0001.00FC 742B                   je 0129         ;仍旧检查扩展INT13H的调用是否成功,不成功跳转到0129执行
:0001.00FE 61                     popa            ;恢复寄存器的值
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0127(U)
|
:0001.00FF 60                     pusha           ;通用寄存器全部入栈
:0001.0100 6A00                   push 0000
:0001.0102 6A00                   push 0000       ;入栈立即数
:0001.0104 FF760A                 push word ptr [bp+0A] ;入栈分区起始地址的高16位
:0001.0107 FF7608                 push word ptr [bp+08] ;入栈分区起始地址的低16位
:0001.010A 6A00                   push 0000
:0001.010C 68007C                 push 7C00
:0001.010F 6A01                   push 0001
:0001.0111 6A10                   push 0010        ;入栈立即数
                                                   ;以上构造 "磁盘地址数据包"
                                         ;内存中的数据为  10 00 01 00 00 7c 00 00 xx xx xx xx 00 00 00 00
:0001.0113 B442                   mov ah, 42       ;AH=42H 扩展INT13H 读扇区功能调用
:0001.0115 8BF4                   mov si, sp       ;SI=SP指向磁盘地址包的开始
:0001.0117 CD13                   int 13           ;调用扩展INT13H 读扇区功能
:0001.0119 61                     popa             ;用栈中的数据设置通用寄存器的值 此处是把构造的磁盘地址数据包出栈
:0001.011A 61                     popa             ;恢复通用寄存器的值
:0001.011B 730E                   jnb 012B         ;调用成功,跳转到12B执行
:0001.011D 4F                     dec di           ;di减1
:0001.011E 740B                   je 012B          ;DI值为0跳转到12B执行
:0001.0120 32E4                   xor ah, ah       ;清零AH的值
:0001.0122 8A5600                 mov dl, [bp+00]  ;DL=80H 假设激活标志为80
:0001.0125 CD13                   int 13           ;调用INT 13H 磁盘复位
:0001.0127 EBD6                   jmp 00FF         ;再次跳转到00FF循环

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00F1(C), :0001.00F7(C), :0001.00FC(C)
|
:0001.0129 61                     popa           ;恢复寄存器的值
:0001.012A F9                     stc            ;使CF=1
*******************************************************************************************
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00D8(C), :0001.00DB(C), :0001.011B(C), :0001.011E(C)
|                     反汇编工具提示: 00D8处有一条条件转移指令跳转到此处12B   
*******************************************************************************************
:0001.012B C3                     ret            ;返回指令


:0001.012C --> :0001.017B   ASCII码表示的字符串
*************************************************************************************
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
00000120                                        49 6E 76 61               Inva
00000130   6C 69 64 20 70 61 72 74  69 74 69 6F 6E 20 74 61   lid partition ta
00000140   62 6C 65 00 45 72 72 6F  72 20 6C 6F 61 64 69 6E   ble Error loadin
00000150   67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74   g operating syst
00000160   65 6D 00 4D 69 73 73 69  6E 67 20 6F 70 65 72 61   em Missing opera
00000170   74 69 6E 67 20 73 79 73  74 65 6D                  ting system
*************************************************************************************

:0001.017B -0001.01b4 全为 00   
:0001.01B5 2C 44 63
2#
 楼主| 发表于 2012-6-13 17:25:32 | 只看该作者
二楼,上传程序流程图.
没有专门的学过怎么画 专业的流程图.
自己画的,能看明白怎么回事就行.

nt52.jpg (141.78 KB, 下载次数: 48)

nt52.jpg
回复

使用道具 举报

3#
 楼主| 发表于 2012-6-13 17:31:00 | 只看该作者
NT52 会判断分区的起始位置,如果起始位置大于等于8G,调用扩展INT 13H读扇区,如果小于8G,会调用基本INT 13H读扇区,基本INT 13H入口参数中用到的CHS参数,全部来自分区表的CHS取值,所以,如果分区表的CHS取值不正确,活动分区小于8G的情形下,NT52 肯定要引导失败.

另外,发现,如果FAT32分区的DBR被装载到7C00以后,如果没有55 AA 标志,NT52 会尝试把DBR+6 扇区,也就是备份DBR扇区载入到7C00,备份DBR,如果有55 AA 标志,则会从备份DBR进行引导.
这只是一种防出错的手段,但真实情况,可能未必会起到作用.
回复

使用道具 举报

4#
发表于 2012-6-13 22:03:34 | 只看该作者

回复 #3 sgw888 的帖子

楼主好人。
学汇编的朋友可以立马上手的好教材。
回复

使用道具 举报

5#
发表于 2012-6-29 22:30:09 | 只看该作者
天才,支持技术+分享
回复

使用道具 举报

6#
发表于 2012-6-30 11:57:51 | 只看该作者
牛流满面,十来年了,终于有人分析介个了。那些不吱声的都是魂淡
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-5-12 17:35

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表