Autor Thema: Segmentregister nach GDT Initialisierung reseten  (Gelesen 4010 mal)

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« am: 25. June 2012, 22:23 »
Hallo,

nachdem die GDT erstellt wurde und der GDT Pointer über lgdt gesetzt wurde, müssen ja noch die Segmentregister zurückgesetzt werden.

Das geht ja mit folgendem Code:

asm volatile(
           "mov $0x10, %ax;"
           "mov %ax, %ds;"
           "mov %ax, %es;"
           "mov %ax, %ss;"
           "ljmp $0x8, $.1;"
           ".1:"
       );

Nur verstehe ich noch nicht ganz was da gemacht wird.
Also 0x10 ist ja der Offset zu dem Kernel-Datensegment.
Nachdem dieser gesetzt wurde, mache ich dann einen long jump in mein Kernel-Codesegment (wieso genau? wo läuft mein Programm weiter?)

Hier verstehe ich nicht so ganz, was die vorletzte und die letzte Zeile bzw. $.1 und .1: bedeuten.

Vielleicht kann mir ja jemand weiterhelfen.

Gruß
Klaus55


kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 25. June 2012, 22:36 »
Also 0x10 ist ja der Offset zu dem Kernel-Datensegment.
Nicht ganz, es ist ein Selektor für das Datensegment.

Zitat
Nachdem dieser gesetzt wurde, mache ich dann einen long jump in mein Kernel-Codesegment (wieso genau? wo läuft mein Programm weiter?)
Du musst alle Segmentregister neu setzen, also auch das Codesegment. cs kann man nicht direkt mit mov befüllen, sondern das geht nur über einen Far Jump.

Das Programm läuft am Sprungziel weiter. Dein Sprungziel besteht aus Segmentselektor 0x08 und Offset $.1. Das .1 ist dabei einfach nur ein Label, und zwar haben Labels in dieser Form (mit Zahlen) die Eigenschaft, dass sie lokal sind und kein extern sichtbares Symbol erzeugen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 25. June 2012, 22:42 »
Super, danke für die schnelle und ausführliche Antwort zu dieser Zeit noch!  :-)

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 26. June 2012, 20:52 »
So, habe nochmal eine Frage.

Auf dieser Seite http://www.lowlevel.eu/wiki/Global_Descriptor_Table wird diese Funktion beschrieben:

static void set_entry(int i, unsigned int base, unsigned int limit, int flags)
{
    gdt[i] = limit & 0xffffLL; // <-----
    gdt[i] |= (base & 0xffffffLL) << 16;
    gdt[i] |= (flags & 0xffLL) << 40;
    gdt[i] |= ((limit >> 16) & 0xfLL) << 48; // <-----
    gdt[i] |= ((flags >> 8 )& 0xffLL) << 52;
    gdt[i] |= ((base >> 24) & 0xffLL) << 56;
}

In dem angegebenen Beispiel wollen wir das Limit auf 0xfffff setzen. Jetzt frage ich mich aber wie das geht, denn
die Funktion bekommt ja nur einen unsigned int = 16 Bit übergeben. Das limit Feld ist aber so aufgeteilt, dass es 20 Bit umfasst.
Wenn man jetzt doch einen Rechtsshift macht, dann wird doch bei unsigned int mit 0en aufgefüllt, oder? dann wären die oberen vier Bit des
Limits aber 0 anstatt 1.

Verstehe ich das richtig oder was verstehe ich da falsch?


Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 26. June 2012, 21:14 »
Der Typ int ist beim GCC 32-Bit groß. Nur bei 16-Bit Systemen ist er 16-Bit groß.
Dieser Text wird unter jedem Beitrag angezeigt.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 29. June 2012, 17:43 »
Ich habe nochmal eine Frage zu dem ljmp.
Wenn ich mir irgendwelche instruction sets anschaue z.B. von Intel, dann finde ich immer nur ein jmp, aber kein ljmp.
Übersetzt der compiler das einfach in ein jump x:y? Wenn ja, wo finde ich eine Tabelle wo all diese Instruktionen aufgelistet sind?


Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 29. June 2012, 18:23 »
Der GCC (bzw. GNU AS) verwendet standardmäßig die AT&T Syntax. Diese Syntax folgt relativ konsistenten Regeln, deswegen gibt es keine direkte Gegenüberstellung der Mnenomics. Allerdings gibt es im AS Manual eine Seite, die die Regeln auflistet. ljmp gehört also zu den wenigen Sonderfällen, weil es einen far pointer als immediate operand hat. ljmp $x, $y ist in der Tat dasselbe wie jmp x:y.
Dieser Text wird unter jedem Beitrag angezeigt.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 01. July 2012, 13:02 »
Ich hätte jetzt nochmal eine Frage.
Also ich hab sozusagen den ersten Prototypen meines Kernels fertig. Bis jetzt habe ich ihn immer mit qemu getestet (qemu-system-x86_64 -kernel kernel).
Wie muss ich den Kernel jetzt installieren/kompilieren, damit ich ihn beim Start des Computers aus dem Boot-Menü auswählen und starten kann?
Ich verwende Linux und Grub.

