Hallo,
Ich hab ein Problem:
Mein Kernel läuft und bin auch schon recht weit (PMM,VMM usw läuft).
Allerdings momentan noch als Lowerhalf kernel.
Jetzt wollte ich ihn so umschreiben das er ein Higherhalf kernel ist, weil mir das besser gefällt und ja auch ne menge Vorteile hat.
Ich hab mir dazu ein neues Projekt erstellt, das mir mit dem GDT Trick meinen Kernel an 0xC0000000 mapped und in die Init funktion springt.
Siehe auch hier:http://wiki.osdev.org/Higher_Half_With_GDT
Meine C init ist noch leer (dauerschleife) aber das ändert sich noch.
Nutze ich den ASM Code 1:1 funktioniert das auch perfekt.
Der Kernel startet, übernimmt die GDT und springt in meine Mainfunktion, wo er in einer endlos schleife stoppt (wie beabsichtigt).
Das Problem ist nun das der ASM teil in NASM Syntax ist, der Rest meines Kernels aber in GNU AS syntax.
Versuche ich nun den code in gas syntax zu ändern stürzt das program mit einem Triple fault ab.
Original Code:
[BITS 32] ; 32 bit code
[section .text] ; keep NASM happy
[global start] ; make 'start' function global
[extern init] ; our C kernel main
; Multiboot constants
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
; Multiboot header (needed to boot from GRUB)
ALIGN 4
multiboot_header:
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; the kernel entry point
start:
; here's the trick: we load a GDT with a base address
; of 0x40000000 for the code (0x08) and data (0x10) segments
lgdt [trickgdt]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; jump to the higher half kernel
jmp 0x08:higherhalf
higherhalf:
; from now the CPU will translate automatically every address
; by adding the base 0x40000000
mov esp, sys_stack ; set up a new stack for our kernel
call init ; jump to our C kernel ;)
; just a simple protection...
jmp $
[global gdt_flush] ; make 'gdt_flush' accessible from C code
[extern gp] ; tells the assembler to look at C code for 'gp'
; this function does the same thing of the 'start' one, this time with
; the real GDT
gdt_flush:
lgdt [gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
[section .setup] ; tells the assembler to include this data in the '.setup' section
trickgdt:
dw gdt_end - gdt - 1 ; size of the GDT
dd gdt ; linear address of GDT
gdt:
dd 0, 0 ; null gate
db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x40 ; code selector 0x08: base 0x40000000, limit 0xFFFFFFFF, type 0x9A, granularity 0xCF
db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x40 ; data selector 0x10: base 0x40000000, limit 0xFFFFFFFF, type 0x92, granularity 0xCF
gdt_end:
[section .bss]
resb 0x1000
sys_stack:
; our kernel stack
Mein übersetzungsversuch:
.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x0
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)
// Der Multiboot-Header
.align 4
.int MB_MAGIC
.int MB_FLAGS
.int MB_CHECKSUM
.section .text
.global start
.extern init
start:
cli
lgdt trickgdt
mov 0x10,%ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
jmp higherhalf
higherhalf:
mov sys_stack, %esp
call init;
protection:
cli
hlt
jmp protection
.global gdt_flush
.extern gp
gdt_flush:
lgdt gp
mov 0x10,%ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
jmp flush2
flush2:
ret
.section .setup
trickgdt:
.short (gdt_end - gdt -1)
.int gdt
gdt:
# Null gate
.quad 0
# Code segment
.byte 0xff
.byte 0xff
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0b10011010
.byte 0b11001111
.byte 0x40
# Data segment
.byte 0xff
.byte 0xff
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0b10010010
.byte 0b11001111
.byte 0x40
gdt_end:
.section .bss
# Kernel stack
.space 0x1000
sys_stack:
Der Code kompiliert problemlos, allerdings stürzt das Program beim neuladen des ds registers in start (mov %ax, %ds) mit einem General protection fault ab (der wiederum nicht abgefangen wird, da die IDT ja nicht eingerichtet is -->Double fault ---> Triple fault).
Kann vielleicht mal einer drüberschauen was ich falsch mache ?
Meiner Meinung nach liegt das Problem entweder beim definieren der gdt oder beim laden der gdt (lgdt trickgdt), aber weiter weis ich nicht.
Ich hab auch schon gegoogelt, konnte aber nichts finden und bin auch nach 2 abenden probieren nicht auf eine lösung gestoßen, weshalb ich mich nun an euch wende.
Vielleicht kann ja mal einer der bei syntaxe kennt drüber schauen und mir sagen was ich falsch mache.
Mit freundlichen Grüßen,
Thalhammer