主引导程序是软件还是固件?如果是软件,那么由谁开发?如何开发?
主引导程序
- 一段存储在主引导区(MBR)中的有效代码。
- 并不固化于硬件,属于操作系统代码的一部分。
- 启动操作系统内核的桥梁,由汇编程序写成。
- 代码总量不能超过512字节(包括0x55aa)。
课程实验
编写一个主引导程序(汇编语言)
可独立运行于x86架构的主机(无操作系统)
运行后在屏幕上打印"HELLO,DTOS!"
org 0x7c00
start:
mov ax, cs
mov ss, ax
mov ds, ax
mov es, ax
mov si, msg
print:
mov al, [si]
add si, 1
cmp al, 0x00
je last
mov ah, 0x0e
mov bx, 0x0f
int 0x10
jmp print
last:
hlt
jmp last
msg:
db 0x0a, 0x0a
db "Hello, DTOS!"
db 0x0a, 0x0a
times 510-($-$$) db 0x00
db 0x55, 0xaa
主引导程序实际待的起始地址是0x7c00,因此第一行的org 0x7c00告诉编译器,这段程序的加载地址是0x7c00,这样编译器就可以对地址进行正确的处理。
然后将ss,ds,es寄存器分别清零,msg标签处在内存中定义了一些数据,这些数据是实实在在在内存中和磁盘文件中占用空间的。msg就代表了这片数据所占用空间的起始地址。mov si, msg就是将这个起始地址送到si寄存器中。
接下来print标号处定义了打印相关的功能,mov al, [si]就是取si所代表的内存地址处的一个字节数据,并放到al寄存器中,然后使si加1,指向下一个数据,此时先判断al中的数据是否是0x00,也就是ASCII码‘\0’,这个字符代表字符串的结束,如果确实为0x00,则跳转到last处,让cpu停机。如果不为0x00,则开始准备打印,将0x0e存到ah寄存器中,将0x0f存到bx寄存器中,相当于格式化参数(%c),然后通过int 10来调用中断向量表里面的打印函数,打印完一个字符后继续跳转到print处进行下一次循环,直到到达字符串的末尾。
下面我们讲一讲msg标号处的数据的定义,db伪指令定义一个字节,其后可以是数据,也可以是字符串。db 0x0a即定义一个字节,其中的数据初始化为0x0a,也就是换行符的ASCII码,db "Hello, DTOS!"相当于定义了12个字节。
根据前面内容知道,主引导扇区为512字节大小,而BIOS判断存储介质是否包含主引导扇区的标准就是看看它的前512个字节的最后两个字节是不是0x55和0xaa,如果是,那么BIOS就认为这个存储介质有主引导扇区,接下来就读取主引导扇区到内存中了。
前面写的程序不足以占满512字节,而我们的需求是要将最后两个字节写入0x55和0xaa,怎么办呢?我们让编译器去判断前面程序和数据占用空间的大小,并用适当数量的数据填满前面不足510字节的部分,然后在最后两个字节我们写入0x55和0xaa。
times 510 - ($ - $ $ ) db 0x00这条命令的意思就是填写510 - ( $ - $ $ )个0x00,$代表times这条伪指令的地址,$$代表当前汇编程序的起始地址(即start处,0x7c00),相减后即为以上所写程序和数据占用的空间大小,再用510减去这个值即为所需要填充的空间的大小。最后,第511字节填入0x55,第512字节填入0xaa。
问题
如何验证编写的主引导程序?
解决方案设计
将汇编源码编译为二进制机器码 (nasm)
创建虚拟盘 (bximage)
将二进制代码写入虚拟盘起始位置 (dd)
在虚拟机中将虚拟盘作为启动盘执行 (vmware)