第02章 编写MBR主引导记录

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

首先,解释下一些汇编的知识:

  1. mov 相当于赋值的意思.mov ax,0x11表示给ax赋值0x11

  2. $标识本行的地址,$$标识本节的地址,节开始的地方有SECTION声明

  3. 寄存器,例如ax,可以拆开使用,就是高8位和低8位

  4. 汇编中的数据类型:

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即可

猜你喜欢

转载自www.cnblogs.com/perfy576/p/9023938.html