如何使用int 13h在0x100000加载内核(并跳转到该内核)?

时间:2019-01-31 20:49:57

标签: assembly x86 boot bootloader

我已经用C编写了内核,并且有一段汇编代码可以调用其主要功能。汇编代码如下:

bits 32
section .text
    align 4
    dd 0x1BADB002            ;magic
    dd 0x00                  ;flags
    dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero

global start
extern kmain ;kmain is defined in the c file

start:
    cli ;block interrupts
    mov ebp, stack_space
    mov esp, ebp ;set stack pointer
    call kmain ; C "kmain" void
    hlt ;halt the CPU

section .bss
resb 8192       ;8KB for stack
stack_space:

这就是我编译所有内容的方式:

sudo nasm -f elf kernel.asm -o kasm.o
sudo gcc -m32 -c kernel.c -o kc.o
sudo ld -m elf_i386 -T link.ld -o kernel.bin kasm.o kc.o

我的link.ld文件是这样的:

OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
    . = 0x100000;
    .text : { *(.text) }
    .data : { *(.data) }
    .bss  : { *(.bss)  }
}

我搜索了很多有用的东西,然后在StackOverflow上找到了一个帖子,这个引导加载程序在0x1000处加载了内核:

[org 0x7c00]

KERNEL_OFFSET equ 0x1000

call load_kernel

;Switch PM
cli
lgdt [gdt_descriptor]

mov eax, cr0
or eax, 0x1
mov cr0, eax

jmp 0x8:init_pm

[bits 32]
init_pm :
   mov ax, 0x10
   mov ds, ax
   mov ss, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   mov ebp, 0x90000
   mov esp, ebp

   call KERNEL_OFFSET
   jmp $

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[bits 16]

load_kernel:
   mov bx, KERNEL_OFFSET
   mov dh, 15
   mov dl, 0

   mov ah, 0x02
   mov al, dh
   mov ch, 0x00
   mov dh, 0x00
   mov cl, 0x02
   int 0x13
   ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[bits 16]

GDT:
;null :
   dd 0x0
   dd 0x0

;code :
   dw 0xffff      ;Limit
   dw 0x0         ;Base
   db 0x0         ;Base
   db 10011010b    ;1st flag, Type flag
   db 11001111b    ;2nd flag, Limit
   db 0x0         ;Base

;data :
   dw 0xffff      
   dw 0x0         
   db 0x0
   db 10010010b
   db 11001111b
   db 0x0

gdt_descriptor :
   dw $ - GDT - 1       ;16-bit size
   dd GDT            ;32-bit start address

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
times 510 -($-$$) db 0
dw 0xaa55

但是,我不能将KERNEL_OFFSET的值更改为0x100000,因为它对于dx寄存器来说太大了。如何在0x100000加载内核并跳转到内核?

PS:我想尽可能避免GRUB,因为我想了解自己在做什么。 任何帮助表示赞赏。谢谢。

编辑:我没有显示内核的源代码,因为它无关紧要。当我使用-kernel参数(qemu -kernel mykernel)启动Qemu时,它确实起作用

0 个答案:

没有答案