Autor Thema: Sprung in den C-Kernel  (Gelesen 6574 mal)

Snake707

  • Beiträge: 20
    • Profil anzeigen
    • Spezi-OS
Gespeichert
« am: 22. July 2007, 20:42 »
Hallo,

ich will einen Kernel in C schreiben (bzw, schreibe schon), allerdings weiß ich nicht, wie ich zum Einsprungpunkt komme. Mein Bootloader lädt den Kernel an eine bestimmte Stelle im Speicher und geht dann in den Protected Mode um dann zum Kernel zu springen. Nur weiß ich nicht wie ich dort zur Main springen kann?

mfg Snake707
SpeziOS und meine Freundin sind leider unvereinbar. Schade. Obwohl sie auch auf die Spezi geht. Nunja Chemiker und Biologen.

Physik ist nach wie vor die wichtigste Wissenschaft

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 22. July 2007, 21:47 »
welcher Compiler/Linker/Assembler? Wo ist das Problem? Was hast du schon probiert? :roll:

Code in intelsyntax:
extern main ; oder auch extern _main je nach compiler(einstellung)
pmode:
   call main ; oder auch _main, je nach compiler(einstellung)
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Snake707

  • Beiträge: 20
    • Profil anzeigen
    • Spezi-OS
Gespeichert
« Antwort #2 am: 22. July 2007, 22:28 »
hi

gcc, ld, nasm
aber gibt es da nicht so eine crt0 Funtion?

Also um vllt Missverständnissen aus dem Weg zu gehen. Der Bootloader, soll den Kernel von Diskette laden und in den pm gehen. Soweit nicht so schwer. Es ist ein C-Kernel. Frage: Da Bootlader und Kernel getrennt sind, woher soll der Bootloader dann wissen wo sich die main Funktin befindet? Das ist mir schleierhaft.
« Letzte Änderung: 22. July 2007, 22:42 von Snake707 »
SpeziOS und meine Freundin sind leider unvereinbar. Schade. Obwohl sie auch auf die Spezi geht. Nunja Chemiker und Biologen.

Physik ist nach wie vor die wichtigste Wissenschaft

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 22. July 2007, 23:26 »
Das kommt wohl auf das Binärformat deines Kernels an. Wenn es flache Binaries sind, mußt du es einfach wissen (zu empfehlen wäre dann wohl, daß es einfach vorne losgeht). Bei ELF kannst du den Entrypoint aus der Datei auslesen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #4 am: 23. July 2007, 00:23 »
Bei ELF binaries wäre es aber nicht mit dem auslesen des entrypoint getan ;) Da muss man schon noch die ganzen Segmente durchgehen, richtig in den speicher kopieren... Falls du das vorhast würd ich dir wirklich grub nahe legen.
Du kannst auch die ersten 4byte deiner Datei dazu hernehmen die Adresse des entrypoint zu speichern. Damit das dann wirklich am Anfang der Datei landet musst du das halt in ne extra section packen und dein Linkerscript entsprechend anpassen,

btw. für Diskussionen gibts im Wiki zu jedem Artikel ne Diskussionsseite (falls das immernoch unklar ist). :-)
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Snake707

  • Beiträge: 20
    • Profil anzeigen
    • Spezi-OS
Gespeichert
« Antwort #5 am: 23. July 2007, 02:17 »
GRUB wäre eine Variante;
ich würde mich aber trotzdem gerna an einem eigenen Bootloader versuchen :P;

also ich habe jetzt noch immer keinen Anhaltspunkt^^

kennt jemand ein gutes Tutorial zu Linkerscripts? Damit hatte ich bisher noch nicht viel zu tun.
« Letzte Änderung: 23. July 2007, 02:19 von Snake707 »
SpeziOS und meine Freundin sind leider unvereinbar. Schade. Obwohl sie auch auf die Spezi geht. Nunja Chemiker und Biologen.

Physik ist nach wie vor die wichtigste Wissenschaft

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 23. July 2007, 09:52 »
Hi

du must beim linken deines C codes darauf auchten, das dein einsprungspunkt an eine bestimmte stelle gelinkt wird. Als ausgabe muss eine flat binary rauskommen. Der einsprung muss dabei nicht umbedingt main heissen.

wie das im einzelnen genau geht, ist linker abhängig. Bei properitären compilern aus dem embedded bereich kann man sowas bereits im code ngeben __root const   CPU_INT32U   FLASH_MARKER @ 0x104FF800 = 0xAA55AA55; (IAR für arm) oder über compilerschalter bzw. Linker dateien, die man als parameter übergibt.

