您的位置:首页 > 移动开发 > Unity3D

若用MASM写操作系统的启动部分如何实现? 其他开发语言 / 汇编语言 - CSDN社区 community.csdn.net

2008-05-25 13:41 751 查看
导读:
偶有个笨方法,不过总是可行的,偶也是成功了才几天  
   
  希望有参考价值  
  偶在windows98下写代码,工具DEBUG(windows自带),只有MASM5.0  
   
   
  ;boot.txt,汇编连接成boot.exe   “org   7c00h”是为了让MASM计算标号和变量地址时得到正确值  
  CSEG           SEGMENT  
                    ASSUME   CS:CSEG,DS:CSEG,ES:CSEG  
                    ORG   7C00H  
  START:       XOR   AX,AX  
                    MOV   DS,AX  
                    MOV   ES,AX                                                                 ;DS,ES置0  
   
                    JMP   OVER                                                                    
   
  ADDRES       DD   00F00000H  
  MESSAGE     DB   'this   is   maguarel   speaking:meme!laopo!press   any   key   to   boot   from   c:'       ;待显示的字符串  
  GETAWAY:   MOV   AX,00F0H  
                    MOV   DS,AX  
                    MOV   AX,0000H  
                    MOV   ES,AX                                                                 ;GETAWAY这小段代码执行时,本代码已经移动到00F0:...处了  
   
                    MOV   AX,0201H  
                    MOV   BX,7C00H  
                    MOV   CX,1H  
                    MOV   DX,80H                                                               ;装载C:的启动扇区至0000:7C00..刚才我在这里的,现在让位了:(  
                    INT   13H  
   
                    MOV   WORD   PTR   [ADDRES],7C00H                             ;设置跳转地址为0000:7C00  
                    MOV   WORD   PTR   [ADDRES+2],0000H  
   
                    JMP   [ADDRES]                                                           ;执行C:的启动扇区,从此控制权交出,本代码宣告死亡  
                     
  OVER:         MOV   AL,3H  
                    MOV   AH,0H  
                    INT   10H  
   
                    MOV   AL,'$'  
                    MOV   AH,09H  
                    MOV   BL,9FH  
                    MOV   CX,10D  
                    MOV   BH,0                                                                     ;显示10个$  
                    INT   10H  
   
                    MOV   BP,OFFSET   MESSAGE  
                    MOV   CX,66D  
                    MOV   DH,12D  
                    MOV   DL,0D  
                    MOV   BL,41H  
                    MOV   AL,1  
                    MOV   AH,13H                                                                 ;显示MESSAGE:提示按任意键  
                    INT   10H  
                     
                    MOV   AH,10H  
                    INT   16H                                                                         ;等待按键,注意这是BIOS中断,一按键,即顺序执行,无按键则等待  
   
                    MOV   AX,00F0H  
                    MOV   ES,AX  
                    MOV   SI,OFFSET   START  
                    MOV   DI,7C00H                                                             ;设置循环  
                    MOV   CX,200H                                                                  
   
   
  CHANGE:     MOV   AL,[SI]  
                    MOV   ES:[DI],AL  
                    INC   SI  
                    INC   DI                                                                           ;循环工作部分,移动自身至00F0:7C00                                                                                                                                                             ;让出0000:7C00给C:的引导程序  
                    LOOP   CHANGE  
   
                    MOV   BX,OFFSET   GETAWAY                                             ;设置跳转偏移  
                    MOV   WORD   PTR   [ADDRES],BX  
                    JMP   [ADDRES]                                                               ;跳转执行移动后的代码  
   
   
                 
   
  CSEG           ENDS  
                    END   START  
   
   
  为了得到纯二进制boot.bin,详细操作相当烦锁:  
   
  汇编链接boot.txt,得boot.exe,32K的..-   -,将其改名为ww.cc,再DEBUG   ww.cc(改名是因为DEBUG调试*.exe文件时太过"自作聪明",地址给它弄的很乱),找到代码开始在偏移XXXX:7F00处,用W命令从7F00开始导出为文件...(DEBUG好像没有导出指定7F00到哪为止的功能-   -,为此又编写了一个FIX程序,工作是将DEBUG导出的文件保留前面510字节,后面的全剪掉,再在未尾加上55AAH,正好512字节),这就是boot.bin了.把它写到磁盘首扇区,编个小程序或用DEBUG都可实现  
   
  这是第一次写引导扇区,可能作了很多多余的工作,不过不要紧,总算是可行的办法  
   
  ;这是用来剪掉debug导出的文件,保留前510字节,再在未尾加上55aa  
  DSEG   SEGMENT  
  FNAME1   DB   'F:/STDIO/WWW.CC',0  
  FNAME2   DB   'F:/STDIO/ML/FIR.TXT',0  
  MESS   DB   'CHU   CUO   LA!NI   GE   ZHU!','$'  
  BUFFER   DB   510   DUP   (0)  
  JIESHU   DW   0AA55H                                         ;未尾两字节写上55aa  
  HANDLE   DW   ?  
  DSEG   ENDS  
  CSEG   SEGMENT  
            ASSUME   DS:DSEG,CS:CSEG,ES:DSEG  
  START:MOV   AX,DSEG  
            MOV   DS,AX                                
            MOV   ES,AX                                
   
                                             
   
            MOV   AL,02H  
            MOV   AH,3DH  
            MOV   DX,OFFSET   FNAME1  
            INT   21H                                   ;打开目标文件1  
            JC   ERROR                                 ;失败则跳转  
             
            MOV   HANDLE,AX  
            MOV   BX,AX  
            MOV   CX,1FDH                             ;1FD=510  
            MOV   DX,OFFSET   BUFFER  
            MOV   AH,3FH  
            INT   21H                                   ;读出文件1前面510字节存至BUFFER  
            JC   ERROR                                 ;失败跳转  
   
   
            MOV   BX,HANDLE  
            MOV   AH,3EH  
            INT   21H                                   ;关闭文件  
            JC   ERROR                                 ;失败则跳转  
   
   
            MOV   AL,02H  
            MOV   AH,3DH  
            MOV   DX,OFFSET   FNAME2  
            INT   21H                                   ;打开目标文件2  
            JC   ERROR                                 ;失败则跳转  
             
            MOV   HANDLE,AX  
            MOV   BX,AX  
            MOV   CX,200H  
            MOV   DX,OFFSET   BUFFER  
            MOV   AH,40H  
            INT   21H                                   ;BUFFER开始处,写进512字节至文件2  
            JC   ERROR                                 ;失败跳转  
   
            MOV   BX,HANDLE  
            MOV   AH,3EH  
            INT   21H                                   ;关闭文件  
            JC   ERROR                                 ;失败则跳转  
   
            JMP   END1                                 ;至此则表示一切成功,跳END返回DOS  
   
  ERROR:MOV   DX,OFFSET   MESS  
              MOV   AH,9H  
              INT   21H                                 ;显示错误提示  
  END1:MOV   AH,4CH  
            INT   21H                                   ;返回DOS  
   
  CSEG   ENDS  
            END   START  
   
  ---------------------------------------------------------------------------------  

 

 

其实谁也不必板面孔教训人,我用搜索也不是一天两天了,不敢说用的太好,比一般才鸟强.   坛子里多的是这样的人,喜欢动不动教训别人:你连搜索也要别人教你吗?   我的经验,这样的人未必有被他"教训"的人搜索能力强.   太喜欢教训别人不会用搜索引擎的人,   你又知道多少搜索引擎的绝招?   你敢保证你什么都能搜到,   如果你敢保证什么都搜到,任何时候都搜到,这么厉害的还没见   相信全坛子人都会服你了!   搜索,有很多误区,   有时甲比乙用的方法好,搜到了,有时乙比甲强.有时背运,搜到的连接坏了,搜到不相干的,有时搜到  
   
  终于找到一个bootrecord,分享一下  
   
   
   
   
  ;NOTE:   This   code   compiles   with   NASM!  
   
  ;If   you   can't   figure   out   how   to   modify   this   code   to   do   what   you   want,  
  ;then   you   probably   shouldn't   be   using   this   code   period.   It   can   be..   harmful.  
   
  ;Ok,   this   is   the   MBR   code.   It   will   load   a   program   located   on   sector   3  
  ;then   let   the   program   run   until   its   time   to   boot.   This   could   be   useful   if  
  ;your   program   does   stuff   that   ***   scanners   might   not   like,   cuz   I   doubt   they  
  ;scan   the   third   sector   ;^)    
   
  ;**what   we're   going   to   do:  
  ;  
  ; load   program   into   8000:0200h  
  ; run   program  
  ; program   calls   endpoint  
  ; endpoint   loads   old   MBR   to   0:7c00h*  
  ; jump   to   0:7c00h  
  ;  
  ;   *reason   we   do   this   is   just   in   case   the   real   MBR   does   something   weird  
  ; that   we   can't   do   cuz..   we   dont   know   what   its   going   to   do.   Its   safer.    
  ; Technically   we   could   just   load   CHS   1:0:0   (or   LBA   64   on   most   systems)  
  ; and   let   it   rip..   but   I   load   the   original   MBR   just   in   case.   anyway..    
   
  %include   "varibles.asm"  
   
  org   0h    
   
  start:                       ;Ok,   dont   change   this   stuff   either..                                  
                  xor   ax,ax  
                  mov   ss,ax  
                  mov   sp,7c00h  
                  sti  
                  mov   ax,8000h  
  mov   es,ax ;we'll   just   use   the   next   section   of   memory    
  ;to   play   with..   im   fairly   sure   its   not   used   for   anything  
   
  ;note:   this   code   won't   work   if   you   don't   have   more  
  ;than   32k   of   memory..   lol,   such   a   big   problem  
  load_1:  
                  mov   ah,02h                                             ;function  
  mov   al,progsize                 ;number   of   sectors   to   use,   defined   in   varibles.asm  
                  mov   cx,0003h                                         ;0-5   sec   #,   6-7   hi   cyl   bits  
                  mov   dx,0080h                                         ;dh=head   dl=drive   (bit   7=hdd)  
                  mov   bx,200h                                           ;data   buffer,   points   to   es:200h  
                  int   13h  
                  cmp   ah,0  
                  jne   load_1                                              
   
  ;initialize   jump/data   registers  
   
  mov   ax,es  
  mov   ds,ax  
  ;stack   is   set   already  
                 
  push   es ;if   the   BIOS   works,   jump   to   es:start_of_program  
  mov   ax,start_of_program  
  push   ax  
                  retf                                                         ;jump   to   code..    
   
   
  ;ok,   this   is   where   the   partition   table   is   supposed   to   be.   If   you're  
  ;smart,   you'll   leave   this   alone...   we   will   put   the   partition   table   here  
  ;when   we   install   this   code.   MAKE   SURE   YOU   DO   THIS   OR   THE   COMPUTER   WONT   BOOT!!  
                   
  times   1beh-($-$$)   db   0 ;this   weird   thing   fills   the   extra   space   with   zeros..    
   
   
                  db   80h                                   ;active  
                  times   3   db   0  
                  db   55h                                   ;fake  
                  times   11   db   0                        
   
                  times   30h   db   0                       ;more   fakeness  
   
  MBR_signature:  
                  db   55h,0aah  
   
  ;------------------------------------------------  
  ;this   is   sector   3...   ok,   its   weird,   but   it   makes   sense   in  
  ;a   weird   sort   of   way.   Don't   argue.    
  ;------------------------------------------------  
   
  load_MBR: ;remember..   this   function   needs   to   be   jumped   to    
  ;so   you   can   boot   computer!    
   
                  mov   dx,0080h                                         ;here   we   overwrite   the   original   code        
                  mov   cx,2                                                 ;sector   #  
                  mov   ax,0201h                                          
                  xor   bx,bx                                               ;offset   0  
                  int   13h  
                  cmp   ah,0  
                  jne   load_MBR ;error?   try   again..   could   freeze    
                                                                                  ;computer,   but   if   it   dont   load,   then  
                                                                                  ;who   cares   anyway?  
   
  mov   dx,0080h ;BIOS   function  
  mov   ax,0  
  push   ax  
  mov   ax,7c00h  
  push   ax  
  retf ;bye-bye   to   me..   boot   computer   now  
   
  %include   "program.asm" ;this   is   where   you   put   your   code.

 

