上一篇,我们启动了bohcs,可惜,没能正常启动,原因是缺少MBR。
从主机上按下power建之后,第一个运行的软件是BIOS,由于软件不可能自己加载自己,所以BIOS肯定是由硬件加载的,这个硬件就是只读存储器ROM。只读存储器中的内容是不可擦除的,它和DRAM不同。
这块ROM也是一块内存,BIOS的地址被硬件映射为0xFFFF0,而CPU中的cs:ip寄存器会在通电的一瞬间被强制初始化为0xF000(段基址):0xFFF0(段内偏移地址),在开机的时候处于实模式,在实模式下,段基址要乘以16,也就是左移4位,于是0xF000就变成0xF0000,CPU访问内存是用段地址+偏移地址来实现的,所以0xF0000+0xFFFF0,就变成了0xFFFF0了。这个地址,就是BIOS的入口地址。
由于在实模式下,只能访问20位地址线的空间(2^20=1MB),而0xFFFF0距1MB只有16个字节了,由于BIOS要检测硬件,做各种初始化工作,16字节的机器指令肯定干不了这么多事,只能说明0xFFFF0处应该是指令,而这个指令就是jmp far f000:e05b,这是条跳转指令,也就是说fe05b才是BIOS代码真正开始的地方。
开始之后,BIOS完成它的使命之后前的最后一项工作就是校验启动盘中位于0盘0道1扇区的内容。也就是MBR在磁盘上最开始的那个扇区。如果此扇区的末尾是0x55和0xaa,BIOS便认为此扇区中确实存在可执行的程序,这便是MBR。然后便加载到物理地址0x7c00,随后跳转到此地址,继续执行。为什么是0x7c00呢?在IBM PC 5150 BIOS开发团队规定的这个数。
MBR不是随便放在哪里都行的,首先不能覆盖已有的数据,其次,不能过早地被其他数据覆盖。通常,MBR的任务是加载某个程序(这个程序一般是内核加载器)到指定位置,并将控制权交给它。所谓的交控制权就是jmp过去而已。之后MBR就没用了,被覆盖也没有关系。
说了这么多,我们现在来写一个MBR,我们要编写MBR,要先准备nasm
[root@makeOS software]# yum install build-essential nasm -y
;主引导程序
;--------------------------------------------------------------------
SECTION MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
mov ax,0x600
mov bx,0x700
mov cx,0
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
db 0x55,0xaa
[root@makeOS software]# nasm -o mbr.bin mbr.S
[root@makeOS software]# ll
total 12
drwxr-xr-x. 4 root root 4096 May 25 23:12 bochs
-rw-r--r--. 1 root root 512 May 26 22:38 mbr.bin
-rw-r--r--. 1 root root 446 Mar 18 22:57 mbr.S
我们看到mbr.bin 是512Bytes
接下来我们就该把mbr.bin写道磁盘的0盘0道1扇区
[root@makeOS software]# pwd
/data/software
[root@makeOS software]# ls
bochs mbr.bin mbr.S
[root@makeOS software]# cd bochs/
[root@makeOS bochs]# ls
bin bochs.out bochsrc.disk hd60M.img share
[root@makeOS bochs]# pwd
/data/software/bochs
[root@makeOS bochs]# dd if=/data/software/mbr.bin of=/data/software/bochs/hd60M.img bs=512 count=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000148634 s, 3.4 MB/s
接下来,激动人心的时刻到了
我们在成功启动bochs后,在控制后台输入c,也就是continue,就会成功输出1 MBR的字样。