注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

DOS编程技术

讨论在纯DOS下的编程技术

 
 
 

日志

 
 
关于我

1984年大学毕业,1985年底有机会开始接触PC机,1986年开始在PC机上做开发工作,曾接触过MS-DOS、CP/M、UNIX、VMS、LINUX、iRMX等众多的操作系统并在上面从事技术开发,擅长做底层与硬件相关的软件开发,目前主要在DOS和LINUX平台下工作,主要从事软件,在硬件开发上也有一定造诣,亦有在8051系列、6502系列(凌阳)、z80系列、ARM、X86等各类平台下开发软硬件的经历。更详细情况可以参考http://resume.whowin.net

网易考拉推荐

dos分区引导扇区分析  

2011-05-15 13:16:56|  分类: 杂七杂八 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
    以前的文章里专门分析过DOS的主引导扇区,主引导扇区并不隶属于某个操作系统,尽管在不同的操作系统下对硬盘进行分区所得到的主引导分区时不同的,但在x86的架构下,其最终结果都是读出某一个活动的分区引导扇区,最后把控制权交给这个分区引导扇区,至于最后引导起来的是什么操作系统,则要看这个分区引导扇区了,所以说,分区引导扇区可是和操作系统密不可分的,不同的操作系统,其分区引导扇区肯定是不同的。
    简单地说,主引导扇区是在对磁盘进行分区时写在磁盘的0柱面(Cylinder)、0磁头(Head)、1扇区(Sector)上的,而分区引导扇区是在你对磁盘进行格式化时,写在磁盘上你所格式化的那个分区的逻辑扇区号为0的扇区上的,听起来有点绕口。
    本文所载的分区引导扇区的代码取自DOS6.22格式化的一个实际硬盘,本文所有的分析过程在DOS 6.22下进行。
1、分区引导扇区的结构
    分区引导程序占用一个扇区,通常是512个字节,可以分成如下6个部分
  • 偏移:00h,长度:3字节,一条跳转指令,跳转到直接可以执行的代码上去
  • 偏移:03h,长度:8字节,厂商标识和DOS版本号
  • 偏移:0bh,长度:25字节,BPB(BIOS Parameter Block),BIOS参数块
  • 偏移:24h,长度:26字节,其他参数区
  • 偏移:3eh,长度:448字节,引导程序
  • 偏移:1feh,长度:2字节,结束标志,aa55h
2、分区引导扇区的读出
    分区引导扇区属于该磁盘分区的一部分,所以在debug下使用debug的命令就可以很容易的读出:
dos分区引导扇区分析 - whowin - DOS编程技术
     命令很简单:L7c00 2 0 1
  • L ------ debug命令,含义为将文件或磁盘扇区调入内存
  • 7c00 --- 扇区读入后存放的地址,我们之所以放在7c00h的位置,是因为实际引导时,该扇区将被读到0:7c00h的位置
  • 2 ------ 磁盘盘符,0代表A盘,1代表B盘,2代表C盘,......
  • 0 ------ 读入的起始逻辑扇区号,我们说过分区引导扇区在该分区的逻辑0扇区
  • 1 ------ 读入的扇区数,在这里我们只读入一个扇区
    很显然,我们通过这个命令将把分区引导扇区读到7c00h--7dffh这块内存中,共计512个字节。
3、分区引导扇区程序的流程图
    分区引导的最终目的,就是把操作系统的第一个引导文件读到内存中并将控制权交给该文件,之后,引导操作系统的重任就交给了这个文件,而分区引导扇区的任务也就完成了。在MSDOS中,这个引导文件就是IO.SYS,MSDOS要求,根目录的第一个文件必须是IO.SYS,第二个文件必须是MSDOS.SYS,而且IO.SYS必须存放在连续的扇区中,这些从流程图中都可以体现出来。
dos分区引导扇区分析 - whowin - DOS编程技术
 


4、分区引导程序的程序分析
    下面是一份有着详细注释的DOS 6.22的分区引导程序的清单,使用DEBUG的命令读出,去掉了其中的段地址部分,其他的未作任何改动,我们将对该清单做详细的说明。
    清单中的第一列是行号,第二列为偏移地址,第三列是机器码,第四列是反汇编出来的指令,第五列(以及所有以;开头的行)为我加的注释。

