Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: unsknown spammer am 29. October 2008, 19:50
-
Hallo erstmal!
Ich boote meinen Kernel ueber grub.
Dann lade ich meine eingene gdt.
Wenn ich das image jetzt unter bochs boote macht der direkt einen restart!
Auszug der Logfile:
00011998349i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00011998349i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00011998349i[CPU0 ] | DS:0010( 0002| 0| 0) ffffffff 000fffff 1 1
00011998349i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00011998349i[CPU0 ] | ES:0010( 0002| 0| 0) ffffffff 000fffff 1 1
00011998349i[CPU0 ] | FS:0010( 0002| 0| 0) ffffffff 000fffff 1 1
00011998349i[CPU0 ] | GS:0010( 0002| 0| 0) ffffffff 000fffff 1 1
DIe Base wird falsch gesetzt!
Ausserdem wird ein anderes limit genommen als ich angegeben habe!
Ich sehe da einfach keinen fehler!
typedef struct gdt_entry{
WORD size0_15;
WORD base0_15;
BYTE base16_23;
BYTE access;
BYTE size16_19;
BYTE base24_31;
}gdt_entry;
typedef struct gdt_ptr{
WORD limit;
DWORD base;
}gdt_ptr;
gdt_ptr pgdt;
gdt_entry gdt[MAX_GDT_ENTRYS];
void init_gdt(){
WORD itemp=0;
//deskriptoren auf 0 setzen
for(itemp=0;itemp<MAX_GDT_ENTRYS;itemp++){
memset((BYTE*)&gdt[itemp],0,sizeof(gdt_entry));
}
//code deskriptor setzen
if(0!=set_gdt(1,0xFFFFF,0,GDT_DATA|GDT_CODE|GDT_PRESENT))return;
//daten deskriptor setzen
if(0!=set_gdt(2,0xFFFFF,0,GDT_DATA|GDT_PRESENT))return;
//limit und base der gdt speichern
pgdt.limit=MAX_GDT_ENTRYS*8 - 1;
pgdt.base=gdt;
//gdt laden und segmentregister aktualisieren
load_gdt();
}
void load_gdt(){
if(pgdt.limit!=0&&pgdt.base!=0){
asm("lgdt %0" : : "m" (pgdt));
//asm("jmp $0x8,$1f;1:");
asm("mov $0x10,%eax");
asm("mov %eax,%ds");
asm("mov %eax,%es");
asm("mov %eax,%fs");
asm("mov %eax,%gs");
//asm("mov %eax,%ss");
}
}
WORD set_gdt(WORD nr,DWORD size,DWORD base,BYTE access){
if(nr>=MAX_GDT_ENTRYS||nr==0)return 1;
gdt[nr].size0_15=size&0xFFFF;
gdt[nr].size16_19=((size>>16)&0xF)|0x80|0x40;
gdt[nr].base0_15=base&0xFFFF;
gdt[nr].base16_23=(base>>16)&0xFF;
gdt[nr].base24_31=(base>>24)&0xFF;
gdt[nr].access=access;
return 0;
}
-
typedef struct gdt_entry{
WORD size0_15;
WORD base0_15;
BYTE base16_23;
BYTE access;
BYTE size16_19;
BYTE base24_31;
} __attribute__ ((packed)) gdt_entry;
typedef struct gdt_ptr{
WORD limit;
DWORD base;
} __attribute__ ((packed)) gdt_ptr;
Ersetz mal deine Structs damit. Bei deinen wird eventuell aligned und dann funktioniert das natürlich nicht mehr.
Ich frage mich außerdem wieso du den structs einen Namen gibst, wenn du ihnen sowieso einen Typnamen zuweist.
-
Danke erstmal!
Ich bin auf einen anderen Compiler umgestiegen!
Mein alter Compiler hat da anscheinend nicht aligned!
Wieso ich den structs namen gebe?
Das habe ich noch von der zeit uebernommen als ich noch nicht mit typedef gearbeitet habe!
Jetzt bekomme ich allerdings eine Exception beim neuladen der Segment-Register:
00012122274i[CPU0 ] >> mov ds, ax : 8ED8
00012122274e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
-
Danke erstmal!
Ich bin auf einen anderen Compiler umgestiegen!
Mein alter Compiler hat da anscheinend nicht aligned!
Wieso ich den structs namen gebe?
Das habe ich noch von der zeit uebernommen als ich noch nicht mit typedef gearbeitet habe!
Jetzt bekomme ich allerdings eine Exception beim neuladen der Segment-Register:
00012122274i[CPU0 ] >> mov ds, ax : 8ED8
00012122274e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Da ist irgendein Fehler im Deskriptor und du bist an dem Punkt wo man so gut wie gar nicht debuggen kann. Viel Spaß beim suchen ;)
-
Wie sehen denn die Definitionen aus?
(MAX_GDT_ENTRYS, GDT_DATA, ...)
Des Weiteren berechnet sich das limit meinem Wissensstand nach sie folgt (vorrausgesetzt, MAX_GDT_ENTRYS ist kein Macro für die Größe der struktur):
((Größe der Struktur) * Anzahl der Einträge) -1
Dann ist mir noch aufgefallen, dass du im gdt zeiger die Adresse zur GDT speichern musst:
// Anstatt folgendem:
pgdt.base=gdt;
// sollte es heißen:
pgdt.base=(DWORD)&gdt;
Das ist, was mir so auf den ersten Blick aufgefallen ist. Hier noch ein Link zu einem Tutorial, in dem die GDT auch in C implementiert wird: http://osdever.net/bkerndev/Docs/gdt.htm
Ich schreibe diesen Link, damit du einen alternativen Weg siehst, wie man das einbauen kann. Da es ein Teil eines Tutorials ist, kann man dies auch übernehmen.
*EDIT*
Eines noch: Nach dem du die GDT mit lgdt geladen hast, muss ein Sprung zum Codesegment gemacht werden.
-
((Größe der Struktur) * Anzahl der Einträge) -1
Das macht er doch( Größe der Struktur = 8 )
Dann ist mir noch aufgefallen, dass du im gdt zeiger die Adresse zur GDT speichern musst:
// Anstatt folgendem:
pgdt.base=gdt;
// sollte es heißen:
pgdt.base=(DWORD)&gdt;
gdt ist ein array, das erstere ist also (auch) richtig
@unsknownspammer
falls du den bochs-debugger verwendest, könnte ein 'info gdt' nach dem 'lgdt' hilfreiche informationen liefern
-
Danke erstmal fuer die antworten!
Ich habe den Fehler gefunden und zwar habe ich das Segment-Bit nicht auf 1 gesetzt!
Jetzt laeuft der Kernel!
Kann mir mal jemand erklaeren wofuer das Segment-Bit da ist?
-
Das Segment-Bit liefert der CPU informationen darüber, ob es sich bei dem jeweiligen Descriptor um ein Segment-Descriptor oder ein System-Descriptor( z.B. Gate-Descriptoren) handelt.
Je nach dem wird dann das Typ-Feld anders Interpretiert.