Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: nooooooooos am 26. September 2005, 17:50
-
Hallo
Ich komme bei meinem eigenem OS nicht mehr weiter. Nachdem ich schon in den PM gewechselt habe, habe ich eine Interrupt Tabelle eingerichtet, und will nun den Timer Interrupt benutzten. Ich leite zuerst die Hardware-Interrupts um und schalte dann die Interrupts ein. Ich habe für den Timer Interrupt einen (bis jetzt noch leeren Handler eingerichtet) welchen ich mit "iretd" beeende.
Wenn ich nun das ganze im Bochs teste, dann blinkt der Bildschirm. Wenn ich das ganze auf eiener Boot-Diskette speichere und 1 zu 1 ausprobiere, dann schaltet sich der Computer immer wieder aus beziehungsweise er startet neu.
Vielen Dank im Vorraus
Dominik
-
Was macht denn iretd?
Versuch mal normales iret zu benutzen.
Wenn du die Interrupts auslässt passiert garnichts? Bist du dir sicher, dass der Handler richtig in der IDT steht?
-
Also das Problem besteht immer noch, auch wenn ich "iret" ohne "d" nehmen.
Ich habe mal für alle Interrupts den selben Handler genommen, da bestand das Problem weiterhin. Nachdem der Bildschirm bei Bochs etwa 20 mal geblinkt hatte, meldete Bochs "Too many registred timers".
Vieleicht hilft das.
Dominik
-
Du musst zum PIC noch ein EOI Signal senden, das kann aber eigentlich nicht für den Problem ausschlaggebend sein.
Zu deinem Problem fällt mir sonst nichts ein, ich kann mir nur vorstellen, das irgentwas in der IDT nicht stimmt.
-
Naja wenn kein EOI kommt merkt sich der PIC noch ein paar Anfragen und irgendwann ist auch der voll, ka wie er darauf reagiert.
-
Das Problem besteht wieterhin. Mein EOI Singnal sieht so aus:
mov al,20h
out 20h,al
Mein Eintrag in der IDT so:
dw II, 8, 8E00h, 0
Dabei habe ich ein Label names II das den EOI beinhaltet und mit iret beendet wird.
Vielen Dank
Dominik
-
Hat wirklich keiner ne Ahnung, woran das liegen könnte. Ich komm nicht mehr weiter.
-
Steht denn im GDT-Eintrag auch das korrekte Segment, in dem der Interrupt-Code liegt?
Außerdem: Schreib mal dies hier hin:
mov al, 20h
out 0a0h, al
out 20h, al
Ist wahrscheinlich nicht die Lösung, aber probier mal...
-
Außerdem: Schreib mal dies hier hin:
mov al, 20h
out 0a0h, al
out 20h, al
Ist wahrscheinlich nicht die Lösung, aber probier mal...
Dies muss gemacht werden wenn der IRQ sich im slave PIC befindet. Aber der timer befindet sich im master deswegen genügt das mov al,20h out 20h,al.
-
Also eben das komische an der ganzen Sache ist dass Bochs abstürzt(blinkt) und nach ca. 40 Sekuden die Meldung ausgiebt "to many registred timers" aber wenn ich das ganze mit dem Debugger anschaue durchläuft Bochs brav meine Endlosschleife.
-
Steht denn im GDT-Eintrag auch das korrekte Segment, in dem der Interrupt-Code liegt?
Was ist mit meiner Frage? Hilft dir das weiter?
-
Ja also ich habe nur einen GDT Eintrag, dieser ist für den ganzen Code und die Interrupts.
-
Du brauchst doch mindestens 3 Einträge, einen Nulldescriptor, einen Code und einen Data Descriptor.
-
Ja eben, ich hab diese drei, und der Code-Deskriptor ist für den ganzen Code inklusive Interrupts, er muss also fast funktionieren. Ich hab ihn für den ganzen 4 GB Adressrau eingestell.
-
Hallo zusammen.
Ich hab jetzt alle Möglichkeiten (zu Fehlern), die ich im Forum gefunden habe, getestet und den Kernel 100 Mal nach Fehlern abgesucht. Dabei sind aber dennoch zwei Fragen aufgetaucht.
1.) Wo soll ich den Stack am besten hintun ? Jetzt hab ich ihn bei 0x2FFFF. Wobei mein Kernel bei 0x10000 ist.
2.) Wenn ich mein OS in Bochs laufen lasse, erscheint diese Meldung:"exeption(): 3rd (13) exeption with no resolution shutdown status is 00h, resetting" Danach startet Bochs mein Os neu und kaum eine Sekunde später geschiet das ganze wieder von Vorne. Nachdem das dann ca. 30 Mal passiert ist, schreibt Bochs:"Too many registred timers. Press Enter...." Wo liegt der Fehler für diese Exeption ???
Hier nochmals den neuen Code:[BITS 16]
;16 Bit Code erstellen
jmp start ;GDT überspringen
NULL_Desc:
dd 0
dd 0
CODE_Desc:
dw 0xFFFF ;Segmentgröße Byte 0/1
dw 0 ;Segmentbasisadresse Byte 0/1
db 0 ;Segmentbasisadresse Byte 2
db 10011010b ;Zugriffsberechtigungen
db 11001111b ;Zusatz + Segmentgröße Bits 16 - 19
db 0 ;Segmentbasisadresse Byte 3
DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt:
Limit dw 0 ;Größe der GDT (wird später eingetragen)
Base dd 0
start_of_idt:
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
dw PMODE4, 8, 8E00h, 0
; Hardware Interrupts
dw PMODE5, 8, 8E00h, 0
end_of_idt:
start:
cli
;Interrupts ausschalten
mov eax, cs ;EAX auf derzeitiges Codesegment setzen
mov ds, eax ;DS auf Codesegment setzen
shl ax, 4 ;EAX mit 16 multiplizieren (Lineare Adresse des Codesegments errechnen)
mov [CODE_Desc+2], eax ;Lineare Adresse des Codesegmentes als Startadresse des Code- und Datendeskriptors eintragen
mov [DATA_Desc+2], eax
shr eax, 16
mov [CODE_Desc+4], al
mov [DATA_Desc+4], al
mov eax, cs ;Startadresse der GDT errechnen
shl eax, 4
add eax, NULL_Desc
mov [Base], eax ;Startadresse der GDT eintragen
mov [Limit], WORD gdt - NULL_Desc -1 ;Größe der GDT errechnen und eintragen
lgdt [gdt] ;GDT laden
mov eax, cr0 ;In den Protected Mode schalten, indem Bit 0 des CR0 Registers auf 1 gesetzt wird
or eax, 1
mov cr0, eax
db 0xea ;FAR-JUMP zum Codesegment
dw PMODE
dw 0x8
[BITS 32] ;32 Bit Code erstellen
PMODE:
mov WORD [CODE_Desc+2], 0 ;Code Segmentstartaddresse auf 0 setzen
mov WORD [DATA_Desc+2], 0 ;Daten Segmentstartadresse auf 0 setzen
mov BYTE [CODE_Desc+4], 0 ;Code Segmentstartaddresse auf 0 setzen
mov BYTE [DATA_Desc+4], 0 ;Daten Segmentstartadresse auf 0 setzen
mov eax, 2 ;Selektor für das Datensegment erstellen
shl eax, 3
mov ds, ax ;Daten- Stack- und Extrasegment mit Datensegmentdeskriptor laden
mov ss, ax
mov es, ax
mov eax, 0 ;FS und GS mit Null-Deskriptor laden
mov fs, ax
mov gs, ax
mov esp, 0x2FFFFF ;Stack setzen
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt
lidt [idt_pointer]
; Neuinit der Interrupt-Controller, sowie neu Setzen des Interrupt Mappings
mov al,00010001b ; kaskadierte Interrupt-Controller und Flankentriggerung an beider Controller
out 020h,al
out 0a0h,al
; neuer IRQ-Vektor für den ersten Controller einstellen neuer Wert => IRQ0..7 -> INT20h..27h
mov al,20h
out 021h,al
; neuer IRQ-Vektor für den zweiten Controller einstellen neuer Wert => IRQ8..15 -> INT28h..2Fh
mov al,28h
out 0a1h,al
; Kaskadierung beider Controller einstellen
mov al,00000100b ; Kaskadierung über IRQ2
out 021h,al
mov al,00000010b ; Kaskadierung über IRQ2
out 0a1h,al
; PIC auf Intel-Umgebung und manuelle Int.- Beendigung einstellen
mov al,00000001b
out 021h,al
out 0a1h,al
sti
PMODE2:
jmp 0x8:0x10000 + PMODE2 ;Endlosschleife
PMODE4:
pusha
push gs
push fs
push ds
push es
pop es
pop ds
pop fs
pop gs
popa
iret
PMODE5:
pusha
push gs
push fs
push ds
push es
mov al,20h
out 20h,al
pop es
pop ds
pop fs
pop gs
popa
iret
jmp 0x8:0x10000 + PMODE2
Vielen Dank im Vorraus
Nooooooooooos
-
Ja, diesen fehler bekomme ich auch bei bochs, vorher kommt allerdings auch noch ein jump_protected: descriptor not executable. Ich weiss nicht woran das liegen kann, ich hab doch alle interrupts ausgeschaltet, zumindest die maskierbaren, bei teejay im pmode tutorial funzt das ja auch ohne idt.
Den source gibts unter http://cibass.de.
mfg ena
-
Also ich habe einen Fehler in deinem Code gefunden. Ob es jetzt der ist, der dafür verandfortlich ist kann ich nicht sagen. Ich weis halt nur das es ein Fehler ist. Hier ist der Fehler:
mov esp, 0x2FFFFF ;Stack setzen
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt
lidt [idt_pointer]
Du kannst doch nicht Daten als Code ausführen. Das musst du so machen:
mov esp, 0x2FFFFF ;Stack setzen
jmp dummy
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt
dummy:
lidt [idt_pointer]
Also musst du einfach die Daten von dem IDT-Register überspringen. Hoffe mal das danach alles klappt.
-
Danke, aber ich habe das Problem mittlerweile gelöst. Es bestand ein Problem mit dem PM-Jump.
Gruss
Noooooooooos
-
Ich würde sagen eher IDT-Tutorial. Was ist der unterschied zwischen Timer-Interupt und sonst einem Interrupt ????
-
nooooooooos meinte wohl eher, das sich der Timer Interrupt genauso behandeln lässt wie alle anderen, deshalb wäre ein Tutorial über die IDT oder Interrupts insgesammt sinnvoller.
-
Genau, denn meine Probleme lagen im implementieren der IDT im allgemeinen. Du kannst natürlich noch etwas zum PIC usw. sagen.
Grus
Noooooooooooooooooos
-
Ist ja auch egal. Ich habe jetzt alles gecheckt. Nur hätte mir ein Praktik-Tutorial für den Einstig geholfen. Damit meine ich, dass man im Tutoial einen Code codet, den man dann selber ein bisschen anpassen kann und dann einen funktionierenden Code hat.
Gruss
Noooooooooos