查看系列文章点这里: 操作系统真象还原
前言
当我们按下电源键,我们电脑第一个运行的软件就是BIOS,即基本输入输出系统。很显然它并不是我们电脑上的操作系统,它的工作是检测、初始化硬件,确认一切没有问题,BIOS会将控制权交给MBR(主引导记录),然后它的使命就结束了。
一、如何启动BIOS?
正常情况下,我们想启动一个软件,我们只需要鼠标点一点或者执行一条指令,操作系统就会帮我打开这个软件,但问题在于BIOS也是一个软件,这时候操作系统还没出生呢,那么要加载这个软件,就只有一种办法,那就是“ 写死 ”,只要让电脑一开机,就去运行BIOS就行了。
具体实现就是将BIOS放到固定不变的一块位置,再将我们的CS和IP寄存器在开机时强制指向这块固定不变的位置的“ 入口 ”,那么BIOS这个软件就运行起来啦!
更具体一点说,这一块位置就是只读存储器ROM(并不是内存,也不是磁盘)中的某一块地方,大小是64KB,地址范围被映射为0xF0000~0xFFFFF,那么BIOS软件的代码就在这里啦!而“ 入口 ”就是这一块地方的顶部,大小16B,地址范围0xFFFF0~0xFFFFF,CS和IP会在开机时强制指向0xFFFF0,这里存放着BIOS的第一条指令。
到这里BIOS启动就算完成了,那么接下来看看BIOS是如何工作的。
二、BIOS如何交出控制权?
当CS和IP指向0xFFFF0时,我们发现其后面就只有16B的空间了,这貌似啥也干不了,只够装一条指令,所以这条指令只能是一条跳转指令,它会带着CS和IP跳转到合适的地方,然后正儿八经的开始工作。
在经过一系列的硬件检测、初始化工作后(我们对这个不感兴趣,跳过跳过),BIOS迎来了它的最后一个任务——检查是否存在可执行的程序(其实就是MBR),如果存在,就跳转过去,然后退出就舞台啦!
具体的方法就是检查启动盘的 0 盘 0 道 1 扇区,看看它的最后两个字节是不是分别等于魔数0x55和0xaa,如果等于,那就执行跳转指令“ jmp 0 : 0x7c00 ”,MBR程序就在0x7c00这个地方。
BIOS的工作已经介绍完了,接下来上虚拟机来检验一下!
三、实践检验!
我们在上一节说了,BIOS要顺利完成它的工作,就需要有一个MBR,但是我们现在还没有,那么我们就先造个假,随便编一个,步骤如下所示:
在我们存放代码的目录下创建一个mbr.s文件,将我们编写好的MBR程序粘贴进去,这个伪造的MBR程序的作用就是在屏幕上打印“1 MBR”,宣告现在是我MBR的天下了!
gedit mbr.S
;主引导程序mbr.s
SECTION MBR vstart=0x7c00 ;定义MBR程序的起始地址
mov ax, cs ;初始化寄存器
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov sp, 0x7c00
mov ax, 0x0600 ;打印字符,不必深究,原理就是BIOS中断,以后用不到了
mov bx, 0x0700
mov cx, 0x0
mov dx, 0x184f
int 0x10
mov ah, 3
mov bh, 0
int 0x10
mov ax, message
mov bp, ax
mov cx, 5
mov ax, 0x1301
mov bx, 0x2
int 0x10
jmp $ ;死循环,避免程序执行到未知的地方了
message db "1 MBR"
times 510-($-$$) db 0 ;填充空白字符,让文件大小为512B
db 0x55, 0xaa ;定义魔数
接下来就是编译,没什么好说的。
nasm -o mbr.bin mbr.S
然后将它写到启动盘的 0 盘 0 道 1 扇区,这里路径大家可能需要根据自己的情况修改。
dd if=./mbr.bin of=../bochs/hd60M.img bs=512 count=1 conv=notrunc
接下来启动我们的bochs。
bin/bochs -f bochsrc.disk
到这里就说明我们BIOS已经完美完成了它的功能了,大功告成!
接下来我们最后再来验证一下BIOS的入口是不是0xFFFF0,以及执行的第一条指令是不是跳转指令。启动bochs后,不着急运行,键入sreg查看寄存器状态,可以看到如图所示的信息,这与我们前面所述的一致。
持续更新中~~~