Autor Thema: Rückkehr aus dem PMode  (Gelesen 2933 mal)

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« am: 17. September 2005, 16:05 »
Hallo,

ich möchte mehrmals zwischen Real und Protected Mode hin und her schalten. Jedoch scheint etwas beim Ausschalten des PModes nicht ganz zu funktionieren, denn sobald ich mich wieder im Real Mode befinden müßte kann ich zum einen nicht mehr in den Protected Mode zurückschalten und zum anderen funktioniert der DOS interrupt (0x21) nicht mehr.
Mein verwendeter Code sieht so aus:
asm{
// Den PM ausschalten:
mov     eax,cr0
and     eax,0xFFFFFFFE
mov     cr0,eax
// Far-Jmp zum Selektor:Offset
fjmp    rm_cs,ende
ende:
mov     dx,rm_ds
mov     ds,dx
mov     ss,dx
mov     es,dx
mov     fs,dx
mov     gs,dx
}

IDTDescr.size=0x3FF;
IDTDescr.base=0;

asm{
lidt    byte ptr [IDTDescr]
sti
}


Also, ich schalte den PMode im cr0 Register aus, mache einen Far-Jump, setze alle Segmente wieder auf den ursprünglichen Wert und lade wieder die Original IDT. Über die Syntax muss man sich an dieser Stelle nicht wundern, da es mein eigener Compiler ist...
Habe ich da noch was vergessen, was noch gemacht werden muss, oder ist das alles soweit richtig und ich muss den Fehler an einer anderen Stelle suchen?
Ich sollte eventuell noch erwähnen, dass nach dem Ausführen dieses Codes ich Interrupts wie 0x10 für die Ausgabe wieder benutzen kann, ohne Probleme.

MM

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 17. September 2005, 16:25 »
um vom 32 bit protected mode in den real mode zu schalten musst du vorher noch kurz in den 16 bit protected mode schalten (alle register mit einem selektor mit limit 0xffff laden). sonst werden unter anderem die limits von den segment registern nich von 4 gb wieder auf 64 kb runter gesetzt. für die datensegmentregister ist das kein problem, für cs und ss wohl schon.

außerdem muss den code natürlich unter 1 mbyte geladen sein.

IDTDescr.size=0x3FF;
IDTDescr.base=0;

wird so auch nicht funktionieren, wenn du bereits im 16 bit modus bist, weil die selektoren/segment register jetzt ja wieder eine andere bedeutung haben und deswegen wirst du irgendwo anders in den speicher schreiben. auch wird wahrscheinlich die wirkung von dem address size prefix und dem operand size prefix umgekehrt sein. also alle als 16 bit compilierten operationen (rechnungen mit short) werden 32 bit sein und alle 32 bit operationen (rechnungen mit int und long) werden 16 bit sein. dadurch gerät auch noch einiges durcheinander.

ich weiss nicht wie den compiler damit umgeht, aber ich halte es für sehr riskant, 16 bit code in 32 bit code einzubetten. ich würde da über eine externe assembler datei gehen.

ich habe das mal gemacht: http://jidder.de/cnp/asm-switch-from-pm-to-rm-and-back.html
ich habe gemerkt, dass dieser code für andere sehr unverständlich ist. deswegen weiss ich nicht ob er dir wirklich hilft. wenn du ihn dir anschauen willst, werde ich natürlich gerne fragen beantworten.
Dieser Text wird unter jedem Beitrag angezeigt.

[MM]

  • Beiträge: 130
    • Profil anzeigen
    • www.mmcoding.eu
Gespeichert
« Antwort #2 am: 17. September 2005, 18:05 »
Habs jetzt teilweise hinbekommen  :)
Und zwar hatte ich für Code und Daten Deskriptoren, mit einem Limit von 64k und auch mit Address Size Prefixes gibt es bei meinem Compilern keine Probleme, sondern ich hatte in es noch ein Deskriptor geladen, welcher den Videospeicher bei 0xB8000 adressierte und nur ein Limit von 160*25 Bytes hatte. Hab jetzt einfach vor dem Umschalten noch in es den Datendeskriptor geladen und jetzt geht es teilweise (danke für den Tip mit den 16-Bit Segmenten).
Was nun geht ist, wenn ich nach der Rückkehr aus dem PMode int 0x21 aufrufe um das Programm zu beenden, was aber nicht geht ist, dass ich den PMode dann ein zweites Mal aktiviere. Dabei hängt er sich dann auf.

Ok, und wärend ich diese Zeile hier schrieb, habe ich auch den Fehler gefunden:
Am Anfang des PMode Codes hatte ich diese Zeilen:
mov ax,DES_TSS
ltr ax

Wenn ich das Laden des Task Segment Segmentes unterlasse geht es alles!
Aber warum? Muss das TSS beim ltr Befehl mit 0 initialisiert sein?

MM

 

Einloggen