1.什么是MBR
说实话,我一直都不喜欢在一大堆内容一开始就抛出一长条概念,这很劝退,但现在记录一下是很有必要的,否则后续忘记就难理解了。
简单来讲,MBR记录着硬盘各个分区的大小和位置信息,就像人口普查一样,对整个硬盘的分布了熟于心。它是开机后访问硬盘时要读取的第一个扇区,不难理解,毕竟要知道自己去哪得先看地图。噢,对了,它的全称是主引导记录(master boot record),由于os需要一步步进行权限的完善,有程序进行接力和指引是必须的事情。
2. 0x7c00?why?
好吧,这个问题我也一直都很好奇,在进行6.s081实验时,取断点并跳转总是从0x7c00开始,搜了很多操作系统有关的文章都没有给我一个满意的答案,现在算是知道了:
早期的CPU要求物理地址 0x0~0x3FF 存放中断向量表(我还不知道这是什么意思),所以只能找其他地方放MBR了,在那时DOS(古老的系统)要求最小内存是32KB,但是MBR自然不可能覆盖在前面或中间(不然其他功能去哪开始加载,无序会导致混乱和时间变长),所以它必须预留空间,所以就得在32KB的末尾。
写程序的大家都知道,程序必须要用到栈,MBR虽说是汇编语言但也是一段程序,它在内存里由于要给栈分配空间实际上总空间要大于512字节,最大估计也就1KB了(毕竟功能就那点),所以选32KB中最后1KB最合适,而那个地方就是0x7c00。
3.启动MBR的坎坷风雪路
首先是简单的MBR代码:
1 ;主引导程序 2 ;--------------------- 3 4 SECTION MBR vstart=0x7c00 ;程序开始的地址 5 mov ax, cs ;使用cs初始化其他的寄存器 6 mov ds, ax ;因为是通过jmp 0:0x7c00到的MBR开始地址 7 mov es, ax ;所以此时的cs为0,也就是用0初始化其他寄存器 8 mov ss, ax ;此类的寄存器不同通过立即数赋值,采用ax中转 9 mov fs, ax 10 mov sp, 0x7c00 ;初始化栈指针 11 12 ;清屏利用0x10中断的0x6号功能 13 ;------------------------ 14 mov ax, 0x600 15 mov bx, 0x700 16 mov cx, 0 17 mov dx, 0x184f 18 19 int 0x10 20 ;获取光标位置 21 ;--------------------- 22 mov ah, 3 ; 3号子功能获取光标位置 23 mov bh, 1 ; bh寄存器存储带获取光标位置的页号,从0开始,此处填1可以看成将光标移动到最开始 24 int 0x10 25 26 ;打印字符串 27 ;------------------ 28 mov ax, message 29 mov bp, ax 30 31 mov cx, 6 ;字符串长度,不包括'\0' 32 mov ax, 0x1301 33 mov bx, 0x2 34 35 int 0x10 36 37 jmp $ 38 39 message db "My MBR" 40 times 510-($-$$) db 0 41 db 0x55, 0xaa
注释都说的很清楚,显示器相关就不提了,主要写写第24行0x10中断和37、40、41行。
0x10中断在这里负责有关打印的例程。调用方法是将功能号送入ah寄存器,其他参数按照中断要求放在适当寄存器,然后执行int 0x10,具体了解在这贴个链接:(3条消息) BIOS INT 10中断功能详解_bios显示模式 int10_rhxznp的博客-CSDN博客
37行是一个死循环,$是本行指令的地址,jmp是近跳转,那么jmp $就是跳到自己的地址再执行自己,再跳到自己的地址再跳转,这样是为了让程序悬停在此处,等待下一步。
40行的$$是本section的起始地址,和上面$区别还是很大的,section起始地址和行起始地址并不是一个东西。$-$$是本行到本section的偏移量,MBR的最后两个字节必须是固定的内容,也就是BIOS认为可执行的程序MBR啦!如果不是,OK,BIOS不认识,无法启动。
那么一串times 和 - 号、db是什么意思?因为要预留出0x55,0xaa,所以得要计算填满扇区用的字节数,MBR共有512字节,那么510个字节就得填充,但是扇区里还有其他东西加载,所以用510-($-$$)得到剩余量,然后用0填充,这样预留的两字节就能确保了。
也就是说,到这里程序加载的顺序是BIOS -> 跳转0x7c00 -> 跳转0x55,0xaa.
接下来是最艰难的启动之路!
利用dd和nasm分别写入和编译MBR,这个没问题,注意路径就行,主要是启动bochs时,错误主要有三个(反反复复!):
-
这个每次启动都会弹出,真的很鸡肋!通过查阅发现img.lock删除后重启就行,还是不行命令加个sudo也可以。
- sector size of 0 is in error. 措施:中文意思是扇区大小0出错,我怀疑是我硬盘没有建立,或者建立了系统没反应,所以重新又建立了一次,解决了问题。
- NO bootable device. 措施:一开始我很困惑,明明我dd也nasm了怎么不认呢?原来是第二个错误的连锁反应,建立硬盘后再dd nasm一次就能识别MBR了。
虽说就三个错误,折腾了我大半天时间,一些文章也没有我的错误,反反复复重启删除,最后终于出现在bochs的图让我成就感满满,附个胜利图:
呃,别问我为什么和上面的程序显示不一样,为了解释重点的MBR结构,我搜索了这个比较简单的程序,但图中的这个是《操作系统真象还原》里的完整代码运行出的结果,所以不一样。
OK!总算是写完初认识啦!我只是个小菜鸡,一些认识肯定是浅显或有些不准确的,后面会随着OS的完善逐步深入,感谢浏览!