打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
从头开始编写操作系统(4) 第3章:引导加载器 - xiaoxiaoyaya的专栏 - C...
  从头开始编写操作系统(4) 第3章:引导加载器 收藏
译自:http://www.brokenthorn.com/Resources/OSDev3.html

第3 章:引导加载器
by Mike, 2008, 2009
本系列文章旨在向您展示并说明如何从头开发一个操作系统。
介绍
欢迎!这正是您等待的一篇教程,在这一章包括的主题有:
引导步骤——它是怎么工作的
引导加载器理论
开发一个简单的引导加载器
使用NASM 汇编器汇编引导加载器
使用VFD (虚拟磁盘驱动器)软件:创建一个软盘映像
使用PartCopy :将引导加载器复制到软盘映像
使用Bochs ——基本设置和应用:测试引导加载器
准备好了吗?
引导过程
当电源按钮按下时
当我们按下电源按钮是到底发生了什么?当这个按钮被按下后,连接到这个按钮的线缆会向主板发送一个电信号,主板简单的把这个信号转发给电源(PSU )。
这个信号只包含1 比特信息。如果是0 ,表示没电(计算机关闭,主板不活动)。如果是1 (活动信号),意味着系统已经加电。
为了更好的理解,记住计算机的基础是二值逻辑。8 “比特”仅仅表示8 条可以导电的“线缆”,0 代表线上没有电流,而1 表示线上有电流。这些与逻辑门,一起构成了数字逻辑点了的基础,而在此之上构建的整个计算机。
当PSU 收到这个活动信号,它开始向系统的其余部分供电。当所有设备都得到正确数量的供电时,就可以确定PSU 会持续向它们供电而不发生大的问题。
PSU 会发送一个“供电正常(power_good )”的信号到主板的基本输入输出系统 (BIOS) 。
BIOS POST
到那个BIOS 接收到“power_good ”信号,BIOS 开始一个称为POST(Power On Self Test 加电自检) 的初始化过程。POST 通过测试确保供电正确,设备已安装 ( 如:键盘、鼠标、USB 、串口等) ,并确保内存状态良好 ( 通过检测内存损伤) 。
POST 向BIOS 交出控制权。POST 将BIOS 加载到内存的末尾( 可能是0xFFFFF0) 并且在内存的第一个字节处放置一个跳转指令。
处理器指令指针 (CS:IP) 被设置为0 ,然后处理器得到控制权。
什么意思呢?处理器会在地址0x0 处开始执行指令。这里,它是一条POST 程序放置的跳转指令,这条指令跳转到0xFFFFF0 处( 或者其他BIOS 被加载到的地址) ,然后处理器开始执行BIOS 。
BIOS 得到控制权……
BIOS
基本输入输出系统(BIOS) 会做一些工作。它创建一个中断向量表 (IVT), 并提供基本的中断服务。BIOS 然后会做一些检查以确保没有硬件问题。BIOS 也提供一个设置的功能。
BIOS 需要找到一个操作系统。根据您在BIOS 设置中指定的引导顺序,BIOS 执行0x19 号中断来找出一个可引导设备。
如果没有找到可引导设备 (INT 0x19 返回了) ,BIOS 会尝试引导顺序列表中的下一个设备。如果再没有可供尝试的设备,BIOS 会打印一个类似于“操作系统未找到”的信息,并停止系统的运行。
中断与中断向量表 (IVT)
一个中断是可以被许多不同的程序调用的子程序。这些中断被保存在从地址0x0 开始的被称为中断向量表的空间中。比如,一个常见的中断INT 0x21 被用于DOS 系统。
注意:这儿没有DOS !“只有”BIOS 设置的中断才有效,没有其他的!使用其他的中断会导致系统执行不存在的程序,这将导致你的系统崩溃。
注意:如果切换处理器模式,IVT 会变得无效。这意味着,任何的中断(无论软硬件,包括BIOS )全都无效。 对于32 位操作系统,我们不得不这样做。
BIOS 0x19 中断
INT 0x19 ——引导程序加载器
通过“热重启”重启系统,不会清空内存,也不会恢复中断向量表。
该中断由BIOS 执行。它读入磁盘的第一个扇区( 扇区(Sector ) 1, 磁头(Head ) 0, 磁道(Track ) 0) 。
扇区Sectors
扇区即一个512 字节的组,扇区1 表示磁盘最前面的512 字节数据。
磁头Heads
磁头( 或“面”) 表示磁盘的一面。磁头0 是正面,磁头1 是背面. 多数磁盘值由一个面,因此只有一个磁头。
磁道Tracks
为了理解磁道,看下面的图:
 
