📄 booting-loading_process_5.htm
字号:
<P><FONT face="Times New Roman TUR"
size=3>但这并不意味着,如果通过了BIOS软盘参数表的验证,而读取就一定能够成功。例如,软盘参数表中所记录的“每磁道的扇区数”为18,而实际的“每磁道的扇区数”为9,如果现在一个INT
13h, ax = 2的调用指定:磁头为0,磁道为1,磁道内起始扇区为2,要读取的扇区数目为9;由于磁道内起始扇区+要读取的扇区数-1 = 2+9 -1 =
10 <
18,通过软盘参数表的验证没有任何问题,但当软盘驱动器真正去读取磁头0,磁道1,第10个扇区的时候,而这个扇区并不存在,调用依然会失败。</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>所以,为了保证一个需要读取软盘的程序不出错误,我们必须保证:</FONT></P>
<P><FONT face="Times New Roman TUR" size=3>“要读取的扇区数” + “磁道内起始扇区” - 1 <=
软盘参数表中“每磁道的扇区数”的数值</FONT></P>
<P><FONT face="Times New Roman TUR" size=3>同时保证:</FONT></P>
<P><FONT face="Times New Roman TUR" size=3>“要读取的扇区数” + “磁道内起始扇区” - 1 <=
实际的“每磁道的扇区数”</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>你如果想保证你的程序永远不在读取软盘的时候出此类错误,最稳妥的方法是每次只读取一个扇区,但这样效率很低,真正作软件的人都愿意有效率更高,而又稳妥地方法——所以我们要在提高效率的目标下,寻找一种方法来确保效率。</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>我们还是看一看上面所列的两个条件,从中我们可以首先得知——我们必须知道实际的“每磁道的扇区数”,否则,我们肯定会出错。那么,在我们知道实际的“每磁道的扇区数”的前提下,软盘参数表中“每磁道的扇区数”的数值不能小于实际的“每磁道的扇区数”,否则,仍然会出错。那么大于呢?由于BIOS对软盘参数表中“每磁道的扇区数”的数值的验证放在前面,如果大于的话,这一级验证即使通过了,还有实际的“每磁道的扇区数”这一关需要通过。所以大于是不会有任何问题的。等于就更不用说了。</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>由此得知,要想让我们的程序不出此类错误,我们必须保证两点:</FONT></P>
<P><FONT face="Times New Roman TUR" size=3>1、保证 软盘参数表中“每磁道的扇区数”的数值 大于等于
实际的“每磁道的扇区数”。</FONT></P>
<P><FONT face="Times New Roman TUR" size=3>2、知道实际的“每磁道的扇区数”;</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>对于第1点,或许大家会问,难道BIOS厂商不能够来保证这一点吗?答案是,能够。但不幸的是,在现实生活中,由于历史的原因,确确实实有一些BIOS厂商将软盘参数表中“每磁道的扇区数”的数值设置的比较小。这样,我们就必须靠自己来保证这一点。</FONT></P><STRONG><FONT
face="Times New Roman TUR" size=3>
<HR width="100%" SIZE=1>
</FONT></STRONG>
<P><STRONG><FONT face="Times New Roman TUR"
size=3>如何保证软盘参数表中“每磁道的扇区数”大于等于实际的“每磁道的扇区数”? </FONT></STRONG></P>
<P><FONT face="Times New Roman TUR"
size=3>我们在前面已经说过,在BIOS的中断向量表中断1Eh的地址0:78h处,放置的仅仅是指向软盘参数表的的指针,而软盘参数表被放在BIOS
ROM中,我们无法修改。所以,我们可以在RAM中复制一份软盘参数表,进行修改。然后将BIOS的中断向量表中断1Eh的地址0:78h处的远指针修改为指向RAM中新复制的软盘参数表。</FONT></P>
<P><FONT face="Times New Roman TUR"
size=3>由于到目前为止,最大可能的“每磁道扇区数”为36(参见表1-5-1),所以我们只需要将新的软盘参数表中的“每磁道扇区数”修改为36,即可以保证软盘参数表中“每磁道的扇区数”的数值大于等于实际的“每磁道的扇区数”。</FONT></P>
<P align=center><FONT face="Times New Roman TUR" size=3><IMG
src="booting-loading_process_5.files/fpt_move.jpg"
tppabs="http://pagoda-ooos.51.net/os_book/booting/loading-process/fpt_move.jpg"></FONT></P>
<P><FONT face="Times New Roman TUR" size=3>下面是Linux 2.4的相关代码。</FONT></P>
<P><FONT face=System size=3># 将0:78h位置所保存的磁盘参数表指针所指向的位置的12格字节拷贝到0x4000-12的<BR>#
位置处,然后将磁盘新参数表的sectors/track值修改为36(2.88M软盘的参数),<BR># 最后修改0:78h处的指针指向0x4000-12
(es:di)<BR>#<BR> movw %cx,
%fs # %fs =
0<BR> movw $0x78, %bx #
%fs:%bx is parameter table address<BR> pushw
%ds<BR> ldsw %fs:(%bx), %si #
%ds:%si is source<BR> movb $6,
%cl
# copy 12 bytes<BR> pushw
%di
# %di =
0x4000-12.<BR> rep
# don't worry about
cld<BR> movsw
# already done above<BR> popw
%di<BR> popw %ds<BR> movb $36,
0x4(%di) # patch sector
count<BR> movw %di,
%fs:(%bx)<BR> movw %es, %fs:2(%bx)</FONT></P>
<P><FONT face="Times New Roman TUR" size=3></FONT><STRONG></P><FONT
face="Times New Roman TUR" size=3>
<HR width="100%" SIZE=1>
</FONT></STRONG>
<P><FONT face="Times New Roman TUR" size=3></FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><STRONG><FONT face="Times New Roman TUR"
size=3>如何获取实际的“每磁道的扇区数”?</FONT></STRONG></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><STRONG><FONT face="Times New Roman TUR"
size=3></FONT></STRONG> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR"
size=3>除了去猜测之外,没有什么好的方法能够获取“实际的每磁道扇区数”。所幸的是,实际存在的软盘只有有限的几个种类,而不同的“实际的每磁道扇区数”就更加有限。参见表1-5-1,我们可以得知,“实际的每磁道扇区数”有9,15,18,36四种。于是,我们就可以对一张软盘使用这四个数值从大到小依次猜测。</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR" size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR"
size=3>猜测的方法,是读取磁头0,磁道0,当前磁道最大扇区。首先猜测“当前磁道最大扇区”为36,如果实际的“每磁道扇区数”小于36,则读取失败。然后猜测“当前磁道最大扇区”为18,如果失败了,再猜测15……依次类推,直到猜测为9为止,这是最小可能的“每磁道扇区数”。</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR" size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR" size=3>下面是Linux 2.4的相关代码。</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face="Times New Roman TUR" size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3># Get disk drive parameters, specifically
number of sectors/track.</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3># It seems that there is no BIOS call to get
the number of sectors.</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3># Guess 36 sectors if sector 36 can be read,
18 sectors if sector 18</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3># can be read, 15 if sector 15 can be
read. Otherwise guess 9.</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3># Note that %cx = 0 from rep movsw
above.</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3>
movw $disksizes, %si # table of sizes to try</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System
size=3>probe_loop:<BR> lodsb
# Load byte at address DS:SI to AL
(DN)<BR> cbtw
# extend to word (ax = (disksizes))<BR> movw %ax,
sectors # sectors = max sectors per
track (DN)<BR> cmpw $disksizes+4, %si # there is 4
parameters</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3>
jae
got_sectors #
If all else fails, try 9</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3> # 读取第一个软驱的Head 0, Track
0, Max sector</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3> </FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3>
xchgw %cx, %ax
# %cx = track and
sector<BR> xorw %dx,
%dx # drive
0, head 0<BR> movw $0x0200, %bx #
address = 512, in INITSEG (%es = %cs)<BR> movw $0x0201,
%ax # service 2, 1
sector<BR> int $0x13<BR> jc
probe_loop # try next
value</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System size=3></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"
align=left><FONT face=System
size=3>got_sectors:</FONT></P></SPAN></SPAN></SPAN></SPAN></FONT></SPAN></FONT></SPAN></FONT></SPAN></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -