Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: elfish_rider am 07. April 2005, 13:08
-
Werden bei einem Software-Interrupt die Register nicht verändert? Ich möchte meine API über INT 30h aufrufen können und Parameter über den Stack übergeben.
PS. Wenn ich Pointer als Argumente übergebe, müssen das Far-Pointer sein? Wenn ja, wie werden diese auf den Stack gebracht?
-
Werden bei einem Software-Interrupt die Register nicht verändert?
Der Unterschied zwischen Hardware-Interrupt und Software-Interrupt ist die Art des Aufrufens und nicht ob Register geändert werden oder nicht. Die Register muss der ISR-Programmierer (also du) immer selbst sichern. Du musst also deine ISR so anpassen, dass die Register auf den Stack gepusht werden, bevor du sie veränderst. Vor dem iret musst du dann wieder alle Register vom Stack laden. Wenn du die Register vorher verändern willst, geht das am einfachsten, in dem du den Stack manipulierst.
mov [esp+das_offset_von_dem_register_auf_dem_stack], wert_der_ins_register_soll
Das Offset musst du selbst ausrechnen, je nachdem was du wann pusht.
far-pointer auf den stack legen:
mov ax, segment (z.b. cs, ds, es oder irgendeine eine zahl ...)
push ax
mov di, offset
push di
und far-pointer vom stack laden:
pop ax ; segment laden
mov ds, ax
pop di ; offset laden
-
was ich eigentlich wissen wollte: kann der Kernel (die API) auf das, was das Programm gepusht hat, zugreifen? Ich bin im PM...
-
wenn esp und ss durch TSS geändert werden nein.
-
Es findet aber kein Taskwechsel statt, oder? Nur ein Interrupt.
-
bei nem taskgate schon, und sonst wird glaub ich bei einem jump von ring 3 zu ring 0 der neue stack mit den werten aus ESP0 und SS0 geladen.
-
Es ist kein Jump! Sondern das Programm macht:
MOV AX, 294Dh
PUSH 129
PUSH 0
INT 30h
mehr nicht. Kann die Kernelfunktion, auf die der IDT-Eintrag 30h gelegt ist, auf die gepushten Werte (siehe oben) zugreifen. Ich hatte die Frage etwas falsch gestellt.
-
ich weiß. aber wenn der eintrag in der IDT auf ein taskgate verweist, dann verweist das auf ein TSS. und dieses TSS wird dann gestartet. und wenn dies nicht der fall ist, also du kein taskgate hast, aber in ring 3 bist mit TSS. und ein int wird aufgerufen, egal welches, dann läd die CPU SS und ESP mit den einträgen SS0 und ESP0, die in dem TSS stehen.
-
ist int 30h nicht ein reservierter int?? sollte doch freigelassen werden?
-
ist int 30h nicht ein reservierter int?? sollte doch freigelassen werden?
Ich dachte, die ersten 32 (sprich 00h-1Fh) seien von der CPU reserviert. Windows 3.1 hat jedenfalls hier auch etwas platziert. Ausserdem war das nur ein Beispiel, ich kann auch auf 40h oder 50h oder 60h oder wasauchimmer verschieben.
-
stimmt sry, hex != dez...^^
-
Ich glaube ich habe kapiert. Ich muss SS0 und ESP0 auf den gleichen Wert setzen wie SS und ESP (in Ring 3), somit kann ich in der INT-Routine auf den original-stack zugreifen...
-
nein, das kannst du nicht, weil sich die werte ja immer ändern. die einzige möglichkeit währe, dass du die alten werte ausließt und dann setzt.
-
Das wäre eben dann das Call-Gate. Ich rede aber schon immer von Interrupt-Gates...
-
Mach doch einen Trick und uebergib in den Registern deine Werte... so macht es DOS.
wenn das nicht reicht, kannst du ja an einen Speicher eine bestimmte Tabelle/Struktur schreiben und die dann auslesen. So umgehst du die Probleme ganz elegant :)
Aber ich dachte am Anfang, dass es einfacher wäre. Aber ihr habt mich alle eines besseren belehrt :) :)
Svenska
-
Ich hatte zuvor auch zu Registern tendiert. Und seit mir klargeworden ist, dass die Segmentregister bei einem INT ja bleiben, lassen sich Zeiger auch praktisch in ein 32bit-General-Purpose-Register packen.
Ausserdem, wenn ich einmal mit C die API ansprechen will (und die Funktionsparameter in den Registern stecken), ist das irgendwie möglich?