Svenska

  • Beiträge: 1 790
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 02. July 2012, 06:32 »
Du trägst die Kernel-Datei in die grub.cfg ein, als "multiboot". Fertig.  :-)
Beachte, dass die Distro-Upgrades die grub.cfg dynamisch erzeugen, also musst du dich u.U. woanders umschauen, z.B. /etc/defaults/* oder /boot/grub/*.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 02. July 2012, 14:37 »
Ja, das hab ich versucht, aber es klappt nicht so ganz wie ich es mache.

Also ich hab das Tutorial durchgemacht und benutze entsprechend das makefile von dort:

SRCS = $(shell find -name '*.[cS]')
OBJS = $(addsuffix .o,$(basename $(SRCS)))

CC = gcc
LD = ld

ASFLAGS = -m32
CFLAGS = -m32 -Wall -g -fno-stack-protector -nostdinc
LDFLAGS = -melf_i386 -Tkernel.ld

INC=-I/usr/include

kernel-0.1: $(OBJS)
  $(LD) $(LDFLAGS) -o $@ $^
 
%.o: %.c
  $(CC) $(INC) $(CFLAGS) -c -o $@ $^

%.o: %.S
  $(CC) $(ASFLAGS) -c -o $@ $^
 
clean:
  rm $(OBJS)
 
.PHONY: clean

In der grub.cfg hab ich den Eintrag hinzugefügt:

Zitat
menuentry "MyKernel" {
   multiboot kernel-0.1
}


Die Datei kernel-0.1 befindet sich im übergeordneten Ordner /boot.

Den Kernel kann ich beim Start auswählen, aber dann erscheint ein Fehler: error: couldn't open file
oder so ähnlich

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 02. July 2012, 14:44 »
Eventuell musst du das multiboot-Modul von GRUB erst noch laden?

(Ja, GRUB 2 ist ein tolles Betriebssystem. Leider haben sie sich nicht die Mühe gemacht, einen anständigen Bootloader mitzuliefern...)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 02. July 2012, 14:49 »
Okay, kannst du mir sagen wie das geht oder hast du nen passenden Link dazu?

Hab noch nicht groß Erfahrung mit GRUB.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 02. July 2012, 14:55 »
Probier mal insmod multiboot. Aber ich kenne mich mit GRUB 2 auch nicht wirklich aus, bis jetzt habe ich noch überall GRUB 1 drauf.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 02. July 2012, 15:35 »
Okay, wenn ich jetzt den Kernel beim Starten auswähle, verschwindet das Menü kurz (vielleicht 5 ms oder so) und erscheint dann wieder.
Wenn ich meinen Kernel mit qemu ausführe schreibt er aber ein paar Sachen auf den Bildschirm, so wie es eigentlich sein sollte.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #14 am: 02. July 2012, 17:55 »
Hallo,
also ich verwende module [Name und Pfad des Moduls] (ohne Klammern), und das funktioniert bei mir prima und ich verwende auch GRUB2.
Ich hoffe ich konnte helfen.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 02. July 2012, 19:10 »
Hm..wie meinst du das? Kannst du mir vielleicht ein Beispiel zeigen?

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #16 am: 02. July 2012, 20:15 »
Hier ist ein Beispiel. Dabei wird der Kernel gebootet und das Modul "tastaturtreiber" wird geladen. Ich hoffe du hast das so gemeint mit
...Kannst du mir vielleicht ein Beispiel zeigen?
set timeout=10
set default=0

menuentry "OS"{
multiboot /kernel
module /tastaturtreiber
boot
}
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

oern

  • Beiträge: 44
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 02. July 2012, 21:42 »
Mit Multiboot-Modul ist gemeint, dass GRUB2 selber modularisiert ist. Die Fähigkeit, Multibootkernel zu laden ist dort in ein Modul namens multiboot ausgelagert, und das kann man wie taljeth schon sagte mit "insmod multiboot" irgendwo oben in der grub.cfg laden.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #18 am: 02. July 2012, 22:02 »
Also bei mir funktioniert das mit "multiboot kernel" super. Ich wüsste nicht warum man es dann noch als zusätzliches Modul laden muss.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

klaus55

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 02. July 2012, 22:48 »
Vielen Dank für eure Hilfe! Es funktioniert jetzt.
Das Problem war, dass ich nur

menuentry "My Kernel" {
multiboot kernel-0.1
}

angegeben habe. Richtig ist aber
menuentry "My Kernel" {
multiboot /boot/kernel-0.1
}

Also ich hab das Verzeichnis nicht richtig angegeben. Wenn ich

menuentry "My Kernel" {
insmod multiboot kernel-0.1
}

mache kommt keine Fehlermeldung, aber er läd den Kernel auch nicht.

Naja, ich bin froh, dass es jetzt funktioniert  :-)

Danke nochmal an alle! Ist echt super, dass immer so schnell Leute antworten, auch wenn es so aussieht, als wär hier nicht viel los.

Edit: Und ich hab jetzt auch endlich verstanden wofür das multiboot gut ist.  :-)

 

Einloggen