assembly - meaty - Kernel simple no se iniciarĂ¡ en GRUB
osdev cross compiler (1)
+1 para una buena pregunta con todos los detalles, gracias.
Al menos en mi máquina el kernel.bin
generado sale como 4869 bytes, que solo cabe en 10 sectores, no 9. Además, la memoria de texto VGA está en 0xb8000
no en 0xb800
(uno más cero - 0xb800
es el segmento de modo real, tiene que ser multiplicado por 16). Con esos pequeños ajustes funciona bien aquí.
Estoy aprendiendo un poco de desarrollo de SO de OSDev.org . Tengo un kernel y estoy tratando de arrancar en GRUB Legacy (0.97) usando qemu. Sin embargo, cuando escribo kernel 200+9
, obtengo el mensaje
[Multiboot-elf, <0x100000:0x80:0x4008>(bad), entry=0x10000c]
Esto es lo que espero, excepto la parte (mala). Si escribo boot
ahora GRUB simplemente cuelga.
Creo que los números 0x100000, 0x44, 0x4008 representan la dirección de inicio del segmento .text, la dirección de inicio .bss y el tamaño de la sección .bss, respectivamente. Creo que esto porque ejecutar objdump -h
en la imagen del núcleo da esta salida:
kernel.bin: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000044 00100000 00100000 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .bss 00004008 00100044 00100044 00001044 2**2
ALLOC
Entonces puedes ver que los números que mencioné casi coinciden. El problema es que en lugar de 100044, el comienzo de .bss es solo 44. Y creo que esta es la razón por la que GRUB dice mal. No puedo tener una sección por debajo de 1 MB en memoria (memoria baja). Pero objdump me dice que mis secciones están por encima de ese umbral, así que no sé qué sucede. De todos modos, pegaré mi código a continuación, es relativamente corto. Aunque mi pregunta es probablemente muy básica si ya has hecho el desarrollo del sistema operativo antes, entonces el código podría ser extraño.
;loader.s - contains the multiboot header for grub and calls the main kernel method
global loader ; making entry point visible to linker
global magic ; we will use this in kmain
global mbd ; we will use this in kmain
extern kmain ; kmain is defined in kmain.cpp
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ 0x03;MODULEALIGN | MEMINFO ; this is the Multiboot ''flag'' field
MAGIC equ 0x1BADB002 ; ''magic number'' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
section .text
loader:
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that''s 16k.
mov esp, stack + STACKSIZE ; set up the stack
mov [magic], eax ; Multiboot magic number
mov [mbd], ebx ; Multiboot info structure
call kmain ; call kernel proper
cli
.hang:
hlt ; halt machine should kernel return
jmp .hang
section .bss
align 4
stack: resb STACKSIZE ; reserve 16k stack on a doubleword boundary
magic: resd 1
mbd: resd 1
.
// kernel.c - Contains the main kernel method
void kmain() {
extern unsigned int magic;
if (magic != 0x2BADB002) {
// Something went wrong
}
volatile unsigned char *videoram = (unsigned char *) 0xB800;
videoram[0] = 65;
videoram[1] = 0x07;
}
A continuación está mi script del enlazador personalizado:
ENTRY (loader)
SECTIONS {
. = 0x00100000;
.text ALIGN (0x1000) : {
*(.text)
}
.rodata ALIGN (0x1000) :
{
*(.rodata*)
}
.data ALIGN (0x1000) :
{
*(.data)
}
.bss :
{
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.comment)
}
}
Y finalmente, construyo el kernel con las siguientes líneas:
nasm -f elf -o loader.o loader.s
gcc -c -o kernel.o kernel.c
ld -T linker.ld -o kernel.bin loader.o kernel.o
cat stage1 stage2 pad kernel.bin > floppy.img
Donde stage1 y stage2 son archivos de GRUB Legacy y pad es cualquier archivo de 750 bytes (entonces stage1 + stage2 + pad tiene un tamaño de archivo de 102400 bytes, o 200 bloques, por eso reinicio con kernel 200 + 9).
Finalmente, ejecuto el kernel en qemu:
qemu-system-x86_64 -fda floppy.img