图中的磁盘代表硬盘或软盘,我们看到的是磁头0 (正面),并且每扇区512 字节。磁道是扇区的集合。
注意:记住1 扇区是512 字节,软盘的1 磁道又18 扇区,这一点在加载文件时很重要。
如果磁盘可引导,则引导扇会被加载到0x7C00 , INT 0x19 会跳转到哪里,将控制权交给一点加载器。
注意:引导加载器会被加载扫0x7C00 ,这很重要!
注意:有些系统在按下“热重启”按钮,会在地址0x0040:0072 处放置一个0x1234 再跳转到0xFFFF:0 。冷重启则会用0x0 代替。
现在,我们的1337 引导加载器得到控制权!
引导加载器理论
关于引导加载器我们已经看了不少。现在,把其中重要的部分放在一起。
引导加载器是……
……与主引导记录(Master Boot Record (MBR) )在一起。
……在磁盘的第一个扇区。
……大小是一个扇区 (512 字节)。
……已经被BIOS 的INT 0x19 加载到地址0x7C00 处。
如你所想,我们不能在512 字节里做很多事情。我们要做什么呢?
在汇编语言中我们很容易超过512 字节。尽管代码看起来不错,可是只有一部分 在内存中,比如,想想下面的例子:
mov     ax, 4ch
inc     bx         ; 512 byte
mov     [var], bx  ; 514 byte
在汇编语言中,从上往下执行。但,要记得当向内存加载文件时,以扇区为单位。 每扇区512 字节,因此只能复制几个512 字节到内存中。
如果只有第一个扇区被加载到内存,我们仅仅复制到第512 字节 (inc bx 那一行) 。这样最后的mov 指令仍在磁盘上,不在内存中 !
那当处理器执行完inc bx 之后会做什么呢?处理器会继续执行第514 字节。但是我们的代码不在内存中,它会跨过文件的末尾! 结果呢?崩溃。
但是,再加载第二(或更多)扇区到指定地址并执行是可能的。这样文件中剩余的数据就会加载到内存中,会工作的很好。
这种方法是可行的,但难以使用。常见的方法是将引导加载器控制在512 字节,用来搜索、加载和执行第二段引导加载器。这个我们会在后面看到。
硬件异常Hardware Exceptions
硬件异常与软件异常相似不过它由处理器 而不是软件执行。
有时,我们必须避免所有异常的产生。比如,在我们切换处理器状态后,整个中断向量表失效,此时,任何的软硬件中断都会使我们的系统崩溃 。我们在后面详细说明。
CLI 和 STI 指令
您可以使用STI 和CLI 指令允许或禁止所有的中断,大部分系统不允许应用程序执行这两条指令,因为这可能会带来大问题(尽管系统可以模拟它们)。
cli            ; 禁止中断
 
; do something...
 
