无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 4420|回复: 8
打印 上一主题 下一主题

新来的,贡献个东西给大家,NT,2000,XP CDROM 引导扇区分析

[复制链接]
跳转到指定楼层
1#
发表于 2001-11-18 21:37:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
07C0:0000 FA            cli                         ;禁止中断
07C0:0001 33C0          xor ax, ax
07C0:0003 8ED0          mov ss, ax                  ;初始化运行堆栈,将 SS:SP 指向运行代码前
07C0:0005 BC007C        mov sp, 7C00
07C0:0008 FB            sti                         ;允许中断
07C0:0009 8CC8          mov ax, cs
07C0:000B 8ED8          mov ds, ax                  ;将 DS 指向 CS 相同地址,此处操作比较浪费,只用了一次
07C0:000D 52            push dx                     ;引导扇区运行时 DX 保存当前引导磁盘号
;下面几条指令用于取得装入偏移地址,由于不能直接对 IP 进行 mov 指令
;所以使用一条 CALL 指令利用堆栈将 IP 取出
07C0:000E E80000        call 0011                   ;执行一条函数调用指令,从而将下一条指令的地址压入堆栈
07C0:0011 5E            pop si                      ;取出刚刚压入的地址
07C0:0012 81EE1100      sub si, 0011                ;减掉偏转地址得到实际的开始偏移
07C0:0016 7412          je 002A                     ;如果偏移为零跳转
;判断装入地址是否为 0000:7C00 如果是则使用远跳转进行地址转换到 0037
07C0:0018 81FE007C      cmp si, 7C00                ;装入偏移是否为 7C00
07C0:001C 7575          jne 0093
07C0:001E 8CC8          mov ax, cs                  ;取得装入段地址,此句多余,见 0009
07C0:0020 3D0000        cmp ax, 0000                ;装入段地址是否为 0000
07C0:0023 757F          jne 00A4
07C0:0025 EA3700C007    jmp 0037                    ;使用远跳转指令进行地址转换
;判断装入地址是否为 0000 如果是则直接进行运行到 0037
07C0:002A C606AE0133    mov byte ptr [01AE], 33     ;修改错误代码为 "3",意义为装载地址错误
07C0:002F 90            nop
07C0:0030 8CC8          mov ax, cs                  ;多余,同 001E
07C0:0032 3DC007        cmp ax, 07C0                ;装入段地址是否为 07C0
07C0:0035 757E          jne 00B5
;前面这段代码用于解决不同系统装入地址的问题,合法地址为 0000:7C00 或 07C0:0000
;如果地址不正确,则进行错误处理,运行到此处地址应全部转换为 07C0:0037
07C0:0037 8CC8          mov ax, cs                  ;取什么取,一定是 07C0 了
07C0:0039 8ED8          mov ds, ax                  ;这次才真的有用,见 000B
07C0:003B C606AE0134    mov byte ptr [01AE], 34     ;修改错误代码为 "4",意义为非法引导盘
07C0:0040 90            nop
07C0:0041 80FA80        cmp dl, 80                  ;查看当前引导磁盘号是否小于 80 ,即不是硬盘或 CDROM
07C0:0044 726F          jb 00B5                     ;如果是则转移错误处理
07C0:0046 C606AE0135    mov byte ptr [01AE], 35     ;修改错误代码为 "5",意义为引导扇区非法或不完整
07C0:004B 90            nop
07C0:004C BBFE07        mov bx, 07FE                ;BX 指向引导扇区结尾标志
07C0:004F 8B07          mov ax, [bx]                ;取出标志
07C0:0051 3D55AA        cmp ax, AA55                ;是否为 AA55
07C0:0054 755F          jne 00B5                    ;如果不是,则转移错误处理
;装载 BOOTFIX.BIN 并运行,显示 "Press any key to boot from CD"
;如果没有此文件则直接跳过
07C0:0056 5A            pop dx                      ;恢复引导磁盘号
07C0:0057 88169904      mov [0499], dl              ;保存磁盘号至数据区
07C0:005B 688A04        push 048A                   ;"BOOTFIX.BIN" 文件名的地址
07C0:005E 6A0B          push 000B                   ;文件名长度为 11
07C0:0060 680020        push 2000                   ;装载起始段地址 2000
07C0:0063 E87603        call 03DC                   ;调用装载函数
07C0:0066 0F820F00      jb 0079                     ;如果不成功则直接跳过
07C0:006A 60            pusha
07C0:006B 1E            push ds
07C0:006C 06            push es                     ;保存当前运行现场
07C0:006D 8A169904      mov dl, [0499]              ;取出当前引导磁盘号
07C0:0071 9A00000020    call 2000:0000              ;运行刚刚装载的 BOOTFIX.BIN
07C0:0076 07            pop es
07C0:0077 1F            pop ds
07C0:0078 61            popa                        ;恢复运行现场
;装载 SETUPLDR.BIN 并运行
07C0:0079 687E04        push 047E                   ;"SETUPLDR.BIN" 文件名的地址
07C0:007C 6A0C          push 000C                   ;文件名长度为 12
07C0:007E 680020        push 2000                   ;装载起始段地址 2000
07C0:0081 E85803        call 03DC                   ;调用装载函数
07C0:0084 0F823500      jb 00BD                     ;如果不成功则转错误处理
07C0:0088 8A169904      mov dl, [0499]              ;取出当前引导磁盘号
07C0:008C 33C0          xor ax, ax
07C0:008E 680020        push 2000
07C0:0091 50            push ax                     ;在堆栈中制造 2000:0000 的返回地址
07C0:0092 CB            retf                        ;转移到 2000:0000 运行刚装载的 SETUPLDR.BIN
;由 07C0:001C 转此
07C0:0093 56            push si
07C0:0094 8BDE          mov bx, si
07C0:0096 81C3AE01      add bx, 01AE                ;计算偏移
07C0:009A C60731        mov byte ptr [bx], 31       ;修改错误代码为 "1",意义为引导段地址错误
07C0:009D 81C68A01      add si, 018A                ;"CDBOOT: Cannot  boot from CD - Code: "
07C0:00A1 EB2A          jmp 00CD                    ;显示并重新引导
07C0:00A3 90            nop
;由 07C0:0023 转此
07C0:00A4 56            push si
07C0:00A5 8BDE          mov bx, si
07C0:00A7 81C3AE01      add bx, 01AE
07C0:00AB C60732        mov byte ptr [bx], 32       ;修改错误代码为 "2",意义为引导偏移地址错误
07C0:00AE 81C68A01      add si, 018A                ;"CDBOOT: Cannot  boot from CD - Code: "
07C0:00B2 EB19          jmp 00CD                    ;显示并重新引导
07C0:00B4 90            nop
;由 07C0:0035, 07C0:0044, 07C0:0054 转此
07C0:00B5 6A00          push 0000
07C0:00B7 BE8A01        mov si, 018A                ;"CDBOOT: Cannot  boot from CD - Code: "
07C0:00BA EB11          jmp 00CD                    ;显示并重新引导
07C0:00BC 90            nop
;由 07C0:0084 转此
07C0:00BD 6A00          push 0000
07C0:00BF BEB201        mov si, 01B2                ;"CDBOOT: Couldn't find NTLDR"
07C0:00C2 EB09          jmp 00CD                    ;显示并重新引导
07C0:00C4 90            nop
;由 07C0:0367 转此
07C0:00C5 6A00          push 0000
07C0:00C7 BED001        mov si, 01D0                ;"CDBOOT: Memory  overflow error"
07C0:00CA EB01          jmp 00CD                    ;显示并重新引导
07C0:00CC 90            nop
;显示并重新引导,si 中为要显示的信息
07C0:00CD E80400        call 00D4                   ;显示 si 中的信息
07C0:00D0 5E            pop si                      ;恢复引导扇区被装载的偏移地址
07C0:00D1 EB12          jmp 00E5                    ;开始错误处理
07C0:00D3 90            nop
;显示信息函数,入口:
;si: 信息起始地址, 0 结尾
07C0:00D4 AC            lodsb                       ;取一个字符
07C0:00D5 0AC0          or al , al                  ;是否结尾
07C0:00D7 0F840900      je 00E4
07C0:00DB B40E          mov ah, 0E
07C0:00DD BB0700        mov bx, 0007
07C0:00E0 CD10          int 10                      ;显示
07C0:00E2 EBF0          jmp 00D4
07C0:00E4 C3            ret
;错误处理,此间地址可能因装载地址不同有所不同,所以使用 si 作为基础地址进行地址运算
;首先延时 0024 次时钟中断,即 36 * 55 = 1980 ms,大约两秒
07C0:00E5 C7846B042400  mov word ptr [si+046B], 0024 ;设定延时计数器为 0024
07C0:00EB FA            cli
07C0:00EC 06            push es
07C0:00ED 33C0          xor ax, ax
07C0:00EF 8EC0          mov es, ax                  ;es 指向中断地址表
07C0:00F1 BB2000        mov bx, 0020                ;bx 指向中断 08 的偏移
07C0:00F4 268B07        mov ax, es:[bx]
07C0:00F7 89846704      mov [si+0467], ax
07C0:00FB 268B4702      mov ax, es:[bx+02]
07C0:00FF 89846904      mov [si+0469], ax           ;保存原中断 08 的地址到 0467
07C0:0103 268937        mov es:[bx], si
07C0:0106 2681076D01    add word ptr es:[bx], 016D
07C0:010B 268C4F02      mov es:[bx+02], cs          ;将中断 08 指向 07C0:016B
07C0:010F 07            pop es
07C0:0110 FB            sti
07C0:0111 83BC6B0400    cmp word ptr [si+046B], 0000 ;查看计数器是否结束
07C0:0116 75F9          jne 0111
07C0:0118 FA            cli
07C0:0119 06            push es
07C0:011A 33C0          xor ax, ax
07C0:011C 8EC0          mov es, ax
07C0:011E BB2000        mov bx, 0020
07C0:0121 8B846704      mov ax, [si+0467]
07C0:0125 268907        mov es:[bx], ax
07C0:0128 8B846904      mov ax, [si+0469]
07C0:012C 26894702      mov es:[bx+02], ax          ;恢复刚才保存的中断 08 的地址
07C0:0130 07            pop es
07C0:0131 FB            sti
;将引导扇区代码移动到 2000:0000,以便在 07C0:0000 装载新的引导扇区
07C0:0132 1E            push ds
07C0:0133 06            push es
07C0:0134 B80020        mov ax, 2000
07C0:0137 8EC0          mov es, ax
07C0:0139 8CC8          mov ax, cs
07C0:013B 8ED8          mov ds, ax
07C0:013D 33FF          xor di, di
07C0:013F B90008        mov cx, 0800
07C0:0142 F3            repz
07C0:0143 A4            movsb
07C0:0144 07            pop es
07C0:0145 1F            pop ds
07C0:0146 EA4B010020    jmp 2000:014B               ;转移到
;在 07C0:0000 装载硬盘的引导扇区此段代码执行时已经被移动到 2000:014B
07C0:014B 06            push es
07C0:014C B8C007        mov ax, 07C0
07C0:014F 8EC0          mov es, ax
07C0:0151 BB0000        mov bx, 0000
07C0:0154 B80102        mov ax, 0201
07C0:0157 B90100        mov cx, 0001
07C0:015A BA8000        mov dx, 0080
07C0:015D CD13          int 13
07C0:015F 0F830200      jnb 0165
07C0:0163 EBFE          jmp 0163                    ;如果装载失败,则死循环
07C0:0165 07            pop es
07C0:0166 B280          mov dl, 80
07C0:0168 EA007C0000    jmp 0000:7C00               ;转移到硬盘引导扇区处理
;新的中断 08 处理程序,每次中断产生都将计数器减一,减至零为止
07C0:016D 9C            pushf
07C0:016E FA            cli
07C0:016F 2E83BC6B0400  cmp word ptr cs:[si+046B], 0000 ;计数器是否为零
07C0:0175 0F840500      je 017E
07C0:0179 2EFF8C6B04    dec word ptr cs:[si+046B]   ;不为零则减一
07C0:017E 9D            popf
07C0:017F 2EFFB46904    push word ptr cs:[si+0469]
07C0:0184 2EFFB46704    push word ptr cs:[si+0467]  ;将原中断地址压入堆栈
07C0:0189 CB            retf                        ;转入系统中断处理程序继续处理
;错误提示信息
07C0:018A               DB "CDBOOT: Cannot  boot from CD - Code: "
07C0:01AE               DB "0", 0D, 0A, 00                  ;错误代码
07C0:01B2               DB "CDBOOT: Couldn't find NTLDR", 0D, 0A, 00
07C0:01D0               DB "CDBOOT: Memory  overflow error", 0D, 0A, 00
;以下为前面的代码中使用的函数
;从刚刚读取的目录中搜索指定的字符串
;这段的作用就是在整个目录中查找指定的文件
;查找的时候考虑了远指针的最小化偏移
;并且考虑了跨段的查找问题
;纯粹算法,没什么逻辑,所以比较烦琐,也比较无聊
;如果想了解的话可以自己查 iso9660 里面有关目录项的内容去一行行详细分析
07C0:01F0 C606B10400    mov byte ptr [04B1], 00     ;
07C0:01F5 90            nop
07C0:01F6 8B0E9E04      mov cx, [049E]              ;取出读取的字符数低位
07C0:01FA FC            cld
07C0:01FB 33DB          xor bx, bx                  ;es:bx 指向目录开始
07C0:01FD 33D2          xor dx, dx
07C0:01FF 8B36AD04      mov si, [04AD]              ;要搜索的字符串的地址
07C0:0203 268A17        mov dl, es:[bx]             ;取该目录项长度
07C0:0206 80FA00        cmp dl, 00                  ;如果长度为零,则跳过该项
07C0:0209 0F843B00      je 0248
07C0:020D 8BC3          mov ax, bx
07C0:020F 052100        add ax, 0021                ;加 21H 指向目录项中文件名
07C0:0212 8BF8          mov di, ax
07C0:0214 51            push cx
07C0:0215 33C9          xor cx, cx
07C0:0217 8A0EAF04      mov cl , [04AF]             ;cx 为字符串长度
07C0:021B F3            repz
07C0:021C A6            cmpsb                       ;比较字符串
07C0:021D 59            pop cx
07C0:021E 0F846F00      je 0291                     ;如果相同
07C0:0222 3BD1          cmp dx, cx                  ;比较目录项长度与总长度的低位
07C0:0224 0F833700      jnb 025F                    ;如果不足则处理总长度高位
07C0:0228 2BCA          sub cx, dx                  ;从总长度低位中减掉当前目录项长度
07C0:022A 803EB10401    cmp byte ptr [04B1], 01
07C0:022F 0F841A00      je 024D
07C0:0233 03D3          add dx, bx                  ;偏移地址加本目录项指向下一目录项
07C0:0235 8BDA          mov bx, dx
07C0:0237 83E30F        and bx, 000F
07C0:023A 51            push cx
07C0:023B B104          mov cl, 04
07C0:023D D3EA          shr dx, cl
07C0:023F 59            pop cx
07C0:0240 8CC0          mov ax, es
07C0:0242 03C2          add ax, dx
07C0:0244 8EC0          mov es, ax                  ;最小化远指针偏移
07C0:0246 EBB7          jmp 01FF
07C0:0248 BA0100        mov dx, 0001                ;设定长度为一,直接进入下次比较
07C0:024B EBD5          jmp 0222
07C0:024D 41            inc cx
07C0:024E C606B10400    mov byte ptr [04B1], 00
07C0:0253 90            nop
07C0:0254 EBDD          jmp 0233
07C0:0256 C606B10401    mov byte ptr [04B1], 01
07C0:025B 90            nop
07C0:025C EB29          jmp 0287
07C0:025E 90            nop
07C0:025F 833EA00400    cmp word ptr [04A0], 0000   ;总长度高位是否为零
07C0:0264 0F850200      jne 026A                    ;如果不为零则继续处理
07C0:0268 F9            stc                         ;没有找到
07C0:0269 C3            ret
07C0:026A 832EA00401    sub word ptr [04A0], 0001   ;高位减一
07C0:026F 03DA          add bx, dx                  ;偏移地址加本目录项指向下一目录项
07C0:0271 53            push bx
07C0:0272 51            push cx
07C0:0273 B104          mov cl, 04
07C0:0275 D3EB          shr bx, cl
07C0:0277 59            pop cx
07C0:0278 8CC0          mov ax, es
07C0:027A 03C3          add ax, bx
07C0:027C 8EC0          mov es, ax                  ;最小化远指针偏移
07C0:027E 5B            pop bx
07C0:027F 83E30F        and bx, 000F
07C0:0282 2BD1          sub dx, cx
07C0:0284 74D0          je 0256
07C0:0286 4A            dec dx
07C0:0287 B8FFFF        mov ax, FFFF
07C0:028A 2BC2          sub ax, dx
07C0:028C 8BC8          mov cx, ax                  ;得到新的总长度的地位剩余值
07C0:028E E96EFF        jmp 01FF                    ;继续查找
07C0:0291 803EB00401    cmp byte ptr [04B0], 01     ;此次查找是否是子目录
07C0:0296 0F840A00      je 02A4                     ;如果是子目录则转子目录属性检查
07C0:029A 26F6471902    test byte ptr es:[bx+19], 02 ;查看目录属性是否为文件
07C0:029F 7581          jne 0222                    ;如果不是继续查找
07C0:02A1 EB0A          jmp 02AD
07C0:02A3 90            nop
07C0:02A4 26F6471902    test byte ptr es:[bx+19], 02 ;查看目录属性是否为子目录
07C0:02A9 0F8475FF      je 0222                     ;如果不是则继续查找
07C0:02AD A0AF04        mov al, [04AF]
07C0:02B0 26384720      cmp es:[bx+20], al          ;比较文件名长度
07C0:02B4 0F856AFF      jne 0222                    ;不相同则继续比较
07C0:02B8 F8            clc                         ;清除标记,查找成功
07C0:02B9 C3            ret
;下面的几个函数使用了类 C 的参数传递方法
;所以大家看到了熟悉的 push bp / mov bp, sp 指令对
;但是显然作者对高级语言函数堆栈组织不很熟悉,
;连函数结尾的 mov sp, bp 也生搬了过来
;这条指令是高级语言用来释放自动局部变量的
;而这里的几个函数则根本没有使用局部变量
;其实如果使用局部变量的话这里的几个函数会比较好看一些,
;我指的是看起来比较象 C 的反汇编代码
;呵呵
;读指定扇区到内存,使用扩展磁盘读写
;考虑到 DOS 下的 64K 数据段的限制, 读操作是循环执行的.
07C0:02BA 55            push bp
07C0:02BB 8BEC          mov bp, sp
07C0:02BD 53            push bx
07C0:02BE 56            push si
07C0:02BF 52            push dx
07C0:02C0 50            push ax                     ;保存寄存器
07C0:02C1 BB6D04        mov bx, 046D                ;bx 指向扩展磁盘读结构
07C0:02C4 C60710        mov byte ptr [bx], 10
07C0:02C7 C6470100      mov byte ptr [bx+01], 00
07C0:02CB C6470300      mov byte ptr [bx+03], 00
07C0:02CF C747040000    mov word ptr [bx+04], 0000
07C0:02D4 C7470C0000    mov word ptr [bx+0C], 0000
07C0:02D9 C7470E0000    mov word ptr [bx+0E], 0000  ;全部清除
;将调用参数复制到临时数据区
07C0:02DE 8B460C        mov ax, [bp+0C]
07C0:02E1 A3A204        mov [04A2], ax
07C0:02E4 8B460A        mov ax, [bp+0A]
07C0:02E7 A3A404        mov [04A4], ax              ;读盘总扇区数,32 位,分两次处理
07C0:02EA 8B4608        mov ax, [bp+08]
07C0:02ED A3A604        mov [04A6], ax              ;数据区的段地址
07C0:02F0 8B4606        mov ax, [bp+06]
07C0:02F3 A3A804        mov [04A8], ax
07C0:02F6 8B4604        mov ax, [bp+04]
07C0:02F9 A3AA04        mov [04AA], ax              ;开始逻辑扇区号,32位
;以上将调用时传递的参数保存在数据区以便使用,
;其实大可不必,既然用了类 C 的参数传递,
;那么完全可以直接使用这些实参当变量用
07C0:02FC 813EA4040000  cmp word ptr [04A4], 0000
07C0:0302 0F851900      jne 031F
07C0:0306 813EA2042000  cmp word ptr [04A2], 0020
07C0:030C 0F8F0F00      jg 031F                     ;总扇区数是否小于 20
;保证每次读取的数据量不超过 64K.
;如果总扇区数小于 20H ,即 20H * 800H = 10000H, 正好是 64K 一个数据段的尺寸
;注意,这里处理的是 CDROM 的扇区, 所以扇区大小是 800H, 2048 字节
07C0:0310 C6067D0400    mov byte ptr [047D], 00     ;清除标记标示不需段处理
07C0:0315 90            nop
07C0:0316 A1A204        mov ax, word ptr [04A2]
07C0:0319 A2AC04        mov byte ptr [04AC], al     ;直接读取总扇区数
07C0:031C EB0D          jmp 032B
07C0:031E 90            nop
07C0:031F C6067D0401    mov byte ptr [047D], 01     ;置标记标示需要段处理
07C0:0324 90            nop
07C0:0325 C606AC0420    mov byte ptr [04AC], 20     ;每次固定读取 20 个扇区,即 64K 数据
07C0:032A 90            nop
07C0:032B A0AC04        mov al, [04AC]                  
07C0:032E 884702        mov [bx+02], al             ;扇区数
07C0:0331 A1A604        mov ax, [04A6]
07C0:0334 894706        mov [bx+06], ax             ;数据区的段地址
07C0:0337 A1A804        mov ax, [04A8]
07C0:033A 894708        mov [bx+08], ax
07C0:033D A1AA04        mov ax, [04AA]
07C0:0340 89470A        mov [bx+0A], ax             ;开始逻辑扇区号
07C0:0343 BE6D04        mov si, 046D
07C0:0346 B442          mov ah, 42
07C0:0348 8A169904      mov dl, [0499]              ;取出引导磁盘号
07C0:034C CD13          int 13                      ;操作
07C0:034E 803E7D0401    cmp byte ptr [047D], 01     ;是否还需要读取?
07C0:0353 0F852200      jne 0379
07C0:0357 832EA20420    sub word ptr [04A2], 0020
07C0:035C 831EA40400    sbb word ptr [04A4], 0000   ;总扇区数减掉 20
07C0:0361 8106A6040010  add word ptr [04A6], 1000   ;数据段地址减掉 1000, 指向下一个 64K.
07C0:0367 0F825AFD      jb 00C5                     ;如果溢出则转错误
07C0:036B 8106A8042000  add word ptr [04A8], 0020
07C0:0371 8116AA040000  adc word ptr [04AA], 0000   ;开始逻辑扇区号加 20
07C0:0377 EB83          jmp 02FC                    ;开始下一次循环读取
07C0:0379 58            pop ax                      ;恢复寄存器
07C0:037A 5A            pop dx
07C0:037B 5E            pop si
07C0:037C 5B            pop bx
07C0:037D 8BE5          mov sp, bp
07C0:037F 5D            pop bp
07C0:0380 C3            ret

