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 就可以运行
Note
如果没有把loader加入镜像中,可以看到屏幕上打印出 1 MBR 字样
上一篇: 4.3 stability应用程序
下一篇: CUDA学习2