主引导记录包括代码、数据两部分。它在被BIOS中断Int19h装入内存后获得控制权。数据  
  ;   部分最重要的当然是分区表了!彻底熟悉主引导记录,可以帮助我们了解系统的引导过程,  
  ;   处理因主引导记录损坏所造成的无法引导故障,消除引导型计算机病毒,更使我们能通过  
  ;   修改主引导记录完成我们希望的工作:如多重引导,系统加软锁等...  
  ;  
  ;   BIOS中断总是把主引导记录所在扇区(硬盘的0头0道1扇区)的内容(包括代码和数据)  
  ;   装入内存0000:7C00起始的区域,然后检验该扇区内容的最后两个字节是不是“AA55”,  
  ;   如果不是,那么对不起,Int19h将不把控制权交给主引导记录;若是,则下面的主引导记录  
  ;   才能获得了控制权了(Int19通过跳转指令交转控制权):  
  ;  
  ;   二进制形式的主引导记录:  
  0000:0600   33   C0   8E   D0   BC   00   7C   FB-50   07   50   1F   FC   BE   1B   7C   3.....|.P.P....|  
  0000:0610   BF   1B   06   50   57   B9   E5   01-F3   A4   CB   BE   BE   07   B1   04   ...PW...........  
  0000:0620   38   2C   7C   09   75   15   83   C6-10   E2   F5   CD   18   8B   14   8B   8,|.u...........  
  0000:0630   EE   83   C6   10   49   74   16   38-2C   74   F6   BE   10   07   4E   AC   ....It.8,t....N.  
  0000:0640   3C   00   74   FA   BB   07   00   B4-0E   CD   10   EB   F2   89   46   25   <.t...........F%  
  0000:0650   96   8A   46   04   B4   06   3C   0E-74   11   B4   0B   3C   0C   74   05   ..F...<.t...<.t.  
  0000:0660   3A   C4   75   2B   40   C6   46   25-06   75   24   BB   AA   55   50   B4   :.u+@.F%.u$..UP.  
  0000:0670   41   CD   13   58   72   16   81   FB-55   AA   75   10   F6   C1   01   74   A..Xr...U.u....t  
  0000:0680   0B   8A   E0   88   56   24   C7   06-A1   06   EB   1E   88   66   04   BF   ....V$.......f..  
  0000:0690   0A   00   B8   01   02   8B   DC   33-C9   83   FF   05   7F   03   8B   4E   .......3.......N  
  0000:06A0   25   03   4E   02   CD   13   72   29-BE   2D   07   81   3E   FE   7D   55   %.N...r).-..>.}U  
  0000:06B0   AA   74   5A   83   EF   05   7F   DA-85   F6   75   83   BE   1A   07   EB   .tZ.......u.....  
  0000:06C0   8A   98   91   52   99   03   46   08-13   56   0A   E8   12   00   5A   EB   ...R..F..V....Z.  
  0000:06D0   D5   4F   74   E4   33   C0   CD   13-EB   B8   00   00   80   49   12   00   .Ot.3........I..  
  0000:06E0   56   33   F6   56   56   52   50   06-53   51   BE   10   00   56   8B   F4   V3.VVRP.SQ...V..  
  0000:06F0   50   52   B8   00   42   8A   56   24-CD   13   5A   58   64   10   72   PR..B.V$..ZX.d.r  
  0000:0700   0A   40   75   01   42   80   C7   02-E2   F7   F8   5E   C3   EB   74   B7   .@u.B......^..t.  
  0000:0710   D6   C7   F8   B1   ED   CE   DE   D0-A7   00   BC   D3   D4   D8   B2   D9   ................  
  0000:0720   D7   F7   CF   B5   CD   B3   CA   B1-B3   F6   B4   ED   00   4D   69   73   .............Mis  
  0000:0730   73   69   6E   67   20   6F   70   65-72   61   74   69   6E   67   20   73   sing   operating   s  
  0000:0740   79   73   74   65   6D   00   00   00-00   00   00   00   00   00   00   00   ystem...........  
  0000:0750   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0760   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0770   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0780   00   00   00   8B   FC   1E   57   8B-F5   CB   00   00   00   00   00   00   ......W.........  
  0000:0790   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:07A0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:07B0   00   00   00   00   00   00   00   00-86   D8   00   00   00   00   80   01   ................  
  0000:07C0   01   00   06   3F   3F   FD   3F   00-00   00   41   A0   0F   00   00   00   ...??.?...A.....  
  0000:07D0   01   FE   05   3F   FF   FE   80   A0-0F   00   C0   4F   2F   00   00   00   ...?.......O/...  
  0000:07E0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:07F0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   55   AA   ..............U.  
  ;Top

