内核引导的捷径(代码)

上一篇讲完简述了利用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
复制代码

接着就应该是kernel.c 文件了.
 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环境这样很方便.

  让我们写内核和测试更加便捷.

内核引导的捷径(代码)_第1张图片




当然如果你对grub不是很熟悉,可以查看我的另外一篇博客,是用u盘启动自制multiboot内核,看了那篇你就知道如何启动了,

这里主要讲利用multiboot编译自己的multiboot内核




当然如果你对grub不是很熟悉,可以查看我的另外一篇博客,是用u盘启动自制multiboot内核,看了那篇你就知道如何启动了,

这里主要讲利用multiboot编译自己的multiboot内核

你可能感兴趣的:(kernel,bootloader)