001 7C00 EB3C       JMP 7C3E
002 ;*****************************************************************
003 ; step1:移动软盘初始化参数表(Disk Initialization Parameter Table)
004 ;       修改int 1eh的中断向量(软盘初始化参数表向量)
005 ;       磁盘复位
006 ;*****************************************************************
007 7C3E FA         CLI                       ; 关中断
008 7C3F 33C0       XOR AX,AX                 ; ax=0
009 7C41 8ED0       MOV SS,AX                 ; ss=0
010 7C43 BC007C     MOV SP,7C00               ; sp=7c00
011 7C46 16         PUSH SS                   ;
012 7C47 07         POP ES                    ; es=0
013 7C48 BB7800     MOV BX,0078               ; int 1eh指向软盘基数表参数,
014                                           ; 一般位于0:0522或0050:0022
015 7C4B 36         SS:                                   
016 7C4C C537       LDS SI,[BX]               ; DS:SI指向软盘技术表参数
017 7C4E 1E         PUSH DS                                
018 7C4F 56         PUSH SI                                
019 7C50 16         PUSH SS                                
020 7C51 53         PUSH BX                                
021 7C52 BF3E7C     MOV DI,7C3E               ; 将前面程序的11个字节覆盖
022 7C55 B90B00     MOV CX,000B                           
023 7C58 FC         CLD                                   
024 7C59 F3         REPZ                                   
025 7C5A A4         MOVSB                     ; 移动11个字节
026 7C5B 06         PUSH ES                   ;
027 7C5C 1F         POP DS                    ; ds=es=0
028 7C5D C645FE0F   MOV BYTE PTR [DI-02],0F   ;
029 7C61 8B0E187C   MOV CX,[7C18]             ; 每磁道扇区数
030 7C65 884DF9     MOV [DI-07],CL            ; 软盘初始化参数表的每磁道的扇区数
031 7C68 894702     MOV [BX+02],AX            ; 新的软盘初始化参数表地址放到
032 7C6B C7073E7C   MOV WORD PTR [BX],7C3E    ; int 1eh向量中
033 7C6F FB         STI                       ; 开中断
034 7C70 CD13       INT 13                    ; 磁盘复位
035 7C72 7279       JB 7CED                   ; 磁盘复位出错,显示Non-system disk......
036 ;************************************************************************
037 ; step2:读出根目录的第一个扇区
038 ;************************************************************************
039 7C74 33C0       XOR AX,AX                 ; ax=0
040 7C76 3906137C   CMP [7C13],AX             ; 小扇区数是否为0
041 7C7A 7408       JZ 7C84                   ; 小扇区数为0,要使用大扇区数作为扇区数
042 7C7C 8B0E137C   MOV CX,[7C13]             ; 小扇区数不为0,[7c13h]为扇区数
043 7C80 890E207C   MOV [7C20],CX             ; 将小扇区数放到大扇区数里。[7c20h]为大扇区数
044 7C84 A0107C     MOV AL,[7C10]             ; FAT的数量
045 7C87 F726167C   MUL WORD PTR [7C16]       ; [7c16h]FAT的扇区数 * FAT数量=FAT占用的总扇区数
046 7C8B 03061C7C   ADD AX,[7C1C]             ; [7c1ch](dword)隐藏扇区数
047 7C8F 13161E7C   ADC DX,[7C1E]                         
048 7C93 03060E7C   ADD AX,[7C0E]             ; 保留扇区数
049 7C97 83D200     ADC DX,+00                ; 处理进位
050 7C9A A3507C     MOV [7C50],AX             ; DX:AX目录区前的总扇区数,即根目录的起始扇区号
051 7C9D 8916527C   MOV [7C52],DX                         
052 7CA1 A3497C     MOV [7C49],AX                         
053 7CA4 89164B7C   MOV [7C4B],DX                         
054 7CA8 B82000     MOV AX,0020               ; 每个目录项占32个字节
055 7CAB F726117C   MUL WORD PTR [7C11]       ; [7c11h]根目录的项数,所有根目录项占用的字节数
056 7CAF 8B1E0B7C   MOV BX,[7C0B]             ; [7c0bh]每扇区的字节数
057 7CB3 03C3       ADD AX,BX                 ; 如果根目录占用的字节数不是扇区字节数的整数倍
058 7CB5 48         DEC AX                    ; 则需要调整根目录前的扇区总数
059 7CB6 F7F3       DIV BX                    ; 并存放在[7c49h]的dword中
060 7CB8 0106497C   ADD [7C49],AX             ; 至此[7c49](word)和[7c4b](word)
061 7CBC 83164B7C00 ADC WORD PTR [7C4B],+00   ; 存放着数据区的起始扇区号
062 7CC1 BB0005     MOV BX,0500               ; 读取的根目录的存储缓冲区
063 7CC4 8B16527C   MOV DX,[7C52]             ; 根目录的起始逻辑扇区号
064 7CC8 A1507C     MOV AX,[7C50]                         
065 7CCB E89200     CALL 7D60                 ; 检查数据的有效性,并将逻辑扇区号转换为CHS格式
066 7CCE 721D       JB 7CED                   ; 数据无效,显示Non-system disk......
067 7CD0 B001       MOV AL,01                 ; 读取1个扇区
068 7CD2 E8AC00     CALL 7D81                 ; 按要求读取扇区
069 7CD5 7216       JB 7CED                   ; 读取失败,显示Non-system disk......
070 ;*******************************************************************************
071 ; step3:检查根目录中的前两个文件是否为IO.SYS和MSDOS.SYS
072 ;*******************************************************************************
073 7CD7 8BFB       MOV DI,BX                 ; BX为缓冲区地址,存放读出的根目录
074 7CD9 B90B00     MOV CX,000B               ; 比较11个字节,文件名8字节扩展名3字节            
075 7CDC BEE67D     MOV SI,7DE6               ; 指向IO      SYS
076 7CDF F3         REPZ                                  
077 7CE0 A6         CMPSB
078 7CE1 750A       JNZ 7CED                  ; 比较失败,显示Non-system disk......
079                                           ; 目录项的第一项为IO      SYS
080 7CE3 8D7F20     LEA DI,[BX+20]            ; 比较下一个目录项MSDOS   SYS
081 7CE6 B90B00     MOV CX,000B                           
082 7CE9 F3         REPZ                                   
083 7CEA A6         CMPSB                                   
084 7CEB 7418       JZ 7D05                   ; 比较成功
085 ;*******************************************************************************
086 7CED BE9E7D     MOV SI,7D9E               ; 指向字符串:Non-system disk......
087 7CF0 E85F00     CALL 7D52                 ; 显示字符串
088 7CF3 33C0       XOR AX,AX                 ; AX = 0
089 7CF5 CD16       INT 16                    ; 等待键盘
090 7CF7 5E         POP SI                                
091 7CF8 1F         POP DS                                
092 7CF9 8F04       POP [SI]                              
093 7CFB 8F4402     POP [SI+02]                           
094 7CFE CD19       INT 19                    ; 复位
095 ;******************************************************************************
096 7D00 58         POP AX                    ;
097 7D01 58         POP AX                                
098 7D02 58         POP AX                                
099 7D03 EBE8       JMP 7CED                  ; 显示字符串:Non-system disk......
100 ;******************************************************************************
101 ; step4:读出文件IO.SYS,并将控制权交给该文件
102 ;******************************************************************************
103 7D05 8B471A     MOV AX,[BX+1A]            ; IO.SYS文件的首簇号
104 7D08 48         DEC AX                    ; FAT表中前两个簇号的位置用于记录FAT标志
105 7D09 48         DEC AX                    ; FAT中簇号2的位置实际表示第0簇的信息,
106                                           ; 根目录中文件首簇记录的是在FAT表中的位置
107                                           ; -2得到实际的簇号
108 7D0A 8A1E0D7C   MOV BL,[7C0D]             ; [7c0dh]每簇扇区数
109 7D0E 32FF       XOR BH,BH                 ; BH=0
110 7D10 F7E3       MUL BX                    ; 簇号*每簇扇区数=文件首簇的相对扇区号
111                                           ; (相对于数据区的起始扇区号)
112 7D12 0306497C   ADD AX,[7C49]             ; 加上数据区的起始扇区号,则DX:AX中应该存放的是
113 7D16 13164B7C   ADC DX,[7C4B]             ; 该文件的起始逻辑扇区号
114 7D1A BB0007     MOV BX,0700               ; 读取文件的缓冲区,0:0700h
115 7D1D B90300     MOV CX,0003               ; 总共读取3个扇区
116 7D20 50         PUSH AX                   ;
117 7D21 52         PUSH DX                   ;
118 7D22 51         PUSH CX                   ;
119 7D23 E83A00     CALL 7D60                 ; 检查逻辑扇区号的有效性,并转换成CHS格式
120 7D26 72D8       JB 7D00                   ; 数据无效,恢复堆栈后显示错误信息
121 7D28 B001       MOV AL,01                 ; 逻辑扇区号有效,读取一个扇区
122 7D2A E85400     CALL 7D81                 ; 读取扇区
123 7D2D 59         POP CX                    ;
124 7D2E 5A         POP DX                    ;
125 7D2F 58         POP AX                    ;
126 7D30 72BB       JB 7CED                   ; 读取失败,显示字符串:Non-system disk......
127 7D32 050100     ADD AX,0001               ; 读取的扇区号+1
128 7D35 83D200     ADC DX,+00                ; 处理进位
129 7D38 031E0B7C   ADD BX,[7C0B]             ; 指向下一块缓冲区
130 7D3C E2E2       LOOP 7D20                 ; 读下一个扇区
131 7D3E 8A2E157C   MOV CH,[7C15]             ; 介质描述符,F8H表示当前介质为硬盘
132 7D42 8A16247C   MOV DL,[7C24]             ; 介质标志,80h为第一硬盘
133 7D46 8B1E497C   MOV BX,[7C49]             ; [7c49h]:[7c4bh]为数据区的起始扇区号
134 7D4A A14B7C     MOV AX,[7C4B]             ;
135 7D4D EA00007000 JMP 0070:0000             ; 将控制权交给刚读出的文件IO.SYS
136 ;****************************************************************************
137 ; 子程序:显示字符串
138 ;   入口:DS:SI指向要显示的字符串,00h结束
139 ;   返回:字符串显示在屏幕上
140 ;****************************************************************************
141 7D52 AC         LODSB                     ; 调入一个字符
142 7D53 0AC0       OR AL,AL                  ; 是否为0
143 7D55 7429       JZ 7D80                   ; 为0,移到字符串尾,返回
144 7D57 B40E       MOV AH,0E                 ; 调用int 10h的0eh功能
145 7D59 BB0700     MOV BX,0007               ; 显示该字符
146 7D5C CD10       INT 10                                
147 7D5E EBF2       JMP 7D52                  ; 显示下一个字符
148 ;****************************************************************************
149 ; 子程序:检查逻辑扇区号的有效性并根据int 13h的要求转换逻辑扇区号
150 ;   入口:dx:ax为逻辑扇区号
151 ;   返回:如果逻辑扇区号不合法则CF=1
152 ;         逻辑扇区号合法则CF=0
153 ;         word ptr [7c4dh]为柱面号(Cylinder)
154 ;         byte ptr [7c25h]为磁头号(Head)
155 ;         byte ptr [7c4fh]为扇区号(Sector)
156 ;****************************************************************************
157 7D60 3B16187C   CMP DX,[7C18]             ; [7c18h]每磁道的扇区数
158 7D64 7319       JNB 7D7F                  ; 数据无效
159 7D66 F736187C   DIV WORD PTR [7C18]       ; DX:AX为起始扇区号/每磁道的扇区数,
160                                           ; 商为逻辑磁道号
161 7D6A FEC2       INC DL                    ; 余数为在磁道上的扇区号,扇区号从1数起
162 7D6C 88164F7C   MOV [7C4F],DL             ; 扇区号
163 7D70 33D2       XOR DX,DX                             
164 7D72 F7361A7C   DIV WORD PTR [7C1A]       ; 磁道号/[7c1ah]磁头数,商为柱面号,
165                                           ; 余数为该磁头下的磁头号
166 7D76 8816257C   MOV [7C25],DL             ; 磁头号(从0数起)
167 7D7A A34D7C     MOV [7C4D],AX             ; 柱面号(从0数起)
168 7D7D F8         CLC                       ; CF=0,数据有效
169 7D7E C3         RET                                   
170 7D7F F9         STC                       ; CF=1,数据无效
171 7D80 C3         RET                                   
172 ;***************************************************************************
173 ; 子程序:读取指定扇区
174 ;   入口:al-----读取的扇区数
175 ;         es:bx--存储缓冲区
176 ;         [7c24h](byte)--介质,80h:第1硬盘,81h:第2硬盘......
177 ;         [7c25h](byte)--磁头号
178 ;         [7c4dh](word)--柱面号
179 ;         [7c4fh](byte)--扇区号
180 ;***************************************************************************
181 7D81 B402       MOV AH,02                 ; 读取扇区功能
182 7D83 8B164D7C   MOV DX,[7C4D]             ; 柱面号
183 7D87 B106       MOV CL,06                             
184 7D89 D2E6       SHL DH,CL                 ; 柱面号的高2位放在bit6:7
185 7D8B 0A364F7C   OR DH,[7C4F]              ; 磁道上的扇区号
186 7D8F 8BCA       MOV CX,DX                 ; dh的bit6:7为柱面号的高2位,
187                                           ; 低5位为起始扇区号,dl的柱面号的低8位
188 7D91 86E9       XCHG CH,CL                ; 按照int 13h调用的要求
189 7D93 8A16247C   MOV DL,[7C24]             ; 介质标志
190 7D97 8A36257C   MOV DH,[7C25]             ; 磁头号
191 7D9B CD13       INT 13                    ; 读扇区
192 7D9D C3         RET                       ;
193 ;***********************************************************************************
194 7C00  EB 3C 90 4D 53 44 4F 53-35 2E 30 00 02 04 01 00   .<.MSDOS5.0..@..
195 7C10  02 00 02 E0 F4 F8 3E 00-20 00 08 00 20 00 00 00   ......>. ... ...
196 7C20  00 00 00 00 80 00 29 07-10 16 18 4E 4F 20 4E 41   ..?...)....NO NA
197 7C30  4D 45 20 20 20 20 46 41-54 31 36 20 20 20         ME    FAT16  
198 7D90                                            0D 0A                 ..
199 7DA0  4E 6F 6E 2D 53 79 73 74-65 6D 20 64 69 73 6B 20   Non-System disk
200 7DB0  6F 72 20 64 69 73 6B 20-65 72 72 6F 72 0D 0A 52   or disk error..R
201 7DC0  65 70 6C 61 63 65 20 61-6E 64 20 70 72 65 73 73   eplace and press
202 7DD0  20 61 6E 79 20 6B 65 79-20 77 68 65 6E 20 72 65    any key when re
203 7DE0  61 64 79 0D 0A 00 49 4F-20 20 20 20 20 20 53 59   ady...IO      SY
204 7DF0  53 4D 53 44 4F 53 20 20-20 53 59 53 00 00 55 AA   SMSDOS   SYS..U.

  • 分区引导扇区在引导的过程中会被读到0:7c00h开始的内存中,这一点在我的另一篇博文《DOS主引导扇区分析》中有介绍
  • 001行:是一个跳转语句,跳转到7c3eh的地方开始执行,这表明7c3eh前的这部分内容应该是数据区,这部分的数据在194-197行中
  • 024-025行,程序将软盘初始化参数表从int 1eh向量指示的内存地址中搬移到了0:7c3eh开始的内存中,并在031-032行修改了int 1eh中断向量的指针使其指向0:7c3eh,软盘初始化参数表现在已经不常用了,对这个搬移,其作用何在笔者并不是很清楚,因为在引导过程中并没有用到这些数据,而且,在DOS启动起来后,int 1eh向量仍然是指向0:0522h的,而不是这里改过的0:7c3eh。
  • 034行的int 13h执行了BIOS的磁盘复位功能,笔者认为该执行更大的意义在于检测int 13h是否可以正常执行
  • 在继续分析代码之前,有必要介绍一下BPB(BIOS Parameter Block),BIOS参数块;在介绍分区引导扇区的结构时,曾经提到,7c0bh-7c23h这25个字节存放的BPB,下面介绍一下BPB表的结构:
    7c0bh:word---每扇区字节数,0200h表示每扇区512字节
    7c0dh:byte---每簇扇区数,04h表示每簇有4个扇区
    7c0eh:word---保留扇区数,0001h表示有1个保留扇区
    7c10h:byte---FAT的个数,02h表示有2个FAT
    7c11h:word---根目录项的个数,0200h表示根目录区最多可以有512个目录项,
                 一个目录项占32个字节
    7c13h:word---小扇区数,如果不为0则表示分区中总扇区数,0000h表示扇区数
                 大于65535,所以不使用小扇区数,而使用后面的大扇区数
                 当前值为:0F4E0H
    7c15h:byte---介质描述符,f8h表示当前介质为硬盘
    7c16h:word---每个FAT的扇区数,003eh表示每个FAT有62个扇区
    7c18h:word---每磁道的扇区数,0020h表示每磁道有32个扇区
    7c1ah:word---磁头数,0008h表示有8个磁头
    7c1ch:dword--隐藏扇区数,00000020h表示在分区引导扇区前有32个隐藏扇区
    7c20h:dword--大扇区数,分区中总扇区数,当前值为0
    这些数据在后面的代码分析中会经常用到,必要时要过来查一下。
  • 039-049行是为了算出根目录区的起始扇区号,分区的逻辑扇区0为分区引导扇区,后面有隐藏扇区,保留扇区,还有FAT表,之后就是根目录区,所以要得到根目录的起始扇区号,必须要要知道每个FAT占用的扇区数,一共有几个FAT,隐藏扇区数和保留扇区数,有了这些数据,则:
    根目录起始逻辑扇区号=FAT扇区数*FAT数量+隐藏扇区数+保留扇区数
    所幸的是,所有这些数据在BPB中都有,所以,算出根目录的起始逻辑扇区号就不是什么难事了,程序中将算出的根目录的起始逻辑扇区号放在了[7c50h]起始的四个字节中(050-051行);052-053行同时也将根目录的起始逻辑扇区号存储在了[7c49h]开始的四个字节中,这是为了后面计算数据区起始扇区号做准备,暂时可以不管它。
  • 052-061行计算数据区的起始扇区号,理论上说,根目录后面就是数据区的开始,但是BPB表中并没有根目录的长度这个数据,但是有根目录项的最大项数,就是根目录最多可以存储多少个目录项的意思,每个目录项占32个字节,所以根目录的长度可以如下计算:
    根目录长度(字节数)=根目录最大项数*每个目录项的字节数
    如果要知道根目录所占的扇区数,则应该再除以每个扇区的字节数,这个数据在BPB中也有
    根目录长度(扇区数)=根目录所占的总字节数/每个扇区的字节数
    但是这个结果可能还会有偏差,因为根目录所占的总字节数不一定恰好是每扇区字节数的整数倍,如果尚有余数,必须再加一个扇区才行,实际程序中是这样计算的:
    根目录长度(扇区数)=(根目录所占的总字节数+每扇区字节数-1)/每个扇区的字节数
    这样计算的结果是一致的,读者可以自行验证。
    计算结果存放在以[7c49h]开始的4个字节中
  • int 13h在读取扇区时(ah=02h)时,入口参数如下:
    ah=02h, al=需要读取的扇区数, es:bx=存放缓冲区, dh=磁头号, dl=磁盘标识(80h=第一个硬盘)
    ch=磁道号的低8位, cl=bit[0:5]为该磁道上的起始扇区号,bit[6:7]为磁道号的高2位
    入口地址为7d60h的子程序其主要任务就是把逻辑扇区号转换成上面的这种格式,方法如下:
    逻辑扇区号/每磁道的扇区数,商为逻辑磁道号,余数为在该磁道上的扇区号,但由于扇区号是从1开始计算的,所以这个扇区号要+1才能符合这个要求,159-161行完成了这个计算,162行把计算出的扇区号放在[7c4fh]中
    逻辑磁道号/磁头数,商为柱面号,余数为磁头号,164行完成了这个计算,166行把磁头号放在了[7c25h],167行把柱面号放在了[7c4dh]中
    7d60h这个子程序中还有简单检验逻辑扇区号是否合法的功能,157-158行检查逻辑扇区号的高16位(DX)是否大于每磁道的扇区数,为什么要这么检查呢?在int 13h的调用中,扇区号放在cl的bit[0:5]中,仅占6个bit,也就是说扇区号最大为63,大致为2的6次方,而磁道号为10位,也就是不能超过2的10次方,逻辑扇区号的低16位为2的16次方,除以2的6次方最小也是2的10次方,所以逻辑磁道号的高16位如果大于每磁道的扇区数,则除以每磁道的扇区数必然大于1,则磁道号会大于2的10次方,DOS已经无法处理这样的磁盘。
  • 回过头来说,062行,让bx=0500h,是准备在下面读取根目录第一扇区时,将该扇区内容放在0:0500h的内存中
  • 065行调用上面提到的子程序检查根目录起始逻辑扇区号的有效性并转换成CHS格式,如果数据无效将显示错误信息(066行)
  • 068行调用子程序读取根目录的起始扇区,067行指出只读一个扇区,因为按照DOS的要求,DOS引导文件应该位于目录项的第一项,如果读取扇区失败将显示错误信息(069行)
  • 073-084行检查根目录区的前两项是否为IO.SYS和MSDOS.SYS,这部分程序比较简单,如果发现不对会显示错误信息(078行),如果检查正确将转到103行继续执行(084行)
  • 103-113行计算文件IO.SYS的起始扇区号,首先从根目录项中得到文件的起始簇号(103行),这里有必要简单解释一下FAT文件系统,FAT文件系统以簇为单位来存储文件,每个簇的大小固定,为一个或多个扇区(一般肯定为多个,在DOS中多为2个或4个扇区,也可以是8个扇区等),假定每簇为4个扇区,每扇区512字节,则每个簇为2048字节,假定一个文件长度为900个字节,它也会占用一个簇,即2048字节;FAT表中的每个表项对应着数据区的一个簇,以FAT16为例,FAT表中每个表项占16bit,即2个字节,则FAT表中的0-1字节代表第0簇,2-3字节代表第1簇,4-5字节代表第2簇......,这种情况下,FAT表的表项下标和簇号是一致的,但在实际的FAT表中,第一个表项和第二个表项用来存储标志,所以实际第3个表项代表第0簇,这样,FAT表的表项下标和实际簇号就有了一个2的偏差,这就是为什么104-105行要把从根目录中得到的文件起始簇号-2的道理,不论是在FAT表还是目录中,存储的簇号都是FAT表的下标,而不是实际簇号,当FAT表中的表项值为0时,表示这是一个空闲的簇,而不是实际表示簇号为0
  • 根据起始簇号计算起始逻辑扇区号的方法如下:
    起始逻辑扇区号=起始簇号*每簇的扇区数+数据区的起始逻辑扇区号
    前面在052-061行已经计算了数据区的起始逻辑扇区号,并且存储在[7c49h]开始的4个字节中。
  • 114行告诉我们,读出的扇区以后要放在0:0700h开始的内存中
  • 115行告诉我们要读连续三个扇区,实际上,IO.SYS这个文件有39k多,但这里并没有全部读出来,仅仅读了三个扇区,很显然,后面的工作交给IO.SYS自己去完成了。
  • 116-130行是一个以来CX的循环,读取IO.SYS的前三个扇区,其中的两个子程序在前面都遇到过,流程图和注释也比较详细,这段就不多说了,这段程序运行完成后,IO.SYS的一部分就被读到0:0700h这个位置了
  • 131-133行初始化了一些寄存器,其目的显然是为了最后移交控制权做准备
  • 134行,跳转到0:0700h(注意:070h:0和0:0700h指向同一个地址)继续执行,把控制权交给IO.SYS,至此分区引导扇区的工作完成





  评论这张
 
阅读(4395)| 评论(3)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018