19 楼pcsir007()回复于 2006-08-13 22:13:27 得分 0

;   反汇编结果  
  ;  
  ;   0000:7C00~0000:7C1A:初始化各个段寄存器、堆栈指针,最后将主引导记录在内存中搬家,腾出其所占内  
  ;   存空间以供装入分区引导记录。  
  0000:7C00   33C0               XOR         AX,AX                   ;AX寄存器清0  
  0000:7C02   8ED0               MOV         SS,AX                   ;SS=0  
  0000:7C04   BC007C           MOV         SP,7C00               ;装填栈指针——SS:SP=0000:7C00  
  0000:7C07   FB                   STI                                     ;开中断(装填栈指针时为避免硬件中断引起栈混乱应关中断)  
  0000:7C08   50                   PUSH       AX                         ;  
  0000:7C09   07                   POP         ES                         ;装填附加数据段寄存器ES=0  
  0000:7C0A   50                   PUSH       AX                         ;  
  0000:7C0B   1F                   POP         DS                         ;装填数据段寄存器DS=0  
  0000:7C0C   FC                   CLD                                     ;规定其后的串操作为正向串操作  
  0000:7C0D   BE1B7C           MOV         SI,7C1B               ;源指针  
  0000:7C10   BF1B06           MOV         DI,061B               ;目的指针  
  0000:7C13   50                   PUSH       AX                         ;  
  0000:7C14   57                   PUSH       DI                         ;看看0000:7C1A——构造一个跳转  
  0000:7C15   B9E501           MOV         CX,01E5               ;  
  0000:7C18   F3                   REPZ                                   ;  
  0000:7C19   A4                   MOVSB                                 ;0000:7C1B起始的CX字节传送至0000:061B起始的区域  
  0000:7C1A   CB                   RETF                                   ;跳转到0000:061B(这是一种技巧跳转)  
  ;    
  ;   为直观起见,下面的地址按实际运行时的地址给出。  
  ;   0000:061B~0000:062B:对分区表进行初步检验,一旦检测到某分区表项状态字节大于等于80h,就通过(当  
  ;   然,在此之前如果检测到某项分区表的状态字节小于80h,就转错误处理。当然,如果四个分区项的状态字节  
  ;   都为零,主引导记录就会调用BIOS-ROM的INT   18h,显示"PRESS   A   KEY   TO   REBOOT"信息等待你的操作。  
  0000:061B   BEBE07           MOV         SI,07BE               ;SI指向第一个分区表项,这时CX=0  
  0000:061E   B104               MOV         CL,04                   ;分区表共四个表项  
  0000:0620   382C               CMP         [SI],CH               ;  
  0000:0622   7C09               JL           062D                     ;大于等于80h转[注意JL指令:(SF   xor   OF)=1则转]  
  0000:0624   7515               JNZ         063B                     ;不为0则[SI]一定小于80h,只能转错误处理了!  
  0000:0626   83C610           ADD         SI,+10                 ;为零则检查下一表项  
  0000:0629   E2F5               LOOP       0620                     ;检查下一表项  
  0000:062B   CD18               INT         18                         ;四表项的状态字节都为0,则系统只好调用INT   18h了!  
  ;    
  ;   0000:062D~0000:0639:检查剩余的分区表项——状态字节必须为零,否则显示错误信息“分区表无效”然  
  ;   后当机!拜托,微软搞错没有,怎么用中文提示信息?真TM傻得可爱!  
  ;   这里还有个小BUG,前面放行原则是只要状态字节大于等于80h,那么如果这个字节是诸如A0h、E5h之类数值  
  ;   呢?嘿嘿,这个引导记录统统认为是有效的可引导分区了!  
  0000:062D   8B14               MOV         DX,[SI]               ;为读分区引导记录做准备:磁头号→DH,驱动器号→DL  
  0000:062F   8BEE               MOV         BP,SI                   ;SI→BP,保存可引导分区表项的指针  
  ;    
  0000:0631   83C610           ADD         SI,+10                 ;其余的分区表项还要检查检查的  
  0000:0634   49                   DEC         CX                         ;  
  0000:0635   7416               JZ           064D                     ;CX=0则检查顺利通过,转继续  
  0000:0637   382C               CMP         [SI],CH               ;  
  0000:0639   74F6               JZ           0631                     ;为零,是合法表项,再查下一表项  
  ;    
  ;   0000:063B~0000:064B:执行错误处理——报告错误信息后当机  
  0000:063B   BE1007           MOV         SI,0710               ;错误信息字符串偏移+1→SI  
  0000:063E   4E                   DEC         SI                         ;SI-1→SI  
  0000:063F   AC                   LODSB                                 ;SI+1→SI  
  0000:0640   3C00               CMP         AL,00                   ;  
  0000:0642   74FA               JZ           063E                     ;AL=0则表明一条错误信息显示完毕,系统陷入一个死循环  
  0000:0644   BB0700           MOV         BX,0007               ;字符方式显示  
  0000:0647   B40E               MOV         AH,0E                   ;  
  0000:0649   CD10               INT         10                         ;以写电传方式显示信息(只显示一个字符)  
  0000:064B   EBF2               JMP         063F                     ;显示下一个字符,直到遇到提示信息结束为止  
  ;    
  ;   0000:064D~0000:0662:判断可引导分区的分区类型,然后转相应处理程序。  
  0000:064D   894625           MOV         [BP+25],AX         ;BP=指向第一个可引导分区表项的指针,这时AX=0000h  
                                                                                    ;使用长度最短的指令将[BP+25]起始的两个单元清零  
                                                                                    ;这两个单元将被用来存放中间变量  
  0000:0650   96                   XCHG       SI,AX                   ;此时SI清零的最佳指令选择(仅1字节),将服务于0000:06B8  
  0000:0651   8A4604           MOV         AL,[BP+04]         ;取分区类型(本例是“06”喽——FAT16主DOS分区)  
  0000:0654   B406               MOV         AH,06                   ;为扩展INT   13h无法使用做好更改分区类型的准备  
  0000:0656   3C0E               CMP         AL,0E                   ;0Eh:需要用扩展INT   13h访问的FAT16主DOS分区  
  0000:0658   7411               JZ           066B                     ;0Eh类型的分区转066Bh  
  0000:065A   B40B               MOV         AH,0B                   ;  
  0000:065C   3C0C               CMP         AL,0C                   ;0Ch:需要用扩展INT   13h访问的FAT32分区  
  0000:065E   7405               JZ           0665                     ;0Ch类型的分区转0665h先行预处理  
  0000:0660   3AC4               CMP         AL,AH                   ;0Bh:用传统INT   13h就可以访问的FAT32分区  
  0000:0662   752B               JNZ         068F                     ;其他类型的分区转068Fh  
  ;    
  ;   0000:0664~0000:06A1:根据分区类型和分区表表项内容进行读取分区引导记录前的处理工作  
  0000:0664   40                   INC         AX                         ;★★★0Bh类型的分区由此开始处理,此条指令用意是清ZF位  
  0000:0665   C6462506       MOV         BYTE   PTR   [BP+25],06   ;★★★0Ch类型的分区由此开始处理  
                                                                                    ;为什么取值06,一时没有自圆我说的解释,请耐心几天吧。  
  0000:0669   7524               JNZ         068F                     ;请注意上面指令对ZF位的影响:0Bh类型分区转,0Ch则不转  
  ;   0000:066B~0000:068C这段代码仅当分区类型是0Ch、0Eh才有获得执行的机会  
  0000:066B   BBAA55           MOV         BX,55AA               ;★★★0Eh类型的分区由此开始处理  
  0000:066E   50                   PUSH       AX                         ;  
  0000:066F   B441               MOV         AH,41                   ;扩展INT   13h功能,检测BIOS是否已经支持扩展INT13h  
  0000:0671   CD13               INT         13                         ;入口参数:BX=55AAh,DL=驱动器号,AH=41h  
  0000:0673   58                   POP         AX                         ;执行完恢复AX为060Eh  
  0000:0674   7216               JB           068C                     ;不支持则转  
  0000:0676   81FB55AA       CMP         BX,AA55               ;  
  0000:067A   7510               JNZ         068C                     ;扩展INT13h不可用也转  
  0000:067C   F6C101           TEST       CL,01                   ;测试扩展盘访问是否被支持  
  0000:067F   740B               JZ           068C                     ;不支持还转  
  ;   因为扩展INT13h方式读盘与标准INT13h方式读盘有很大差别,所以0000:0686处指令修改其后的代码以保证按  
  ;   照扩展读方式读分区引导扇区时能正确跳转到相应的处理程序中。  
  0000:0681   8AE0               MOV         AH,AL                   ;分区类型→AH  
  0000:0683   885624           MOV         [BP+24],DL         ;保存驱动器号→[BP+24]  
  0000:0686   C706A106EB1E   MOV         WORD   PTR   [06A1],1EEB   ;修改0000:06A1处代码为"JMP   06C1"  
  0000:068C   886604           MOV         [BP+04],AH         ;注意:如果扩展INT13h不能使用则A改分区类型为06,但如果  
                                                                                    ;扩展INT13h能使用,则仍保持原分区类型不变  
  0000:068F   BF0A00           MOV         DI,000A               ;★★★其它类型分区由此开始处理。此条指令初始化计数器  
  0000:0692   B80102           MOV         AX,0201               ;AH:读操作,AL:读取1个扇区的内容  
  0000:0695   8BDC               MOV         BX,SP                   ;SP=7C00→BX,指定分区引导记录装入内存的位置偏移  
  0000:0697   33C9               XOR         CX,CX                   ;CX清零  
  0000:0699   83FF05           CMP         DI,+05                 ;注意5    
  0000:069C   7F03               JG           06A1                     ;大于则转去读由分区表指定的分区引导扇区  
  0000:069E   8B4E25           MOV         CX,[BP+25]         ;小于则证明所读分区表指定的引导扇区无合法的引导记录,  
                                                                                    ;改按???再读,毕竟多一种选择多一次机会嘛!;)Top

