上一篇讲完简述了利用grub内核引导的流程.
下面就是代码时间了. (代码用作编译出多重引导内核)
首先来看boot.S,规范上提供了范例代码,这里用NASM语法改写
global loader ; making entry point visible to linker extern kmain ; 这是kernel的入口函数 global start,_start ;默认的链接入口地址 MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries MEMINFO equ 1<<1 ; provide memory map FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header CHECKSUM equ -(MAGIC + FLAGS) ; checksum required TEMPSTACKSIZE equ 0x4000 ;16k [section .text] align 4 ;Align 32 bits boundary start: _start: multiboot_header: dd MAGIC dd FLAGS ;这个FLAGS标志,便是需要设置的,你需要到时候加载器返回给你信息 dd CHECKSUM ;如果这里使用了ELF文件格式,引导头中的一部分可以不写 multiboot_entry: mov esp, stack+TEMPSTACKSIZE ; set up the temp stack push ebx ; push Multiboot info structure push eax ;push Multiboot magic number call kmain ; call kernel prope cli loop: hlt jmp loop [section .bss] align 32 stack: ;我只是临时用的堆栈而已,切换GDT后会被抛弃 resb TEMPSTACKSIZE ; reserve 16k stack on a quadword boundary 复制代码
void kmain( void* mbd, unsigned int magic ) { if ( magic != 0x2BADB002 ) { //这里用来检测,引导头是否返回的值正确,然后用来保存各种信息. //为了简洁全部忽略 } //打印一个久违的Hello,World! unsigned char *videoram = (unsigned char *) 0xb8000; char str[]="hello world"; int i; for (i=0;i<sizeof(str);i++) { videoram[i*2] = str[i]; videoram[1] = 0x07; /* forground, background color. */ } //接下来的事情,可以随意发挥了. }
最后一步还是挺关键:我们的编译命令(编译连接脚本)
gcc -m32 kernel.c -c -fno-stack-protector
//-fno-stack-protector 这是GCC高级版本为了修改堆栈溢出问题二加入大补丁,默认GCC会开启这个功能
ld -m elf_i386 boot.o kernel.o -o kernel.img
注意:gcc fatal error: bits/predefs.h 如果出现这个错误 sudo apt-get install g++-multilib
这里我们就完成了kernel.img镜像的制作..我们迫不及待的要开始看看我们的程序是否运行正常!!
最快捷的方法,我把这个镜像文件放到了我的ubuntu的根目录,重启电脑.
出现grub2的时候不加载默认的选项,按e编辑,按F2进入命令行,输入
set root=hd0,msdos1
(这里你必须知道你的linux /根目录的分区号,我们在已存在的配置文件中可以看到这个信息,之前对一个配置文件按E的时候,可以看到)
multiboot /kernel.img (我的内核文件在/目录下)
boot
//注意grub的话,貌似命令root(0,0) 反正这一步设置根目录路径
用bochs 模拟一下这个现象,一睹为快.
看到了这番场景,是不是很愉快呢,接下来我会介绍,如何在U盘上安装grub2(grub gurb out 而且网上也有很多安装的攻略),当然我们需要linux环境这样很方便.
让我们写内核和测试更加便捷.
当然如果你对grub不是很熟悉,可以查看我的另外一篇博客,是用u盘启动自制multiboot内核,看了那篇你就知道如何启动了,
这里主要讲利用multiboot编译自己的multiboot内核
当然如果你对grub不是很熟悉,可以查看我的另外一篇博客,是用u盘启动自制multiboot内核,看了那篇你就知道如何启动了,
这里主要讲利用multiboot编译自己的multiboot内核