开机后运行的第一个程序是 BIOS 。
BIOS 搬运 MBR 并 跳转运行 MBR…
全名 基本输入输出系统。
BIOS本身不需要修改,于是被写入了ROM中,被映射在低端1MB内存的顶部,
0xF0000~0xFFFFF,开机CS:IP指向 0xF000:0xFFF0 也就是 0xFFFF0. 也就是只有6个字节够用了,而这6个字节正好是一个跳转语句 JMP far F000:E05B. 跳到了 FE05B 处。这里是BIOS代码真正存在的地方。
BIOS 检测内存、显卡等外设信息,检测通过并初始化好硬件后,开始在内存0x000~0x3FF处建立数据结构,中断向量表IVT并填写中断例程。
因为是历史原因。
BIOS将检测到了任何可用的磁盘,BIOS就将其第一个扇区加载到0x7c00。
MBR的任务是加载某个程序(这个程序一般是内核加载器,很少有直接加载内核的)到指定位置,并将控制权交给它。之后MBR就没用了。
MBR 的大小必须是 512 字节,并且该扇区最后两个字节必须为 0xaa55。
$ 表示 本行代码前的标号。
$ $ 指代本 section 的起始地址。
section 又称 节 段。
如果 section 用了 vstart=xxxx 修饰,则 $$ 则表示 xxxx。
如果想要获得 section 在文件中的真实偏移量(真实地址),nasm编译器提供了 section.节名.start
nasm -f <format><filename> [-o <output>]
-f 是指定输出文件的格式。
nasm -hf 可用查看nasm 编译输出的格式。
目前只关注 bin 和 elf 这两种格式。
bin 是纯二进制。
elf 和 pe 相似,都是二进制可执行文件,掺杂了程序的内存布局、位置等信息。是给操作系统中的程序加载器用的。
section MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
;使用 int 0x10 功能号 0x06 清屏
mov ah,0x06
mov bl,0x00
mov bh,0x07
mov cx,0x0000
mov dx,0x184f
int 0x10
;获取光标的位置
mov ah,0x03
mov bh,0x00
int 0x10
;调用13好子功能打印字符串
mov ax,message
mov bp,ax
mov cx,0x0b
mov ah,0x13
mov al,0x01
mov bx,0x0002
int 0x10
jmp $
message db "This is MBR"
times 510 - ($-$$) db 0
db 0x55, 0xaa
编译
nasm mbr.asm -o mbr.bin
接下来将其写到0盘0道1扇区
if=FILE
指定要读取的文件
of=FILE
把数据输出到哪个文件
bs=BYTES
指定块的大小
count=BLOCKS
指定拷贝的块数
seek=BLOCKS
将块输出到文件时想要跳过多少个块
conv=CONVS
指定如何转换文件
append append mode (makes sense only for output; conv=notrunc suggested)
这句话建议在追加数据时,conv最好用notrunc方式,也就是不打断文件。
下面开始使用命令了
dd if=mbr.bin of=hd60M.img bs=512 count=1 conv=notrunc
得到的输出:
ount=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes copied, 0.00267 s, 192 kB/s