「無法從引導介質中讀取」我也跟着上Write your own operating system in 1 hour本系列教程創建一個基本的操作系統只有4個文件只是打印的「Hello World」:Makefile
,kernel.cpp
,loader.s
和linker.ld
。無法啓動在VirtualBox中定製的內核:
我正在創建一個mykernel.iso
文件,但是當我將它啓動到VirtualBox時,出現錯誤「無法從引導介質讀取:系統暫停」。我確認.iso
文件與我的機器實例相關聯。看起來代碼中還有其他一些問題。
這裏是我的Makefile:
#we need to tell the compiler to stop assuming that this will be executed inside an OS
CPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = --32
LDPARAMS = -melf_i386
objects = loader.o kernel.o
%.o: %.cpp
g++ $(CPPPARAMS) -o [email protected] -c $<
%.o: %.s
as $(ASPARAMS) -o [email protected] $<
mykernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o [email protected] $(objects)
install: mykernel.bin
sudo cp $< /boot/mykernel.bin
mykernel.iso: mykernel.bin
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp $< iso/boot/
echo 'set default=0' > iso/boot/grub/grub.cfg
echo 'set timeout=0' >> iso/boot/grub/grub.cfg
echo '' >> iso/boot/grub/grub.cfg
echo 'menuentry "My Personal OS" {' >> iso/boot/grub/grub.cfg
echo 'multiboot /boot/mykernel.bin' >> iso/boot/grub/grub.cfg
echo 'boot' >> iso/boot/grub/grub.cfg
echo '}' >> iso/boot/grub/grub.cfg
grub-mkrescue --output [email protected] iso
rm -rf iso
clean:
rm -rf iso
rm *.o
rm mykernel.iso
rm mykernel.bin
這裏是kernel.cpp
void printf(char *str)
{
unsigned short *VideoMemory = (unsigned short*)0xb8000;
for(int i=0;str[i] != '\0';i++)
VideoMemory[i] = (VideoMemory[i] & 0xFF00) | str[i];
}
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
for(constructor * i=&start_ctors;i!=&end_ctors;i++)
(*i)();
}
extern "C" void kernelMain(void * multiboot_structure, unsigned int magic_number)
{
printf("Hello World!");
//we do not want to exit from the kernel
while(1);
}
這裏是loader.s
:
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
.extern kernelMain
.extern callConstructors
.global loader
loader:
mov $kernel_stack, %esp
call callConstructors
push %eax #AX register has the pointer of multiboot structure stored by bootloader
push %ebx #BX register has the magic number
call kernelMain
#double check to not come out of the kernel, creating one more loop
_stop:
cli
hlt
jmp _stop
.section .bss
.space 2*1024*1024 #2MB for stack to grow towards left side
kernel_stack:
這裏是linker.ld
:
ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x100000;
.text :
{
*(.multiboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*(.init_array));
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ :
{
*(.fini_array*)
*(.comment)
}
}
我的開發環境是安裝了virtualbox的Linux Mint 18.1 64位。我的代碼幾乎與系列教師的代碼相匹配,但我仍無法在虛擬機中啓動。
編輯
我試着用qemu-system-i386 -kernel mykernel.bin
和正常工作與消息Hello World
。那意味着有一些問題,VirtualBox的環境和配置。
在虛擬機啓動過程中,您是否打過F12並告訴它您從光盤啓動? –
我懷疑你的問題可能與棧有關。你創建一個2MB的棧很大。因爲它位於BSS部分,所以多重引導加載程序會將其歸零。在某些環境中,問題是如此龐大的BSS段可能導致多引導加載程序在加載和處理內核時失敗。如果堆棧是問題,請嘗試將大小設置爲2k(2048字節)而不是2mb。它工作嗎? (即將其更改爲:'.section .bss''.space 2 * 1024') –
您應該嘗試用'qemu'來查看您的內核是否正常。可能首先檢查二進制文件(.bin),然後檢查.iso。 –