;从指定扇区开始读取指定的字节数到内存
;调用 02BA 完成读取
07C0:0381 55            push bp
07C0:0382 8BEC          mov bp, sp
07C0:0384 51            push cx
07C0:0385 53            push bx
07C0:0386 50            push ax
;将字节数转换为逻辑扇区数,不足一个扇区按照一个扇区计算
07C0:0387 B10B          mov cl, 0B
07C0:0389 8B1EA004      mov bx, [04A0]
07C0:038D A19E04        mov ax, [049E]
07C0:0390 0FADD8        shrd ax, bx, cl
07C0:0393 D3EB          shr bx, cl                  ;将 bx:ax 右移 11 位,即除 2048
07C0:0395 F7069E04FF07  test word ptr [049E], 07FF  ;低位是否为零
07C0:039B 7406          je 03A3
07C0:039D 050100        add ax, 0001
07C0:03A0 83D300        adc bx, 0000                ;不是则加一
07C0:03A3 50            push ax
07C0:03A4 53            push bx                     ;总扇区数
07C0:03A5 FF7604        push word ptr [bp+04]       ;段地址
07C0:03A8 FF369A04      push word ptr [049A]
07C0:03AC FF369C04      push word ptr [049C]        ;开始逻辑扇区号
07C0:03B0 E807FF        call 02BA                   ;读扇区
07C0:03B3 83C40A        add sp, 000A
07C0:03B6 58            pop ax                      ;恢复寄存器
07C0:03B7 5B            pop bx
07C0:03B8 59            pop cx
07C0:03B9 8BE5          mov sp, bp
07C0:03BB 5D            pop bp
07C0:03BC C3            ret
;取出目录项的起始扇区和字节数
07C0:03BD 50            push ax
07C0:03BE 268B4702      mov ax, es:[bx+02]
07C0:03C2 A39A04        mov [049A], ax
07C0:03C5 268B4704      mov ax, es:[bx+04]
07C0:03C9 A39C04        mov [049C], ax              ;开始逻辑扇区号
07C0:03CC 268B470A      mov ax, es:[bx+0A]
07C0:03D0 A39E04        mov [049E], ax
07C0:03D3 268B470C      mov ax, es:[bx+0C]
07C0:03D7 A3A004        mov [04A0], ax              ;字节数
07C0:03DA 58            pop ax
07C0:03DB C3            ret
;装载函数,入口为: 文件名地址, 文件名长度, 装载段地址
07C0:03DC 55            push bp
07C0:03DD 8BEC          mov bp, sp
;读 CDROM 引导信息
07C0:03DF 6A01          push 0001
07C0:03E1 6A00          push 0000                   ;总扇区数 00000001
07C0:03E3 680010        push 1000                   ;段地址 1000
07C0:03E6 6A10          push 0010
07C0:03E8 6A00          push 0000                   ;开始逻辑扇区号 00000010
07C0:03EA E8CDFE        call 02BA                   ;读扇区
07C0:03ED 83C40A        add sp, 000A
;取出 root 目录信息
07C0:03F0 B80010        mov ax, 1000
07C0:03F3 8EC0          mov es, ax
07C0:03F5 26A19E00      mov ax, es:[009E]
07C0:03F9 A39A04        mov [049A], ax
07C0:03FC 26A1A000      mov ax, es:[00A0]
07C0:0400 A39C04        mov [049C], ax              ;开始逻辑扇区号
07C0:0403 26A1A600      mov ax, es:[00A6]
07C0:0407 A39E04        mov [049E], ax
07C0:040A 26A1A800      mov ax, es:[00A8]
07C0:040E A3A004        mov [04A0], ax              ;读取字节数
07C0:0411 680010        push 1000                   ;段地址 1000
07C0:0414 E86AFF        call 0381                   ;读数据
07C0:0417 83C402        add sp, 0002
;在 root 目录中中搜索 "I386"
07C0:041A C706AD049504  mov word ptr [04AD], 0495   ;"I386" 地址
07C0:0420 C606AF0404    mov byte ptr [04AF], 04     ;长度 4
07C0:0425 90            nop
07C0:0426 C606B00401    mov byte ptr [04B0], 01     ;置目录项标记,查找时检查是否为子目录
07C0:042B 90            nop
07C0:042C E8C1FD        call 01F0                   ;开始搜索
07C0:042F 7234          jb 0465                     ;如果没有找到
;将找到的 "I386" 目录读出来
07C0:0431 E889FF        call 03BD                   ;取出起始扇区和字节数
07C0:0434 680010        push 1000
07C0:0437 E847FF        call 0381                   ;读取扇区
07C0:043A 83C402        add sp, 0002
;在 I386 中搜索调用函数时的指定文件
07C0:043D B80010        mov ax, 1000
07C0:0440 8EC0          mov es, ax
07C0:0442 8B4608        mov ax, [bp+08]
07C0:0445 A3AD04        mov [04AD], ax              ;文件名地址
07C0:0448 8A4606        mov al , [bp+06]
07C0:044B A2AF04        mov byte ptr [04AF], al     ;文件名长度
07C0:044E C606B00400    mov byte ptr [04B0], 00     ;置目录项标记,查找时检查是否为文件
07C0:0453 90            nop
07C0:0454 E899FD        call 01F0                   ;开始搜索
07C0:0457 720C          jb 0465                     ;如果没有找到
;将找到的指定文件读出来
07C0:0459 E861FF        call 03BD                   ;取出起始扇区和字节数
07C0:045C FF7604        push word ptr [bp+04]
07C0:045F E81FFF        call 0381                   ;读取扇区
07C0:0462 83C402        add sp, 0002
07C0:0465 5D            pop bp
07C0:0466 C3            ret
;代码结束,开始数据区
07C0:0467               DW 0000, 00000              ;保存中断 08 的原地址
07C0:046B               DW 0000                     ;延时计数器
;此处存放磁盘扩展读结构
07C0:046D               DB 00                       ;结构尺寸
07C0:046E               DB 00                       ;保留
07C0:046F               DB 00                       ;要读取的扇区数
07C0:0470               DB 00                       ;保留
07C0:0471               DW 0000, 0000               ;读取数据的目标地址
07C0:0475               DD 00                       ;开始逻辑扇区
07C0:047A               DW 0000                     ;保留
07C0:047D               DW 0000                     ;段处理标记, 为零不需处理
07C0:047E               DB "SETUPLDR.BIN"
07C0:048A               DB "BOOTFIX.BIN"
07C0:0495               DB "I386"
07C0:0499               DB 0000                     ;磁盘号
07C0:049A               DW 0000
07C0:049C               DW 0000                     ;开始逻辑扇区号
07C0:049E               DW 0000
07C0:04A0               DW 0000                     ;读取字节数
;此处存放读盘操作的临时数据
07C0:04A2               DW 0000, 0000               ;总扇区数
07C0:04A6               DW 0000                     ;数据区的段地址
07C0:04A8               DW 0000, 0000               ;开始逻辑扇区号
07C0:04AC               DW 0000                     ;扇区数
07C0:04AD               DW 0000                     ;搜索字符串地址
07C0:04AF               DW 0000                     ;长度
07C0:04B0               DB 00                       ;目录项标记,为 1 表示查找子目录
07C0:04B1               DB 00
07C0:07FE               DB 55, AA
仓促完成,不足的大家补充。
2#
发表于 2009-10-17 07:45:33 | 只看该作者
写的好!
支持一下!!!!!!!

