Kernel 在没有文件系统的情况下加载内核-osdev
我构建了一个引导加载程序,将内核加载到内存中。内核代码位于软盘的扇区上。两阶段引导加载程序从软盘中读取原始内存字节,并将其放入内存中,然后执行内核。这在bochs仿真器上运行良好,但在qemu仿真器上失败 一些教程建议将内核文件保存在文件系统(如FAT12)上,然后从中读取文件。 所以,我想问这样一个系统是在物理机器上工作,还是像在qemu模拟器上一样失败?这样读内核好吗 我将来可能会用C实现一个文件系统,而不是用汇编语言在引导加载程序中实现它 qemu的问题可能是因为我的映像文件不是512字节的倍数,使得最后一个扇区无法读取 编辑: 第一阶段引导加载程序在Qemu和BOCH上成功加载第二阶段。 阶段1引导加载程序是-Kernel 在没有文件系统的情况下加载内核-osdev,kernel,bootloader,osdev,bochs,Kernel,Bootloader,Osdev,Bochs,我构建了一个引导加载程序,将内核加载到内存中。内核代码位于软盘的扇区上。两阶段引导加载程序从软盘中读取原始内存字节,并将其放入内存中,然后执行内核。这在bochs仿真器上运行良好,但在qemu仿真器上失败 一些教程建议将内核文件保存在文件系统(如FAT12)上,然后从中读取文件。 所以,我想问这样一个系统是在物理机器上工作,还是像在qemu模拟器上一样失败?这样读内核好吗 我将来可能会用C实现一个文件系统,而不是用汇编语言在引导加载程序中实现它 qemu的问题可能是因为我的映像文件不是512字节
[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
[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
阶段2引导加载程序是-
[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
[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:
[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
受保护模式。asm:
[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
[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_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
print32.asm:
[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
[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_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
gdt.asm:
[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
[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_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
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
DIRECTORIES=引导内核驱动程序HALx86 dataman
C_SOURCES=$(通配符驱动程序/*.C HALx86/*.C dataman/*.C)
ASM_SOURCES=$(通配符HALx86/*.ASM)
CC=gcc
CFLAGS=-DDEBUG-m32-ffreserving-c-nostlib
KERNEL=KERNEL/KERNEL\u start.o KERNEL/KERNEL.o
ASM=nasm
AOFLAGS=-f elf32-o
ABINFLAGS=-f bin-o
OBJ=${C_源:.C=.o}
ASMOBJ=${ASM_SOURCES:.ASM=.o}
全部:os-image.img
os-image.img:boot/boot_sector.bin boot/boot_stage2.bin kernel/kernel.bin
cat$^>$@
回显“操作系统映像大小:”
wc-c os-image.img
kernel/kernel.bin:$(kernel)${OBJ}${ASMOBJ}
ld-melf_i386-o$@-Ttext 0x1000$^--格式二进制文件
%.o:%.c
$(CC)$(CFLAGS)$<-o$@
%.o:%.asm
$(ASM)$<$(AOFLAGS)$@
%.bin:%.asm
nasm$<$(ABINFLAGS)$@
清洁:
rm-fr内核/*.o
rm-fr驱动程序/*.o
rm-fr HALx86/*.o
rm-fr dataman/*.o
rm-fr启动/*.bin
rm-fr os-image.img*.bin*.o
重建:
澄清
制作
备份:
澄清
zip-r backups/BACKUP\u DATE-`DATE+%d-%m-%Y\u%H-%m-%S`.zip$(目录)README.txt生成文件
制作
如果没有文件系统,就无法从文件加载内核
我见过的大多数传统BIOS教程都没有将内核放在文件中;相反,它们只是将引导加载程序和内核连接成一个原始二进制文件,并将其重命名为软盘映像。这样,您就可以直接从磁盘的扇区加载内核。如果没有文件系统,您就不能从文件加载内核
我见过的大多数传统BIOS教程都没有将内核放在文件中;相反,它们只是将引导加载程序和内核连接成一个原始二进制文件,并将其重命名为软盘映像。通过这种方式,您可以直接从磁盘的扇区加载内核。是的,从FAT12文件系统读取文件可以从引导加载程序工作。一些操作系统已经做了30多年了。如果它对你不起作用,那么它就是你代码中的一个bug。我从来没有尝试过使用FAT12文件系统,而是从按顺序将二进制程序直接放在扇区开始的。它有什么缺点吗?因为它只对bochs有效,而对qemu无效。在我看来,我的代码不能在物理机器上运行并没有什么大的原因@MichIf它在其中一个上工作,而在另一个上不工作,这是因为您的代码不正确。您可能在代码中做出了一些不正确的假设。如果您发布了所有代码,我可能会告诉您为什么它在BOCHS而不是QEMU中工作,并建议修复。如果使用USB在真正的硬件上进行测试,您甚至可能需要在引导加载程序中放置BIOS参数块。在bootloader开发中有很多gotchyas。我已经为stage 2 bootloader@MichaelPetchAdd添加了所有文件中的代码。通常问题可以从早期错误的事情开始。每一个文件,以便人们可以复制它。如果不这样做,很可能不会给出答案。是的,从FAT12文件系统读取文件可以从引导加载程序中工作。一些操作系统已经做了30多年了。如果它对你不起作用,那么它就是你代码中的一个bug。我从来没有尝试过使用FAT12文件系统,而是从按顺序将二进制程序直接放在扇区开始的。它有什么缺点吗?因为它只对bochs有效,而对qemu无效。在我看来,我的代码不能在物理机器上运行并没有什么大的原因@MichIf它在其中一个上工作,而在另一个上不工作,这是因为您的代码不正确。您可能在代码中做出了一些不正确的假设。如果您发布了所有代码,我可能会告诉您为什么它在BOCHS而不是QEMU中工作,并建议修复。如果使用USB在真正的硬件上进行测试,您甚至可能需要在引导加载程序中放置BIOS参数块。在bootloader开发中有很多gotchyas。我已经为stage 2 bootloader@MichaelPetchAdd添加了所有文件中的代码。通常问题可以从早期错误的事情开始。每一个文件,以便人们可以复制它。如果不这样做,你很可能得不到答案。