20 楼pcsir007()回复于 2006-08-13 22:13:50 得分 0

;   以下标有①②者请注意它们的地址都是一样的,就是说实际运行中只可能是二者之一,但为了分析之方便,我  
  ;   把两者都列了出来以供对比,阅读时千万别看成是两条指令了啊!  
  ①0000:06A1   034E02           ADD         CX,[BP+02]         ;获取分区引导扇区所在的柱面号和物理扇区号  
  ②0000:06A1   EB1E               JMP         06C1                     ;如果分区类型是0Ch、0Eh而且扩展读能使用则执行该指令  
  ;    
  ;   0000:06A4:将可引导分区的分区引导记录装入内存指定区域  
  ;   入口参数:AH=功能号,02为读盘操作;AL=一次读取的扇区数  
  ;                     ES:BX=读入内存的起始地址  
  ;                     CH=10位柱面号的低8位;CL:高两位是10位柱面号的高两位,低6位是物理扇区号  
  ;                     DH=磁头号;DL=驱动器号,最高位(即位7)为0是软盘,为1是硬盘  
  0000:06A4   CD13               INT         13                         ;读分区引导记录到0000:7C00起始的区域  
  ;    
  ;    
  0000:06A6   7229               JB           06D1                     ;不成功转  
  0000:06A8   BE2D07           MOV         SI,072D               ;错误信息字符串偏移→SI  
  0000:06AB   813EFE7D55AA   CMP         WORD   PTR   [7DFE],AA55   ;分区引导记录合法吗?  
  0000:06B1   745A               JZ           070D                     ;合法则转(这是主引导记录唯一的正常出口)    
  0000:06B3   83EF05           SUB         DI,+05                 ;不合法则为换读其他扇区做准备  
  0000:06B6   7FDA               JG           0692                     ;只有一次换读扇区的机会!  
  ;    
  ;   0000:06B8~0000:06BF:错误预处理  
  0000:06B8   85F6               TEST       SI,SI                   ;测试SI值是否为0,其意义在于确定该显示哪条信息  
  0000:06BA   7583               JNZ         063F                     ;不为0则转错误处理,显示“Missing   operating   system”  
  0000:06BC   BE1A07           MOV         SI,071A               ;错误信息字符串偏移→SI  
  0000:06BF   EB8A               JMP         064B                     ;转错误处理,显示“加载操作系统时出错”  
  ;    
  ;   0000:06C1~0000:06CF:整理扩展读所需入口参数,然后调用扩展读子程序  
  ;   这段代码只有在以扩展读方式读取分区引导记录时才有机会获得执行  
  0000:06C1   98                   CBW                                     ;转换字节AL为字AX,执行后,AX中是一次要读的扇区数  
  0000:06C2   91                   XCHG       CX,AX                   ;AX→CX,CX→AX,执行后,CX中是一次要读的扇区数  
  0000:06C3   52                   PUSH       DX                         ;  
  0000:06C4   99                   CWD                                     ;将字AX转换为双字→DX,AX  
  0000:06C5   034608           ADD         AX,[BP+08]         ;  
  0000:06C8   13560A           ADC         DX,[BP+0A]         ;执行后,DX:AX=LBA绝对物理扇区号  
  0000:06CB   E81200           CALL       06E0                     ;调用扩展读子程序  
  0000:06CE   5A                   POP         DX                         ;  
  0000:06CF   EBD5               JMP         06A6                     ;  
  ;    
  ;   0000:06D1~0000:06D8分区引导记录装入失败时的处理  
  0000:06D1   4F                   DEC         DI                         ;计数器减1  
  0000:06D2   74E4               JZ           06B8                     ;五次读盘均未成功则转错误处理(注意这时SI=0)  
  0000:06D4   33C0               XOR         AX,AX                   ;置功能号  
  0000:06D6   CD13               INT         13                         ;复位磁盘系统  
  0000:06D8   EBB8               JMP         0692                     ;再读  
  ;    
  ;    
  0000:06DA   00   00   80   49   12   00   ...I..  
  ;    
  ;   0000:06E0~0000:070C:使用扩展INT   13h功能读取分区引导记录的子程序  
  ;   调用时,SP=7BFE。这段程序利用压栈寄存器方式构造了一个磁盘地址包,请注意体会。另外,0000:06FC处  
  ;   的一条指令就释放了几乎全部由本段程序占用的栈空间,构思之巧妙,绝对需要我们学习!  
  ;   所以,分析该段程序,一个重点应放在栈的变化上。  
  0000:06E0   56                   PUSH       SI                         ;保存SI——注意,这次压栈并不构造磁盘地址包  
  0000:06E1   33F6               XOR         SI,SI                   ;清零  
  0000:06E3   56                   PUSH       SI                         ;  
  0000:06E4   56                   PUSH       SI                         ;  
  0000:06E5   52                   PUSH       DX                         ;  
  0000:06E6   50                   PUSH       AX                         ;以上四条指令压栈的是扇区LBA号码*2  
  0000:06E7   06                   PUSH       ES                         ;压栈内存目标缓冲区首址段址  
  0000:06E8   53                   PUSH       BX                         ;压栈内存目标缓冲区首址偏移  
  0000:06E9   51                   PUSH       CX                         ;压栈所读扇区数  
  0000:06EA   BE1000           MOV         SI,0010               ;注意SI的高8位对应着磁盘地址包的保留字节,必须为0  
  0000:06ED   56                   PUSH       SI                         ;压栈磁盘地址包包长,执行完本条指令一个包已经构造完毕  
  0000:06EE   8BF4               MOV         SI,SP                   ;规定磁盘地址包偏移指针,这时SP=7BEA  
  0000:06F0   50                   PUSH       AX                         ;保存AX  
  0000:06F1   52                   PUSH       DX                         ;保存DX  
  0000:06F2   B80042           MOV         AX,4200               ;置扩展读功能号  
  0000:06F5   8A5624           MOV         DL,[BP+24]         ;取驱动器号,参照0000:0683  
  ;   入口参数:AH=功能号,02为读盘操作;DL=驱动器号  
  ;                     DS:SI=16字节磁盘地址包——第0字节:包长度(固定为10h);第1字节:保留,必须为0;  
  ;                     第2、3字节:所读扇区数;第4~5字节:内存目标缓冲区首址偏移;  
  ;                     第6~7字节:内存目标缓冲区首址段址;   第8~15字节:扇区LBA号码  
  ;   出口参数:成功则AH=0;错误则AH=错误代码  
  0000:06F8   CD13               INT         13                         ;执行扩展读操作  
  0000:06FA   5A                   POP         DX                         ;  
  0000:06FB   58                   POP         AX                         ;  
  0000:06FC   8D6410           LEA         SP,[SI+10]         ;7BEA+10h=7BFA→SP(注意是取偏移而不是取单元内容)  
  0000:06FF   720A               JB           070B                     ;扩展读不成功转  
  0000:0701   40                   INC         AX                         ;  
  0000:0702   7501               JNZ         0705                     ;  
  0000:0704   42                   INC         DX                         ;AX加1溢出时(比如0FFFFh+1)DX才加1  
  0000:0705   80C702           ADD         BH,02                   ;调整BX,使偏移量增加512字节(刚好一扇区)  
  0000:0708   E2F7               LOOP       0701                     ;0701~0708一段代码暂未明白其真实意图!  
  0000:070A   F8                   CLC                                     ;  
  0000:070B   5E                   POP         SI                         ;  
  0000:070C   C3                   RET                                     ;  
  ;    
  ;   0000:070D:中继跳转  
  0000:070D   EB74               JMP         0783                     ;  
  ;    
  ;   070F~0745是错误信息!果然是中文Windows98生成的主引导记录,所以我要特别  
  ;   “感谢”微软这个傻B,真难为它竟然用中文表述前两个信息!可惜真需显示的时  
  ;   候鬼才能看懂是什么呢!!!我K!——耍弄我们耶!?  
  ;   070F~0718:“分区表无效”中文信息  
  ;   071A~072B:“加载操作系统时出错”中文信息  
  ;   072D~0744:“Missing   operating   system”英文信息  
  0000:070F   B7   .    
  0000:0710   D6   C7   F8   B1   ED   CE   DE   D0-A7   00   BC   D3   D4   D8   B2   D9   ................  
  0000:0720   D7   F7   CF   B5   CD   B3   CA   B1-B3   F6   B4   ED   00   4D   69   73   .............Mis  
  0000:0730   73   69   6E   67   20   6F   70   65-72   61   74   69   6E   67   20   73   sing   operating   s  
  0000:0740   79   73   74   65   6D   00   00   00-00   00   00   00   00   00   00   00   system..........  
  0000:0750   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0760   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0770   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:0780   00   00   00   ...  
  ;    
  ;   0000:0783~0000:0789:控制权移交  
  0000:0783   8BFC               MOV         DI,SP                   ;  
  0000:0785   1E                   PUSH       DS                         ;  
  0000:0786   57                   PUSH       DI                         ;构造一个跳转地址  
  0000:0787   8BF5               MOV         SI,BP                   ;  
  0000:0789   CB                   RETF                                   ;交控制权给分区引导记录(0000:7C00)  
  ;    
  ;    
  0000:078A   00   00   00   00   00   00   ......  
  0000:0790   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:07A0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  ;    
  ;   07B8~07BB四个字节的内容用于什么呢?(不同机器此四字节均不同)  
  ;   07BE~07FD为分区表,内含四个分区表项(每表项10h字节)  
  0000:07B0   00   00   00   00   00   00   00   00-86   D8   00   00   00   00   80   01   ................  
  0000:07C0   01   00   06   3F   3F   FD   3F   00-00   00   41   A0   0F   00   00   00   ...??.?...A.....  
  0000:07D0   01   FE   05   3F   FF   FE   80   A0-0F   00   C0   4F   2F   00   00   00   ...?.......O/...  
  0000:07E0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   00   00   ................  
  0000:07F0   00   00   00   00   00   00   00   00-00   00   00   00   00   00   55   AA   ..............U.    
  *1:因为物理扇区号总是从1排列而起  
  *2:由此可见,就是使用LBA扩展读的功能,主引导记录却限制了分区引导扇区必须在LBA绝对物理扇区  
          0FFFFFFFFh之前才有可能从该分区引导系统!     
 
本文转自
http://topic.csdn.net/t/20060811/13/4942884.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