gruss

Snake707

  • Beiträge: 20
    • Profil anzeigen
    • Spezi-OS
Gespeichert
« Antwort #7 am: 23. July 2007, 10:22 »
Ok, ich habe jetzt einfach mal nur Bahnhof verstanden. Vielleicht wäre es einfacher, wenn ich mich erstmal mit dem Linker auseinandersetze. Da habe ich nämlich noch gar keine Ahnung. Soll ich da die man pages von ld verwenden? Oder kennt jemand zufällig ein gutes Tutorial.
Das wäre auch sehr nützlich, weil ich die Makefiles noch schreiben will.

mfg Snake707
SpeziOS und meine Freundin sind leider unvereinbar. Schade. Obwohl sie auch auf die Spezi geht. Nunja Chemiker und Biologen.

Physik ist nach wie vor die wichtigste Wissenschaft

Cheebi

  • Beiträge: 91
    • Profil anzeigen
    • Cheebis Webseite
Gespeichert
« Antwort #8 am: 24. July 2007, 11:57 »
hey,

pass auf, probier einfach folgendes und versuch beim coden nachzuvollziehen, was genau passiert:

du hast einen bootloader, der den kernel lädt und dann in den pm springt. das sieht in etwa so aus:

;boot.asm

[BITS16]
org 0x7c00

start:
         ...; hier steht der code, der dir den kernel an eine bestimmte adresse lädt
         ...; du musst dabei darauf achten, dass du dir vorher überlegst, wohin du den kernel laden willst
         ...; sagen wir du hättest dir die lineare adresse  0x20000 ausgesucht
         ;
         ; so, jetzt steht der kernel bei 0x20000
         ; jetzt musst du in den pm schalten
         ;
         lgdt ...
         mov         eax, cr0
         or         eax, 1
         mov         cr0, eax
         jmp         0x8 : pmode
         ;
         ; das müsstest du ja soweit implementiert haben

[BITS32]
pmode:
         mov         eax, 0x10
         mov         ds, eax
         mov         es, eax
         mov         ss, eax
         mov         gs, eax
         mov         fs, eax
         mov         esp, stack_size

         ; na das kennst ja alles
         ; soooo

         ; das tolle ist, dass du weißt, wo dein kernel liegt. du hast ihn ja nach 0x20000 geladen
         ; da springen wir nun hin...
         jmp         0x8 : 0x20000
         ;
         ; fertig

jetzt brauchst du noch einen kernel...

// kernel.c

void main()
{
  // welcome
  for(;;);
}

jetzt noch etwas, das nicht unbedingt notwendig ist, aber manchmal ganz nützlich ist...

; asm32.asm

[BITS 32]

[global _stopsystem]
[extern _main]

_start:
         call         _main

_stopsystem:
         cli
         hlt

jetzt musst du nur noch gucken, wie das alles zusammen gehört.
also den bootlader assemblierst du ganz normal mit nasm:

   nasm -f bin -o boot.bin boot.asm

boot.bin schreibst in sektor null...

asm32.asm musst du anders assemblieren:

   nasm -f aout -o asm32.o asm32asm

jetzt hast du die erste objekt-datei asm32.o
den kernel kompilierst du so:

   gcc -ffreestanding -c -o kernel.o kernel.c

jetzt hast du die zweite objekt-datei.
um alles zusammen zu linken, brauchst du noch eine sogenannte linker-file:

OUTPUT_FORMAT("binary")
INPUT(asm32.o kernel.o)
ENTRY(_start)
SECTIONS
{
  .text  0x20000 : {
    *(.text)
  }
  .data  : {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}
die datei erklärt sich ja sogut wie von selbst... wenn nicht, fragen!

das ganze muss nur noch gelinkt werden:

   ld -T link.ld -o kernel.bin

nach diesem befehl hast du eine datei namens kernel.bin, die der bootloader laden kann...

da du in der link.ld die reihenfolge INPUT(asm32.asm kernel.o) hast, ist der allererste befehl in kernel.bin "jmp _main"... dadurch ist sichergestellt, dass selbst wenn _main nicht ganz vorne anfängt, trotzdem der kernel-code aufgerufen wird.

gruß

Cheebi

ps: meld dich, wenns funktioniert... hab den code jetzt nicht getestet...
0100 1001 0100 1100 0100 0001 0010 0000 0011 1010 0010 1101 0010 1010
http://www.cheebi.de

 

Einloggen