首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加载没有文件系统的内核- osdev

加载没有文件系统的内核- osdev
EN

Stack Overflow用户
提问于 2017-05-14 13:38:29
回答 1查看 1.1K关注 0票数 1

我构建了一个引导加载器来将内核加载到内存中。内核代码位于软盘的扇区上。二级引导加载程序从软盘中读取内存的原始字节,并将其放在内存中并执行内核。这在bochs模拟器上很好,但在qemu模拟器上却失败了。

一些教程建议将内核文件保存在文件系统(如FAT12)上,然后从它读取文件。所以,我想问一下,这样的系统在物理机器上真的能工作吗,还是会像qemu仿真器那样失败?用这种方式阅读内核也有好处吗?

将来我可能会用C实现一个文件系统,而不是使用程序集在引导加载程序中实现它。

qemu的问题可能是因为我的图像文件不是512字节的倍数,使得最后一个扇区不可读。

编辑:第一阶段引导加载器成功地在Qemu和Bochs上加载第二阶段。第1阶段引导加载程序是-

代码语言:javascript
复制
[org 0x7c00]

STAGE2 equ 0x800

STAGE2_SECTORS equ 2+1
TRACKS equ 2

mov [BOOT_DRIVE],dl

mov bp,0x9000
mov sp,bp

mov bx, msgReal
call print_string

call load_stage2

call STAGE2

jmp $

%include 'boot/bios.ASM'

[bits 16]
load_stage2:
    mov bx, msgStage2
    call print_string
    mov cl, 2
    mov bx, STAGE2
    mov dh, 1
    mov dl, [BOOT_DRIVE]
load_sector:
    call disk_load
    cmp cl, STAGE2_SECTORS
    je loaded
    cmp cl, 15
    add cl, 1
    add bx, 512
    jmp load_sector
loaded:
    ret

BOOT_DRIVE db 0
msgReal db "Booted in 16-bit mode",0
msgStage2 db "Loading the stage2 boot loader onto memory",0

times 510-($-$$) db 0
dw 0xaa55

第二阶段引导加载程序是-

代码语言:javascript
复制
[org 0x800]

KERNEL equ 0x1000
KERNEL_SECTORS equ 24

mov bx, msgStage2
call print_string

call load_kernel

mov bx, msg
call print_string

int 0x12
mov [0x600], ax

call switch_to_pm

%include 'boot/bios.ASM'

%include 'boot/gdt.ASM'
%include 'boot/protected_mode.ASM'
%include 'boot/print32.ASM'

[bits 16]

load_kernel:
    mov bx, msgKernel
    call print_string
    mov ax, 3
    mov cl, 4
    mov ch, 0
    mov bx, KERNEL
    mov dl, [BOOT_DRIVE]
    mov dh, 0
    mov ch, 0
load_sector:
    mov ah, 0x02
    mov al, 1
    int 0x13
    jc error1
    cmp al, 1
    jne error2
    push bx
    mov bl, [Sector]
    cmp bl, KERNEL_SECTORS
    pop bx
    je loaded
    push bx
    mov bl, [Sector]
    inc bl
    mov [Sector], bl
    pop bx
    inc cl
    cmp cl, 18
    jne continue
    add ch, 1
    mov cl, 1
continue:
    add bx, BytesPerSector
    jmp load_sector
loaded:
    ret

error1:
    mov bx, errorMsg1
    call print_string
    jmp $

error2:
    mov bx, errorMsg2
    call print_string
    jmp $

[bits 32]

BEGIN_PM:
    mov ebx, msgProt
    call print_string32
    call KERNEL
    jmp $

BytesPerSector equ 512
NumHeads equ 2
SectorsPerTrack equ 18

Sector db 0

BOOT_DRIVE db 0
msgStage2 db "Stage 2 reached!", 0
msgProt db "Successfully switched to 32-bit mode",0
msgKernel db "Loading the kernel onto memory",0
msg db "Loaded!!", 0
errorMsg1 db "Error1", 0
errorMsg2 db "Error2", 0