sti            ; 允许中断——我们前面禁止了!
双重错误(Double Fault )的硬件异常
如果处理器在处理异常的时候发现了问题(如,非法指令,除0 ,等),处理器会执行双重错误处理程序,即0x8 中断。
我们在后面会看到一个双重错误。如果处理器在双重错误之后还不能恢复,它会执行一个三重错误(Triple Fault )。
三重错误Triple Fault
前面我们见到过这个条目吗?CPU 的三重错误意味着系统重启。
在早期阶段,比如在引导加载过程中,你代码中的错误,会产生一个三重错误。这表明你的代码有问题。
开发一个简单的引导加载器
总算到了我们等的了!
让我们在看看我们的列表:
与主引导记录(Master Boot Record (MBR) )在一起。
在磁盘的第一个扇区。
大小是一个扇区 (512 字节)。
已经被BIOS 的INT 0x19 加载到地址0x7C00 处。
打开任意的文本编辑器(我使用Visual Studio 2005 ), 但Notepad (记事本)就足够了。
这里是引导加载器 (Boot1.asm)...
;*********************************************
;       Boot1.asm
;              - A Simple Bootloader
;
;       Operating Systems Development Tutorial
;*********************************************
 
org            0x7c00                         ; 我们已经被BIOS 加载到 0x7C00
 
bits    16                                    ; 我们在16 位实模式
Start:
 
        cli                                   ; 禁止中断
        hlt                                   ; 系统停机
       
times 510 - ($-$$) db 0                              ; 我们得有512 字节,将剩余的部分清零
dw 0xAA55                                     ; 引导标志
这些并没有什么令人兴奋的,下面我们一行行分析:
org            0x7c00
记住:BIOS 把我们加载到0x7C00 ,上面的代码告诉 NASM 确保相对地址为0x7C00 。这表示,第一条指令在0x7C00 处
bits    16
还记得第2 章吗?在那一章里,我解释了x86 系列向后兼容老DOS 系统。因为老DOS 系统是16 位的,所有的x86 兼容机引导时为16 位模式 ,也就是:
我们受限在1 MB 内存。
我们受限在16 为寄存器。
我们会在后面将计算机切换到32 位模式。
times 510 - ($-$$) db 0
我希望这里有文档可以参考。在NASM 中,美元符($) 表示当前行的地址。$$ 表示第一条指令的地址(0x7C00) 。所以,$-$$ 返回当前行到起点共有多少字节 ( 这里就是程序的大小) 。
dw 0xAA55
这需要一些解释。
BIOS INT 0x19 会搜索可引导磁盘。那它怎么知道一个磁盘是否可以引导呢?因为引导标志。如果511 字节是0xAA 且512 字节是0x55 ,INT 0x19 会加载它,并执行引导加载器。
因为引导表示必须是引导扇的最后两个字节。我们使用times 关键字填充到第510 个字节,而不是第512 个字节。
使用NASM 汇编
NASM 是命令行汇编器,因此必须通过命令行或批处理脚本执行。汇编Boot1.asm 这么做:
nasm -f bin Boot1.asm -o Boot1.bin
-f 选项用于告诉 NASM 生成哪种类型的文件,这里是二进制文件。
-o 选项由于给出输出文件名,这里是Boot1.bin
汇编之后你会得到一个名为"Boot1.bin"512 字节的文件。
注意:因为一些原因Windows 文件浏览器会显示文件的大小为1 KB ,但查看文件属性时你会发现它确实是512 字节。
使用VFD ( 虚拟软盘驱动器)
我们使用VFD 来创建我们的操作系统要保存的虚拟软盘。下面解释如何使用它。
打开 vfdwin.exe.
在Driver 标签下,点击Start 按钮,以启动驱动器。
点击Drive0 或Drive1 标签。
点击Open
你会看到这个:
 