[ 本帖最后由 天涯海角1216 于 2009-10-17 07:47 编辑 ]
回复

使用道具 举报

3#
发表于 2009-10-17 08:29:20 | 只看该作者
这么古老的帖子都叫沙发翻出来了,看来沙发很有心。
回复

使用道具 举报

4#
发表于 2009-10-17 10:25:39 | 只看该作者
好几年前的,不过还是很有芯哦
回复

使用道具 举报

5#
发表于 2009-10-17 16:33:03 | 只看该作者
天啊!书啊!天书啊!
回复

使用道具 举报

6#
发表于 2009-10-17 18:12:04 | 只看该作者
书啊,天啊,在哪???

400贴留念。。。
回复

使用道具 举报

7#
发表于 2009-10-17 21:57:17 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

8#
发表于 2009-10-20 18:59:50 | 只看该作者
虚拟的框架下,我们谁又认识最原始又是最真实的东西.那是1和0的世界,今天是无数旧人智慧堆积而起的.
回复

使用道具 举报

9#
发表于 2009-10-20 21:53:22 | 只看该作者

顶一个!

玩这东西(汇编)多年,很怀念那些日子。
回复

使用道具 举报

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

本版积分规则

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

闽公网安备 35020302032614号

GMT+8, 2025-8-6 19:39

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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