Autor Thema: Einfach nur ?  (Gelesen 8513 mal)

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« am: 28. November 2006, 19:26 »
Ich weiß echt nicht was ich falsch gemacht habe... wirklich nicht...
Es scheint so als ob alle Interrupts falsch ankommen. Das ist aber auch alles was ich herausfinden konnte.
Was passiert ist folgendes: Sobald ich anschalte, gibt es keinen Exception error. Das ist in diesem fall nicht gut, da die IRQ's nicht gemappt waren. Danach habe ich die IRQ's gemappt, aber nun werden die nicht ausgeführt. Irgendwas läuft da ganz falsch, ich kann's nicht mal beschreiben.
Ich poste hier mal den link zum source, mit Floppy image. Ich wäre wirklich sehr, sehr dankbar wenn sich dann doch jemand die Mühe machen würde und mal einen Blick drauf werfen würde. (Leider größtenteils unkommentiert)
http://scanish.dyndns.org/scen/kernel.zip
Vielen Dank für eure Aufmerksamkeit!

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #1 am: 28. November 2006, 20:34 »
STI is benutzt, und der klartext fehlt weil ich selber nicht den Durchblick habe was da los is...

[edit]Also im klartext: Die IRQ's waren nicht gemappt, also hätte theoretisch die Exception 13 feuern müssen beim ersten Versuch des PIT, irgendwas zu melden... Und nach dem Einschalten der IRQ's kommt der PIT genau einmal zu Wort, dann ist schluss... [/edit]

Der IDT code:
#include <system.h>
#include <video.h>

typedef struct
{
unsigned short base_low;
unsigned short sel;
unsigned char resvd;
unsigned char flags;
unsigned short base_high;
} __attribute__((packed)) IDT_ENTRY;

typedef struct
{
unsigned short limit;
unsigned int base;
} __attribute__((packed)) IDT_PTR;

void load_idt();

void _isr00();
[...]
void _isr31();

void _irq00();
[...]
void _irq15();

IDT_ENTRY idt[256];
IDT_PTR idtp;

void set_idt_entry(unsigned char num,unsigned int base,unsigned short sel,unsigned char flags)
{
idt[num].base_low = base & 0xFFFF;
idt[num].base_high = (base >> 16) & 0xFFFF;

idt[num].sel = sel;
idt[num].flags = flags;
idt[num].resvd = 0;
}

void install_idt()
{
idtp.limit = sizeof(IDT_ENTRY)*256 - 1;
idtp.base = (unsigned int)&idt;

memset((unsigned char*)&idt,0,sizeof(IDT_ENTRY)*256);

// insert interrupt handlers here
set_idt_entry(0,(unsigned int)_isr00,0x8,0x8E);
[...]
set_idt_entry(31,(unsigned int)_isr31,0x8,0x8E);

outport(0x20,0x11);
outport(0xA0,0x11);
outport(0x21,0x20);
outport(0xA1,0x28);
outport(0x21,0x04);
outport(0xA1,0x02);
outport(0x21,0x01);
outport(0xA1,0x01);
outport(0x21,0x0);
outport(0xA1,0x0);

set_idt_entry(32,(unsigned int)_irq00,0x8,0x8E);
[...]
set_idt_entry(47,(unsigned int)_irq15,0x8,0x8E);

load_idt();
}

const char* error_messages[] =
{
"Division By Zero\n",
[...]
"Reserved\n",
};

void fault_handler(unsigned char code,unsigned char error)
{
set_colour(1,0);

if(error >= 19) print(error_messages[19]);
else
{
print(error_messages[error]);
if(code > 0)
{
print("Error code: ");
putnum(code);
}
}
putnum(code);
putnum(error);
}

void irq_handler(unsigned char num)
{
putnum(num);

if(num >= 8) outport(0xA0,0x20);
outport(0x20,0x20);
}

Die ISR's sehen so aus:
[GLOBAL _isr00]
_isr00:
cli
push dword 0
push dword 0
call fault_handler
sti
iret

Die IRQ's sehen in etwa alle so aus
[GLOBAL _irq00]
_irq00:
cli
push dword 0
call irq_handler
sti
iret
« Letzte Änderung: 28. November 2006, 20:40 von FalShen »

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 29. November 2006, 13:43 »
Ich bin mir nicht sicher, ich kenn mich mit C nicht so gut aus, aber ich dacht in C muss der Funktions aufrufer den Stack säubern:

push dword 123
call _irq_handler
add esp, 0x04

Edit: hab nach geguckt es ist so! !!  C Funktionen haben ein einfach ret am ende, d.h. der stack wird nicht von den parametern befreit.
« Letzte Änderung: 29. November 2006, 13:49 von M.Nemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #3 am: 29. November 2006, 14:10 »
*headbang* stimmt ja!!
Ow danke... hab ich total vergessen...
Tausend Dank!

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #4 am: 30. November 2006, 01:47 »
Weiß jetzt nich ob es sich lohnt ein neuen Thread für dieses Problem zu machen, aber es ist 1. seltsam (siehe Titel) und 2. treibt es mich in den Wahnsinn, wie eigentlich das ganze Projekt...
Ich drücke eine Taste, und will diese ausgeben. Der hört aber nicht mehr auf, die Taste auszugeben, außer, wenn ich ne andere drücke, dann hört der nie mehr auf diese auszugeben... und so weiter.
Ich glaube nich, dass das so muss...