times 1024-($-$$) db 0

bios.asm

代码语言:javascript
复制
[bits 16]

print_string:
    pusha
    mov cx,bx
    mov ah,0x0e
    printStringStart:
    mov al,[bx]
    cmp al,0
    je done
    int 0x10
    inc bx
    jmp printStringStart
    done:
    popa
    ret

disk_load:
    pusha
    push dx
    mov ah,0x02
    mov al,dh
    mov dh,0x0
    int 0x13
    jc disk_error
    pop dx
    cmp dh,al
    jne disk_error
    popa
    ret

disk_error:
    mov ah,0x0e
    mov al,'X'
    int 0x10
    mov bx,errMsg
    call print_string
    jmp $

errMsg:
    db "Disk Read Error....."
    times 80-20 db " "
    db 0

protected_mode.asm:

代码语言:javascript
复制
[bits 16]
switch_to_pm:
    cli
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax
    jmp CODE_SEG:init_pm

[bits 32]
init_pm:
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp,0x90000
    mov esp,0x90000

    call BEGIN_PM

print32.asm:

代码语言:javascript
复制
[bits 32]

VIDEO_MEM equ 0xb8000
DEF_COLOR equ 0x0f

print_string32:
    pusha
    mov edx,VIDEO_MEM

print_string32_loop:
    mov al, [ebx]
    mov ah, DEF_COLOR

    cmp al,0
    je print_string32_end

    mov [edx],ax

    inc ebx
    add edx,2
    jmp print_string32_loop

print_string32_end:
    popa
    ret

gdt.asm:

代码语言:javascript
复制
gdt_start:
gdt_null:
    dd 0x0
    dd 0x0

gdt_code:
    dw 0xffff
    dw 0x0
    db 0x0
    db 10011010b
    db 11001111b
    db 0x0

gdt_data:
    dw 0xffff
    dw 0x0
    db 0x0
    db 10010010b
    db 11001111b
    db 0x0
gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

MakeFile

代码语言:javascript
复制
DIRECTORIES = boot kernel drivers HALx86 dataman

C_SOURCES = $(wildcard drivers/*.c HALx86/*.c dataman/*.c)
ASM_SOURCES = $(wildcard HALx86/*.asm)

CC = gcc
CFLAGS = -DDEBUG -m32 -ffreestanding -c -nostdlib

KERNEL = kernel/kernel_start.o kernel/kernel.o

ASM = nasm
AOFLAGS = -f elf32 -o
ABINFLAGS = -f bin -o

OBJ = ${C_SOURCES:.c=.o}
ASMOBJ = ${ASM_SOURCES:.asm=.o}

all: os-image.img

os-image.img: boot/boot_sector.bin boot/boot_stage2.bin kernel/kernel.bin
    cat $^ > $@
    echo "OS Image size:"
    wc -c os-image.img

kernel/kernel.bin: $(KERNEL) ${OBJ} ${ASMOBJ}
    ld -melf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary

%.o : %.c
    $(CC) $(CFLAGS) $< -o $@

%.o : %.asm
    $(ASM) $< $(AOFLAGS) $@

%.bin : %.asm 
    nasm $< $(ABINFLAGS) $@

clean:
    rm -fr kernel/*.o
    rm -fr drivers/*.o
    rm -fr HALx86/*.o
    rm -fr dataman/*.o
    rm -fr boot/*.bin
    rm -fr os-image.img *.bin *.o

rebuild:
    make clean
    make

backup:
    make clean
    zip -r backups/BACKUP_DATE-`date +%d-%m-%Y_%H-%M-%S`.zip $(DIRECTORIES) README.txt makefile
    make
EN

回答 1

Stack Overflow用户

发布于 2021-04-14 21:14:45

如果没有文件系统,就无法从文件中加载内核。

我见过的大多数遗留BIOS教程都没有将内核放入文件中,而是将引导加载程序和内核连接到一个原始二进制文件中,并将其重命名为软盘映像。这样,您就可以直接从磁盘的扇区加载内核。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43964525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档