使用Multiboot规范编写loader.s

BootLoader是一段汇编代码,文件名为loader.s,它需要按照Multiboot规范来编译内核才可以被GRUB引导。
按照Mutileboot规范,内核必须在起始的8KB中的包含一个多引导项头(Multiboot header),里面必须包含3个4字节对齐的块:这个多引导项头里面必须有3个4字节对齐的块。

一个魔术块:包含了魔数[0x1BADB002],是多引导项头结构的定义值。
一个标志块:我们不关心这个块的内容,我们简单设定为0。
一个校检块:校检块,魔术块和标志块的数值的总和必须是0。

我们在loader.s中定义他们
image.png

.set MAGIC, 0x1badb002;                 # 魔数块
.set FLAGS, (1<<0 | 1<<1);              # 标志块<br />.set CHECKSUM, -(MAGIC + FLAGS);        # 校验块

下面的伪指令声明了Multiboot标准中的多引导项头
三个块都是32位字段

.section .multiboot
.long MAGIC//long即是4字节
.long FLAGS
.long CHECKSUM

在多引导项头之后,是程序的入口点。kernel的代码在文件kernel.cpp中,loader.s在入口点中跳转到kernel.cpp的函数中执行。首先需要使用.global伪指令告诉链接器程序的入口点,用loader表示,最后是stop代码。

kernel.cpp中主函数的名称是kernelMain,需要传入两个参数,分别是BootLoader的地址和魔数,它们存放于寄存器%eax和%ebx中,将它们压栈以传递参数。kernelMain是一个外部符号,需要提前在loader.s中声明,这些外部符号存在于.text段中。同样地,为了使得loader函数对外部可见,使用.global伪指令向外暴露loader。

.section .multiboot
    # ...
    .long CHECKSUM

.section .text
.extern kernelMain
.global loader

loader:
    push %eax       # bootloader's address in %eax
    push %ebx       # magic number in %ebx
    call kernelMain

stop:
    # 禁用中断
    cli
    # 禁用中断后使用hlt暂停CPU,以后无法再唤醒
    hlt
    jmp stop

标签: none

评论已关闭