装载BootLoader

目标:在BootSector中装载BootLoader

虽然简单,但是我却用了两天来解决它,还是了解的东西太少,重点在解决错误过程

最终代码大家看我另一篇文章:BootSector中装载BootLoader代码
(纯代码应该不可能投稿成功,就不投了)

书一中先写了BootSector的代码,当然,只是显示了一段文字代表确实运行了,接下来它要在BootSector中装载BootLoader到内存

而书二中则是先进入保护模式,然后再去写BootSector

为避免大家叫法,理解不同,这里再说明一下这两个词:
  1. BootSector指是那个512字节的引导扇区(虽然我发现可以制作成iso镜像超过512字节也会读取到),由于BootSector空间有限,做的事不够多(虽然对我们来说够多的了),所以我们用它把BootLoader加载到内存中。

  2. BootLoader指的是被BootSector加载的启动程序,它会加载内核,进入保护模式,执行内核等等

书二先进入保护模式是为了借助DOS来解决BootSector空间有限的问题,我不想采用这种方法,而且一个更重要的原因是它看起来太复杂。

装载BootLader问题

和书一一样,直接使用0x13读取即可,我们此时只能使用BIOS中断,在维基百科上的是我找到的内容比较全的(如果大家知道那里能获取到更详细的,也分享下喽),按照书中所作,显然是错误的,否则,我就不会查两天了

我们使用13H号中断,2号功能(AH=02H),当然,在使用前稍微了解一下磁盘是最好的

寄存器 存放的参数(书中取值)
AL 一次读取的扇区数(=1)
CH 柱面号(=0)
CL 扇区号(=0)
DH 磁头(=2,因为第一个扇区是引导扇区)
DL 驱动器号(=0)
ES:BX 读取到内存的位置(=820H: 000H)

接下来重点就是这几个坑人的参数了,此时一定要记得,书中介绍的是软盘(谁让这书历史有点久了),而查到的资料大多是硬盘,但是我们用的ISO镜像应当是属于启动光盘,与前面两者不同

  1. 扇区数没什么问题,按照查到的资料,多个扇区读取在某种情况会有错,而且书中也是这样说的,我们就取1,这个没有争议

    同样,读取到内存的位置也没有争议,7C00H是BIOS装载引导扇区的位置,512字节后就是8000H,作者为了让地址一致一点,软盘中第二、三个扇区地址200H,400H,正好对应内存地址8200H,8400H

  2. 软盘(按照书中所说):80个柱面,每个柱面18个扇区,正反两面都有磁头

    而硬盘与软盘都是使用CHS寻址(柱面-磁头-扇区),理论上三者范围为分别为0-1023, 0~255, 0-63,所以我猜硬盘可以达到最大范围,而软盘局限于构造,范围比较小

    最后是ISO镜像,为了解决问题,我去查了下它的文件结构,一个扇区认为是2048个字节(前面俩都是512字节),除此之外,他是从第十六个扇区开始记录数据,而且在我的ISO文件中,引导扇区是在第23个扇区,它并没有什么柱面和磁头的说法

  3. 最后是我们的驱动器号,维基百科上:

    当时很激动,因为这个表是我找到的唯一一个注明CD的驱动器号的

驱动器号 驱动器
DL = 00h 1st floppy disk ( "drive A:" )
DL = 01h 2nd floppy disk ( "drive B:" )
DL = 80h 1st hard disk
DL = 81h 2nd hard disk
DL = e0h CD/DVD

