OS学习笔记(2) - MBR到Loader交接

首先,BIOS加载MBR,我们在MBR中实现对Loader加载到内存一个给定位置(0x900)

boot.S

%include "boot.inc"
SECTION MBR vstart=0x7c00
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7c00 
    mov ax, 0xb800  
    mov gs, ax

    ; clear screen
    mov ax, 0600h       ; AH = 0x06 AL = 0x00
    mov bx, 0700h       ; BH = 0x07 BL = 0x00
    mov cx, 0           ; left-top      (CH, CL) -> (0, 0)
    mov dx, 184fh       ; right-bottom  (DH, DL) -> (80, 25)
    int 10h
    ; output string
    mov byte [gs:0x00], '1'
    mov byte [gs:0x01], 0xA4

    mov byte [gs:0x02], ' '
    mov byte [gs:0x03], 0xA4

    mov byte [gs:0x04], 'M'
    mov byte [gs:0x05], 0xA4

    mov byte [gs:0x06], 'B'
    mov byte [gs:0x07], 0xA4

    mov byte [gs:0x08], 'R'
    mov byte [gs:0x09], 0xA4

    mov eax, LOADER_START_SECTOR    ; first sector 
    mov bx, LOADER_BASE_ADDR        ; load <loader> to memory addr 
    mov cx, 1                       ; numbers of write sector
    call rd_disk_m_16

    jmp LOADER_BASE_ADDR

; -----------------------------------
; read n sectors from disk 
; -----------------------------------
rd_disk_m_16:
    mov esi, eax     ; backup eax
    mov di, cx      ; backup cx
    ; step 1 - setup numbers of sector
    mov dx, 0x1f2
    mov al, cl
    out dx, al      ; sectors 

    mov eax, esi    ; restore eax 
    ; step 2 - 
    mov dx, 0x1f3
    out dx, al

    mov cl, 8
    shr eax, cl
    mov dx, 0x1f4
    out dx, al

    shr eax, cl
    mov dx, 0x1f5
    out dx, al

    shr eax, cl
    and al, 0x0f
    or al, 0xe0
    mov dx, 0x1f6
    out dx, al

    ; step 3 
    mov dx, 0x1f7
    mov al, 0x20
    out dx, al

    ; step 4 - check harddisk status
.not_ready:
    nop
    in al, dx
    and al, 0x88
    cmp al, 0x08
    jnz .not_ready

    ; step 5 - read data from 0x1f0 port 
    mov ax, di
    mov dx, 256
    mul dx
    mov cx, ax

    mov dx, 0x1f0
.go_on_read:
    in ax, dx
    mov [bx], ax
    add bx, 2
    loop .go_on_read
    ret

    times 510-($-$$) db 0
    db 0x55, 0xaa
rd_disk_m_16函数涉及一些读硬盘的细节,暂可略过,以后再仔细研究,现在当成一个可以读取硬盘的黑盒函数,输入参数(eax-要读取的第一个扇区, bx-加载到内存的位置, cx-加载的扇区数)即可。

boot.inc

LOADER_START_SECTOR equ 0x02
LOADER_BASE_ADDR    equ 0x900
定义一些宏的头文件

loader.S

%include "boot.inc"

section loader vstart=LOADER_BASE_ADDR
    ; output string
    mov byte [gs:0x00], '2'
    mov byte [gs:0x01], 0xA4

    mov byte [gs:0x02], ' '
    mov byte [gs:0x03], 0xA4

    mov byte [gs:0x04], 'L'
    mov byte [gs:0x05], 0xA4

    mov byte [gs:0x06], 'O'
    mov byte [gs:0x07], 0xA4

    mov byte [gs:0x08], 'A'
    mov byte [gs:0x09], 0xA4

    mov byte [gs:0x0A], 'D'
    mov byte [gs:0x0B], 0xA4

    mov byte [gs:0x0C], 'E'
    mov byte [gs:0x0D], 0xA4

    mov byte [gs:0x0C], 'R'
    mov byte [gs:0x0D], 0xA4
loader.S 编译之后,是一个独立的执行二进制文件,是被mbr程序加载到内存(0x900)中的。

makefile

boot.img: mbr.bin loader.bin
    @echo "start make image file ... "
    dd if=mbr.bin of=boot.img bs=512 count=1 conv=notrunc
    dd if=loader.bin of=boot.img bs=512 count=1 seek=2 conv=notrunc

mbr.bin: boot.S boot.inc
    nasm boot.S -o $@

loader.bin: loader.S boot.inc
    nasm loader.S -o $@

clean:
    @rm mbr.bin loader.bin boot.img

run:
    qemu boot.img
为了编译和制作镜像方便,编写一个简单的makefile
make 就可以制作一个完整的引导镜像
make run 就可以运行

这里写图片描述

Note
如果没有把loader加入镜像中,可以看到屏幕上打印出 1 MBR 字样
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值