确保Media Type (媒体类型)是st 和ard 3.5" 1.44 MB floppy (标准的3.5" 1.44 MB 软盘),并且类型是RAM 。同样的,确保Write Protect (写保护)打开(不选中)。点击 "Create".
到“我的电脑”( 在“您”的计算机上) 您会见到一个新的软盘驱动器。
在驱动器图标上右击-> 属性,格式化软盘。在VFD 标签处会有一个格式化选项。
PartCopy ——复制引导加载器
好,现在我们有了自己的引导加载器,怎么把它复制到硬盘中呢?你可能知道,Windows 不允许我们将文件直接复制到磁盘的第一个扇区上,所以我们用一个命令来完成。
在第1 章中我们见到了debug 命令,如果你决定使用那个命令,请跳过这一节。
PartCopy 是一个命令行出现,它使用下面的语法:
partcopy file first_byte last_byte drive
PartCopy 不仅仅用于复制文件,它可以将制定的字节复制到扇区或从扇区复制出来,感谢它的语法(见上面),这是一个安全的方法。
因为你可以模拟软驱,你可以使用驱动器号(如A: )来代表驱动器。
要复制引导驱动器,这么做:
partcopy Boot1.bin 0 200 -f0
f0 代表0 号软驱。你可以使用f0 或f1 等,这要根据你的软盘在那个驱动器里。Boot1.bin 是我们要复制的文件。从第一个字节(0x0) 复制到最后一个字节 (0x200, 十进制的512) 。注意partcopy 只接受16 进制的数据。
警告:如果使用不小心,可能会导致磁盘数据损坏。上面的命令值适用于软盘,不要在硬盘上尝试。
Bochs: 测试引导加载器
Bochs 是一个32 位PC 仿真器,我们使用它来调试和测试。
Bochs 使用配置文件来描述要仿真的硬件。如下例,是我使用的配置文件:
# ROM 和 VGA BIOS images ---------------------------------------------
 
romimage:    file=BIOS-bochs-latest, address=0xf0000
vgaromimage: VGABIOS-lgpl-latest
 
# boot from floppy using our disk image -------------------------------
 
floppya: 1_44=a:, status=inserted  # Boot from drive A
 
# logging 和 reporting -----------------------------------------------
 
log:         OSDev.log              # All errors and info logs will output to OSDev.log
error:       action=report
info:        action=report
配置文件使用# 注释。它试图从一个在驱动器A 中的软盘引导。
ROM BIOS 和VGA BIOS 映像文件是和Bochs 一起的,所以别为它担心。
定位BIOS ROM
配置文件中的大部分都很简单。有一行需要再看看:
romimage:    file=BIOS-bochs-latest, address=0xf0000
这行告诉Bochs 把BIOS 放到内存的什么位置。要知道BIOS 的大小是可变的,BIOS 必须放在1MB 的末尾,即BIOS 的最后一个字节必须在0xFFFFF 。
因此你可能需要改变BIOS 的位置。这可以通过获得BIOS 映像的大小(它在Bochs 文件夹下的BIOS-bochs-latest )。这个大小以字节为单位。
这样从0xFFFFF 减去BIOS 文件的大小(以字节为单位)。这就是新的BIOS 地址,更新这一行的address ,把BIOS 移到一个新位置。
你可能不需要这一步。如果你被告知“BIOS 必须在0xFFFFF 结束”时,你就要这么做了。
如何使用Bochs
使用Bochs:
执行bochs.exe
选择option 2 (Read options form) ;按回车。
输入配置文件名 ( 我们上面创建的那个) ; 回车。
你会返回到主菜单。选option 5:Begin Simulation (开始仿真),回车。
一个新的窗口会打开,你会看到:
 
如果Bochs 退出并重启了
……你有了一个三重错误的经历。返回到代码,找找哪里出了错。如果你需要帮助,联系我吧。
如果窗口出现,但什么也没发生
恭喜!这是我们的cli 和hlt 指令使系统停止了,我们的引导加载器在执行了。
构建步骤——总结
和我们在前一章里提到的构建步骤相比较,一旦你跟着做了,你会发现这很简单。
从此往后,我们将步骤详细重复这个构建步骤。
下次见
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaoxiaoyaya/archive/2011/04/13/6321590.aspx
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
自制 os 极简教程 2:史上最难的 hello world
MBR和GPT分区表的那些事儿
“裸机”到底能干些什么呢?
计算机病毒
操作系统引导详细过程
装机、做系统必备:秒懂MBR和GPT分区表
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服