开始解决之路

  1. 按照作者的做法我错了,读取出错了,调用INT 13H后CF标志位为1

  2. 发生错误的主要原因是我与作者的环境不一样,他的是软盘,我的是ISO镜像,当我找到一张INT 13H的表之后,发现了DL=80H这个选项,我改了之后,读取没有出错,但是内存中没有写入我想要的东西,都是一堆0,也就是说什么都没有读到

  3. 我认为我驱动器找对了,但是ISO镜像和实际硬盘可能存在区别(当时我天真的认为两者差不多),所以我就去看了ISO的文件结构,找到的上面所说的一些问题,所以我尝试着从第16个扇区开始读,结果和上一步一样

    猜测可能和ISO文件一个扇区认为是2048个字节有关,按照512个字节一个扇区来说,就该去读第64个,仍旧一堆0

    由于当时认为最大18个扇区,然后换算一下,以512,2048为标准,都进行了一次读取,一堆0

    可能ISO前15扇区完全没用?试着以16扇区为开始,读取各处尝试一下,一堆0

  4. 在维基上找到了注明驱动器号的表,发现有个CD,而且由于前面查询,了解到ISO应该和光盘类似(使用UltraISO很直观的写着启动光盘映像,我居然没有仔细想过),突然兴奋,我把驱动器号改为E0H后,再次尝试,结果读取出错。。。。一盆冷水

  5. 不死心的我把驱动器号在00H,80H,E0H旁边几个数到处换,而且按照第三步中改其它参数,依次试了个遍(感觉心头下起了雨)

  6. 突然看到了Vmware那里清楚的列出了硬盘与CD镜像,所以。。。我之前读取成功是因为确实有硬盘,读取失败是因为没有找到CD对应的驱动器号,开始疯狂找资料


  1. 找资料失败,找到的最详细的是维基的,但是我已经尝试过了

  2. 既然如此,我就要试试作者编出来的,他有自己的生成的批处理以及各种环境,我没法配置,但是我可以直接拿他结果试,他有img镜像,但是要生成iso的,所以只能拿他的img做引导文件,最终可以运行(倾盆大雨)为什么同样是读取软盘,它的出了结果,我的没有结果

  3. 我要拿linux的引导看一下,我发现他们是从DL读取的驱动器号,我尝试了一下,读取出来是0,也就是-软-盘-,可是我试过了,都是错啊,我***

  4. 就在我即将放弃的时候我突然想起,我现在几乎肯定,就在驱动器号上,我除了80H可以读到,还没有找到另一个可以读的驱动器号,既然如此,我为什么不直接试一下全部的,由于之前试过00,80H,E0H导致我想到的是一个一个试,这肯定不可能,太累了
    两天的摧残,让我忘记了循环,幸亏最后想到,最后真的成功试到一个(中途差点因为逻辑错误没有写成功,差点放弃)

最终我们拿到了除80H以外的唯一一个驱动器号9FH,我拿着3中的方法,尝试各种组合,因为我相信这就是那个ISO映像对应的驱动器号

最终:

驱动器号:9FH
柱面:0
磁头:0
扇区:5(CHS寻址依然以512一扇区为准,但是ISO每个扇区实际上是2048字节,所以访问储存到第二个扇区需要CHS寻到第五个扇区)

未解决的问题:

  1. 为何Linux他们就可以DL就可以读到正确的驱动器号呢?

  2. 作者的究竟读取争取没,因为我实在不想去折腾他的环境了,因为要想验证,我就需要看到内存的样子,就需要改他的代码,就得使用他的环境

  3. 维基上的那个E0到底哪来的,我最终得到的9F又是为什么

查询的过程中,发现有很多人都有做这件事,我查询的几个方面,几乎都提到过《30天自制操作系统》,有些很久远了,我不知道是否早已有人解决了这个问题,但是特别希望,下次有人碰到这个问题可以查询到我的这篇文章,让他可以少走点弯路(虽然我这可能就是一条弯路,但起码解决了面前的问题不是么)


1的答案
DL中确实存在,只不过实我的代码错了,在输出字符串的时候,设置过DL=00H,所以就覆盖掉了,我改正了代码,将DL存入DriverLetter中

2的答案
作者应该是找到了,由于他的是软盘,可以直接使用00

3的答案
在某个角落找到这样一段,大致含义是,boot image有三种情况

  1. 软盘类型,加载boot image后对应驱动器号00
  2. 硬盘类型,加载boot image后对应驱动器号80
  3. 只是一段简单的引导程序,加载boot image后驱动器和原本的一样,在我这里就是那个奇特的9F了


所以总结我的错误,正确做法就是在将寄存器初始化之后就将DL存起来就好,那就是你的驱动器号

你可能感兴趣的:(装载BootLoader)