使用 grub 引导汇编编写的内核
Posted
技术标签:
【中文标题】使用 grub 引导汇编编写的内核【英文标题】:Booting assembly written kernel with grub 【发布时间】:2014-05-12 13:08:50 【问题描述】:我知道,对于这么小的简单内核,我实际上并不需要使用 GRUB 来引导它,但我正在尝试在我的内核变大之前学习如何做到这一点,我需要引导它。我使用 OSDev.org 上的实模式汇编教程编写了一个带有汇编的简单内核。我试图启动它,但 GRUB 给了我一个错误,即它找不到多启动标头。我查看了 C Bare Bones 教程的汇编代码。我是否只需将所有内容都放在 .multiboot 部分中?你能告诉我如何启动这段代码吗? (这段代码不是我创造的,我把代码留在家里的机器上,现在在学校,我只是从 OSDev 借来的,所以请不要给我任何卑鄙的 cmets 说我偷了别人的代码。)
; boot.asm
mov ax, 0x07c0
mov ds, ax
mov si, msg
ch_loop:lodsb
or al, al ; zero=end or str
jz hang ; get out
mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
我可以使用 Bios 启动和打印还是使用堆栈?
;====================================
[ORG 0x7c00] ; add to offsets
xor ax, ax ; make it zero
mov ds, ax ; DS=0
mov ss, ax ; stack starts at 0
mov sp, 0x9c00 ; 200h past code start
mov ax, 0xb800 ; text video memory
mov es, ax
mov si, msg ; show text string
call sprint
mov ax, 0xb800 ; look at video mem
mov gs, ax
mov bx, 0x0000 ; 'W'=57 attrib=0F
mov ax, [gs:bx]
mov word [reg16], ax ;look at register
call printreg16
hang:
jmp hang
----------------------
dochar: call cprint ; print one character
sprint: lodsb ; string char to AL
cmp al, 0
jne dochar ; else, we're done
add byte [ypos], 1 ;down one row
mov byte [xpos], 0 ;back to left
ret
cprint: mov ah, 0x0F ; attrib = white on black
mov cx, ax ; save char/attribute
movzx ax, byte [ypos]
mov dx, 160 ; 2 bytes (char/attrib)
mul dx ; for 80 columns
movzx bx, byte [xpos]
shl bx, 1 ; times 2 to skip attrib
mov di, 0 ; start of video memory
add di, ax ; add y offset
add di, bx ; add x offset
mov ax, cx ; restore char/attribute
stosw ; write char/attribute
add byte [xpos], 1 ; advance to right
ret
;------------------------------------
printreg16:
mov di, outstr16
mov ax, [reg16]
mov si, hexstr
mov cx, 4 ;four places
hexloop:
rol ax, 4 ;leftmost will
mov bx, ax ; become
and bx, 0x0f ; rightmost
mov bl, [si + bx];index into hexstr
mov [di], bl
inc di
dec cx
jnz hexloop
mov si, outstr16
call sprint
ret
;------------------------------------
xpos db 0
ypos db 0
hexstr db '0123456789ABCDEF'
outstr16 db '0000', 0 ;register value string
reg16 dw 0 ; pass values to printreg16
msg db "What are you doing, Dave?", 0
times 510-($-$$) db 0
db 0x55
db 0xAA
;==================================
提前谢谢你。
【问题讨论】:
我很抱歉代码的格式是我在论坛上的第一个编码问题 【参考方案1】:如果您想编写实模式内核(16 位),则不能使用 GRUB。 GRUB 只能加载 32 位内核。
您应该考虑一个事实,即不能简单地在 32 位模式下使用 BIOS 中断。
MultiBoot 规范 (http://www.uruk.org/orig-grub/boot-proposal.html) 描述了 GRUB 所需的文件格式。
这对初学者来说绝对不是什么...
如果您想在没有 GRUB 的情况下启动内核(并且您的操作系统大于 510 字节),您的启动扇区必须使用中断 0x13 从磁盘加载操作系统的其余部分。
此时电脑运行在16位实模式下。
【讨论】:
Linux 以实模式启动 here【参考方案2】:通过多重引导,您的内核以保护模式启动,here。
‘CR0’位 31 (PG) 必须清零。必须设置位 0 (PE)。其他位 都是未定义的。
Grub 可以引导 16 位内核,因为 Linux 以 16 位 here 启动。但为了方便起见here 用于 Linux、FreeBSD、NetBSD 和 OpenBSD。还有here
不支持 Multiboot 且没有 GRUB 中的特定支持(特定支持可用于 Linux, FreeBSD、NetBSD 和 OpenBSD)必须是链式加载的,这涉及 加载另一个引导加载程序并以实模式跳转到它。
【讨论】:
以上是关于使用 grub 引导汇编编写的内核的主要内容,如果未能解决你的问题,请参考以下文章
为 HP 瘦客户端编译自定义内核并使用 grub 创建可引导 ISO