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


  • Mod

    Das i in iret deutet auf die Auslösung durch einen interrupt hin.
    http://www.i8086.de/asm/8086-88-asm-iret.html

    Zu 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


  • Mod

    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


Anmelden zum Antworten