luciferau 2022-08-02 21:59
浏览 42
已结题

自己编写操作系统,运行ISO文件,遇到grub

 编写操作系统时,使用自己生成的ISO文件再虚拟机运行时出现一下错误(virtualbox和VMware workstation 都试过)

img

人都懵逼了,他们编写的代码和我一样,为啥我的就会进入grub呢,

我想要达到的结果:能正确进入系统,打印hello world ;

代码部分

kernel.cpp

// 这里给显存地址(0xb8000)写数据即可
void printf(char* str){
    static 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 system_constructors(){
    for(constructor* i= &start_ctors; i != &end_ctors; i++){
        (*i)();
    }
}

 
// warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
// 这是由于下面定义方法是C, 使用extern "C" 表示是C语言
// void kernelMain(void * multiboot_structure, unsigned int magicnumber){
extern "C" void kernelMain(void* multiboot_structure, unsigned int magicnumber){ 
    printf((char*)"Hello World");
    while(1);
}
 

linker.ld

ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)

SECTIONS 
{
    . = 0x0100000;

    .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)
    }
}

loader.s

/* ; 对于BootLoader来讲, 他不知道什么是kernel, 他只按照设定位置开始运行程序, 所以我们需要将kernel程序写入到指定的位置 0x1badb002 没有原因, 太爷爷们的规定
注意: .开头不会被翻译成机器指令, 而是给汇编器一种特殊知识, 称之为汇编指示,或者委操作 */
.set MAGIC, 0x1badb002  /*GRUB魔术块*/
.set FLAGS, (1<<0 | 1<<1)  /*;GRUB标志块*/
.set CHECKSUM, -(MAGIC + FLAGS)  /*;校验块*/

/* ; Boot程序按照Mutileboot 规范来编译内核,才可以被GRUB引导 */
.section .multboot
    .long MAGIC
    .long FLAGS
    .long CHECKSUM

/*  */
.section .text /* 代码段 */

/*--ignore-unresolved-symbol_GLOBAL_OFFSET_TABLE_*/
/* 引用外部函数, 调用时候可以遍历所有文件找到该函数 
    这里之所以需要增加一个_kernel的"_" 是因为在ld时找不到函数所在, 这是因为kernel.cpp文件在经过编译之后
    已经变成了call   87 <_kernelMain+0x9>, 所以这里需要使用_kernelMain来引入
    查看命令 objdump -d kernel.o
*/
.extern _kernelMain 
.extern _system_constructors /* 引用外部函数, 调用时候可以遍历所有文件找到该函数 */
.global loader /* .global 表示全   局可见 */
 
/* AT&T 和 Intel对寄存器使用不一样, Intel不加符号, 而At&T使用% 
    下面先把两个寄存器数据(eax, ebx)压栈, 然后调用函数 kernelMain, 并且将两个参数传递给这个函数
*/
loader: 
    mov $kernel_stack, %esp
    call _system_constructors
    push %eax 
    push %ebx 
    call _kernelMain /* 这里就是引导执行这个函数, 这个函数在kernel.cpp里面定义 */

/* 
    cli ; 将IF置0,屏蔽掉“可屏蔽中断”,当可屏蔽中断到来时CPU不响应,继续执行原指令
    hlt ; 本指令是处理器“暂停”指令。
    jmp _stop ; 命令跳转指令
 */
_stop:
    cli 
    hlt 
    jmp _stop

/* ; 未初始化变量端 */
.section .bss

/*  这个段开辟空间是2M */
.space 2*1024*1024 

/*  */
kernel_stack:

Makefile

GPPPARAMS = -m32 -Iinclude -fno-use-cxa-atexit -fleading-underscore -fno-exceptions -fno-builtin -nostdlib -fno-rtti -fno-pie

ASPARAMS = --32

LDPARAMS = -melf_i386 -no-pie

objects = loader.o kernel.o

%.o: %.cpp
    g++ ${GPPPARAMS} -o $@ -c $< 

%.o: %.s
    as ${ASPARAMS} -o $@ $<

mykernel.bin: linker.ld ${objects}
    ld ${LDPARAMS} -T $< -o $@ ${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 timeout=8' > iso/boot/grub/grub.cfg
    echo 'set default=0' >> iso/boot/grub/grub.cfg
    echo '' >> iso/boot/grub/grub.cfg
    echo 'menuentry "my 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.cfgmak
    grub-mkrescue --output=$@ iso
    rm -rf iso

 
  • 写回答

1条回答 默认 最新

  • luciferau 2022-08-07 13:20
    关注

    mutilboot

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 8月15日
  • 已采纳回答 8月7日
  • 创建了问题 8月2日

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效