1 BIOS
BIOS全程 Base Input & Output System,基本输入输出系统
Intel 8086有20条地址总线,可以访问1\(MB\)的内存空间:\(0x00000\dots 0xFFFFF\),这1\(MB\)的空间被具体的分成不同的部分.
其中,底部:\(0x00000\dots 0x9FFFF\)这段内存是物理内存映射区,也就是DRAM,动态随机访问内存.一共640\(KB\)
顶部\(0xF0000\dots 0xFFFFF\)是BIOS的ROM映射区,一共64\(KB\)
地址总线宽度决定了可以访问的空间大小.其中,在计算机中,除了插在主板上的内存需要通过地址总线来访问,还有一些其他外设同样需要通过地址总线来访问:BIOS,显卡等
BIOS本身是一个程序,其入口在\(0xFFFF0\):在开机的一瞬间,cpu将cs:ip寄存器的只强制初始化位\(0xF000:0xFFF0\),但是,\(0xFFFF0\)距离\(0xFFFFF\)只有16个字节,并不能执行复杂的操作,因此此处的代码是一条跳转代码.
2 0x7c00
BIOS进行操作的最后一项:去教研启动盘中位于0盘0道1扇区中的内容,此扇区末尾两个字节是否是魔数:\(0x55\)和\(0xaa\),如果是,那么将该扇区的内容加载到物理内存\(0x7c00\)的位置.
0盘0道1扇区,这种表示方法是是:CHS方法,即柱面Culinder,磁头Header,扇区Sector
3 编写MBR
首先,解释下一些汇编的知识:
mov 相当于赋值的意思.
mov ax,0x11
表示给ax
赋值0x11
$
标识本行的地址,$$
标识本节的地址,节开始的地方有SECTION
声明寄存器,例如
ax
,可以拆开使用,就是高8位和低8位汇编中的数据类型:
db:字节.dw:两个字节.dq:4个字节
因为MBR要被BIOS加载到内存的0x7c00
处,并将跳转到改地址执行.因此MBR中的地址应该以0x7c00
作为段基址.也就是说,所有的地址应该以0x7c00
开始编写.当然我们在编写程序的时候不会直接使用变量的地址.例如我们定义一个int a=1
,我们使用1的时候,不会去使用1的物理地址,而是使用a
,当时编译器会将a
替换为一个地址,因为cpu运行的时候需要的是地址.因此这个起始地址对与程序编写来说没有影响,它只是对编译器有影响.使用vstart
告诉编译器,起始地址从0x7c00
开始编排.使用vstart
通常情况下,是在知道了程序将要被加载的地址以后,才使用.否则也会造成混乱.
另外要使用到一些BIOS中断的知识:BIOS中断大全
还有一个是,要在510字节以后开始填充0x55
,0xaa
,也就是说要在指定的位置填充.首先MBR中使用不了510字节,因此,正常的代码后面全部填充位0.然后在510字节后面开始填充两字节的魔术.使用times
批量填充.
; mbr.asm 主引导程序
SECTION MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
; 清除屏幕
; INT 0x10 功能号0x06,AH中存功能号,AL中存上卷行数,BH中存上卷行属性
; ah:子功能号,al:0表示0x06子功能号,向上卷屏幕的行数,0表示全部
; bh:空白区域缺省属性
; cx,dx:上卷时候认为屏幕的大小,也就是只上卷cx,dx标识的矩形区域内的字符.
mov ax,0x600
mov bx,0x0700
mov cx,0x0
mov dx,0x184f
int 0x10
; 设置光标位置
; INT 0x10 子功能号0x02,AH中存子功能号
; bh:显示页码,dh:y,dl:x
mov ax,0x02
mov dx,0x0
int 0x10
; 显示字符串
; int 0x10 子功能号0x13
; es:bp:字符串起始地址,bh:页码,cx:字符串长度,al输出模式
mov ax,msg_start
mov bp,ax
mov cx,msg_end-msg_start
mov bx,0x0002
mov ax,0x1301
int 0x10
jmp $ ;让程序在这里无限循环
msg_start db "2 mbr start!!!!!"
msg_end db 0
times 510-($-$$) db 0
db 0x55,0xaa
将asm
文件编译,并刻录在虚拟磁盘中:
使用nasm
编译:nasm -o mbr.bin mbr.asm
.紧接着使用dd
命令,刻录:dd if=./mbr.bin of=./hd60m.img bs=512 count=10 conv=notrunc
然后运行bochs
,按c
回车开始执行.
dd
命令详解:链接
注意,当count
的块少于源文件的大小时.其余的块会用0填充.我们这里多填充了9块.
4 脚本
为了方便每次编译和刻录.
因此编写shell脚本一键执行start.sh
:
#! /bin/bash
# 编译mbr.asm
nasm -o mbr.bin mbr.asm
# 刻录mbr.bin
dd if=./mbr.bin of=./hd60m.img bs=512 count=10 conv=notrunc
# 运行bochs
bochs
然后,改变权限,让其可执行chmod a+x ./start.sh
以后修改mbr.asm
文件以后,直接运行./start.sh
即可