Gelöst: Rückkehr aus Task mit CALL-IRET = Prozessorfehler
-
Hallo zusammen,
ich habe eine Task laufen die ständig die Uhrzeit aktualisiert auf dem Schirm
anzeigt.In Zeile 2 wird mittels CALL eine andere Task aufgerufen bei deren Rückkehr
sich jedoch der Prozessor aufhängt.Hier mal die beiden Routinen.
uhrzeit: call 0x28:123456 .los: xor ax, ax in al, 0x70 and al, 11000000b out 0x70, al in al, 0x71 ;Speicherstelle 0 einlesen (Sekunde) shl ax, 4d shr al, 4d and ax, 0x0F0F add ax, 0x3030 xchg al, ah mov word [sekunde], ax xor ax, ax in al, 0x70 and al, 11000000b or al, 0x2 out 0x70, al in al, 0x71 ;Speicherstelle 2 einlesen (Minute) shl ax, 4d shr al, 4d and ax, 0x0F0F add ax, 0x3030 xchg al, ah mov word [minute], ax xor ax, ax in al, 0x70 and al, 11000000b or al, 0x4 out 0x70, al in al, 0x71 ;Speicherstelle 4 einlesen (Stunde) shl ax, 4d shr al, 4d and ax, 0x0F0F add ax, 0x3030 xchg al, ah mov word [stunde], ax cli push dword [c2] ;Coursor sichern mov eax, 80d mov dword [c2], eax push dword uhr call prints256 pop dword [c2] ;Coursor sichern sti jmp .los ret uhr: stunde dw 0 db ":" minute dw 0 db ":" sekunde dw 0 db 0
tasklesen: cli xor eax, eax str ax ;mein TR nach AX push eax ;TR sichern auf Stack sgdt [.mygdt] mov eax, [.base] ;Basis von GDT nach EAX pop ebx ;EBX = TR add ebx, eax ;EBX zeigt auf mein TSS Descriptor ;Wir lesen jetzt im Desc. die Basisadressen unseres TSS Segments ;aus mov eax, [ebx + 2] ;bswap eax ;EAX umkehren and eax, 0xFFFFFF ; mov al, byte [ebx + 7] ; bswap eax ;EAX = 32bit Adresse unseres TSS push dword [c2] mov edx, 500d mov [c2], edx push eax push dword .tssbase call prints256 push dword TSS2 call itoh push eax call prints256 push dword crlf call prints256 push dword .tsserrechnet call prints256 call itoh push eax call prints256 pop dword [c2] sti iret
Ich habe gelesen das wenn man eine Task (hier über ein TSS-Descriptor) aufruft, immer mit IRET zurückgekehrt werden muss!
Beide Tasks an sich laufen fehlerfrei, wenn ich sie einzeln aufrufe.
Auch wenn ich bei der zweiten alles bis auf Zeile 1 und Zeile 40 lösche kommt
der Fehler.Hier noch meine kleine GDT, falls von Interesse.
gdttabelle: ;0 dd 0 dd 0 CODE: ;8 dw 0xFFFF dw 0 db 0 db 10011010b db 11001111b ;DB und G Bit gesetzt db 0 DATEN: ;16 dw 0xFFFF dw 0 db 0 db 10010010b db 11001111b ;DB und G Bit gesetzt db 0 taskuser: ;24 ;Tasksegment dw 104d dw TSS1 db 0 db 10001001b ;Type = 9 db 0 db 0 tasktmp : ;32 dw 104d dw TSS4 db 0 db 10001001b db 0 ; db 0 taskuser2: ;40 ;Tasksegment dw 104d dw TSS2 db 0 db 10001001b ;Type = 9 db 0 db 0
Wie kehre ich jetzt richtig aus einer Task zurück in die aufrufende?
Gruß, Nicky
Sollten noch Codefragmente benötigt werden bitte bescheid geben.
-
Hallo nochmal,
ich habe da noch eine Sache wo ich nicht weiß woran es liegen könnte.
Mein Kernel erstellt das PageDirectory und die PageTables und füllt das
CR3 Register mit der Startadresse des PageDirectory.Auch hier läuft alles tadellos (Textausgaben, Unterprogramm usw), sobald ich
jedoch versuche eine Task zu starten streikt auch hier der Prozessor.Im TSS jeder Task ist im 7. DWORD der Wert des CR3 eingetragen.
In meinem Fall 0x21000. Das ist auch der Wert der beim Erstellen vom Kernel
im CR3 eingetragen wird.Falls jemand eine Idee hat woran es liegen könnte, währe ich auch hier dankbar.
Gruß, Nicky
-
Das i in iret deutet auf die Auslösung durch einen interrupt hin.
http://www.i8086.de/asm/8086-88-asm-iret.htmlZu call passt ret (nicht iret).
http://www.i8086.de/asm/8086-88-asm-ret.html
-
Hallo Erhard,
folgendes habe ich gefunden:
http://www.fh-zwickau.de/doc/prmo/pmtutor/text/p_spez2.htm
Anmerkung: Auch wenn CALL benutzt wird, um einen Task-Wechsel auszulösen, muß IRET (nicht RET!!!) benutzt werden, um zum unterbrochenen Task zurückzukehren.
Genau das habe ich versucht... Ein paar Seiten weiter steht jedoch folgendes:
Wird ein Task also ein zweites Mal durch den Task-Handler aktiviert, ohne daß vorher das Busy-Bit des jeweiligen Tasks gelöscht wurde, wird eine Exception ausgelöst. Der Task-Handler muß zur Lösung dieses Problems in die Task-Verkettung eingreifen. Dabei müssen die folgenden drei Tätigkeiten durchgeführt werden:
dafür sorgen,
daß während der Manipulation keine Interrupts auftreten (CLI / STI),das "Back-Link" Feld im TSS des Task-Handlers mit einem Selektor auf das TSS setzen, was nach dem IRET Befehl aktiviert werden soll,
das "Busy-Bit" der bereits aktivierten Tasks löschen (das "Busy-Bit" ist Bestandteil des Deskriptortyps des jeweiligen TSS und muß daher in der GDT geändert werden).
Erst dann kann über IRET zurückgekehrt werden.
Dann liegt es wohl am Busy-Bit im TSS-Descriptor
Werde mal mit dem CallGate vom Timer versuchen meine Tasks zu verketten.
Gruß, Nicky
-
Interessante Details.
-
Hallo und ein frohes Neues Jahr...
bin leider nicht weiter gekommen bei der Taskverkettung.
habe mal die Stacks des "alten" und des neuen Task's ausgelesen. Ich kann dort
und auch im TSS-Segment von beiden keinen Eintrag finden der auf das EFLAG
Register mit gesetztem Bit 14 passt, was ja eigentlich gesetzt sein sollte.Das einzige was ich finden kann ist, das im CR0 Register das TS Bit gesetzt wurde.
Die SS-Register beider Task's sind auf 0x10 gesetzt. Nur ESP ist beim ersten auf
0x80000 und beim zweiten auf 0x80500 gesetzt.
Das sollte doch genug Abstand sein.Das beide in Ring 0 laufen sollte auch kein Problem sein...
Falls noch jemand was weiß einfach melden..
Gruß, Nicky
-
Hallo,
Mein Programm funktioniert.
VirtualPc kann es einfach nicht. In VirtualBox läuft alles tadellos.Gruß Nicky