欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-22 09:52:29
...

首先,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 aaa@qq.com

loader.bin: loader.S boot.inc
    nasm loader.S -o aaa@qq.com

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

run:
    qemu boot.img

为了编译和制作镜像方便,编写一个简单的makefile

make 就可以制作一个完整的引导镜像

make run 就可以运行

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

Note

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

相关标签: os