Das ist der glorreiche Keyboardtreiber Code (nicht wirklich ganz von mir :))
char key;
BOOL keypressed = FALSE;

BOOL shift = FALSE;
BOOL caps = FALSE;

void keyboard_handler()
{
unsigned char scancode;

while((inport(0x64) & 1) == 0);
while((inport(0x64) & 0x2) != 0);
scancode = inport(0x60);

if(scancode & 0x80)
{
scancode &= ~0x80;

if((scancode == SC_SHIFT_LEFT)||(scancode == SC_SHIFT_RIGHT))
{
if(!caps) shift = FALSE;
else shift = TRUE;
}

return;
}

if(scancode == SC_CAPS)
{
caps = !caps;
shift = !shift;
return;
}

if((scancode == SC_SHIFT_LEFT)||(scancode == SC_SHIFT_RIGHT))
{
if(!caps) shift = TRUE;
else shift = FALSE;

return;
}

if(!keypressed)
{
if(!shift) key = keymap_us[scancode];
else key = keymap_us_shift[scancode];
keypressed = TRUE;
}
}

char readkey()
{
while(!keypressed);

char temp = key;
keypressed = FALSE;
return temp;
}

Und hier die Ausgabe (in der main function):
while(1)
{
char c = readkey();
putc(c);
}
Das while(1) muss hier sein, das ich ja immer, wenn eine taste gedrückt wird, diese gerne ausgegeben haben möcht. readkey() sollte allerdings warten, bis eine Taste gedrückt wurde. Tut's aber nicht. Von der Logik im Treiber-Code sollte der das allerdings machen...
('sollte' ist so ein tolles Wort das im Berech Informatik plötzlich seine gesamte Bedeutung verliert)

Sorry euch zu damit zu nerven, aber ich weiß wieder mal nicht, was falsch läuft...

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 30. November 2006, 14:29 »
Einen fehler in deinem Code kann ich nicht finden.

Du hast den Keyboard-Handler hoffentilch am richtigen IRQ installiert, Timer und Keyboard IRQ sind nah bei einander.
Eine Installation des Keybord-Hanlers am Timer IRQ-0 würde genau ein solches feheler bild verursachen.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #6 am: 30. November 2006, 14:55 »
Also, hab jetzt den keyboard handler direkt auf den irq 1 gepackt, also im assembler teil, aber das ergebnis is das selbe... Hab ich vielleicht die IDT falsch gefüllt oder irgendsowas? Der code steht ja noch oben...

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 30. November 2006, 15:34 »
ich finde keinen fehler im code.

Aber dir müste (zumindest bei der letzten version) der Timer-Intterrupt den bildschirm mit nullen zu kleistern, (wenn das so war/ist dann müsste mit der IDT und den IRQs alles richtig sein)

Und den Fehler mit dem stack aufräumen hast du auch in irqs.asm & isrs.asm überall korrigiert?
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #8 am: 30. November 2006, 15:50 »
Ja, er kleistert mir alles mit nullen zu, und auch 1 wenn tastatur event. Und natürlich habe ich den Stack auch dort korrigiert... es muss irgendwo im handler code sein....

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 30. November 2006, 16:56 »
Hab den Fehler gefunden:

gcc macht mit der option -Os aus dem
while(!keypressed);ein
xx:
test al, al
jz xx
d.h. statt eine variable für keypressed zu nehmen nimmt gcc das al register
<edit> gcc schreibt vor der schleife mov al, keypressed (der weiß ja nicht das ein interrupt kypresset wärend dem schleifen durch gang verändert</edit>


ohne diese Optimierungs option funktioniert alles präachtig
« Letzte Änderung: 30. November 2006, 17:08 von M.Nemo »
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 30. November 2006, 17:17 »
Sollte alternativ aber auch mit volatile gehen. So wird der Rest trotzdem noch optimiert.

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #11 am: 30. November 2006, 23:22 »
Also ich weiß nicht... ohne optimierung (-Os option) oder volatile von keypressed is das Ergebnis bei mir immer noch dasselbe... *shrug*

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 01. December 2006, 13:50 »
Bei mir funktioniert es. Hast du die alten *.o & kernel.bin gelöscht befor du neu kompilierst?
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #13 am: 01. December 2006, 13:52 »
ich würd volatile empfehlen, da genau das sicherstellt, dass die variable von "außen" geändert werden kann und der compiler nicht fälschlicherweise annimmt, dass nur die momentane Befehlssequenz die Variable ändert.
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

FalShen

  • Beiträge: 73
    • Profil anzeigen
    • ScénOS
Gespeichert
« Antwort #14 am: 02. December 2006, 00:31 »
Wie gesagt.........  :?
Ich habe eine abbruchbedingung (bei ESC) in die Schleife bei main.c gepackt... nun gehts...............
Besser keine fragen stellen...... :|

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 02. December 2006, 15:35 »
bin mir jezt zimlich sicher den fehler gefunden zu haben

gcc compiliert mit -Os und volatile:
while(!keypressed); zu
a:
    mov al, keypressed
    test al, al
    jz a
wenn jetzt genau zwichen
mov al, keypressedund
test al, alder timer interrupt ausgefürt wird, dann hat al einen wert ungleich 0 und ein zeichen wird ausgegeben

mögliche korrectur wäre
am besten in allen interrupts ein pusha am anfang und popa am ende

oder die schleife in asm schreiben
a:
cmp byte keypressed, 0x00
jz a
(wie das im at-syntax aussieht hab ich keine ahnung)


„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

 

Einloggen