Autor Thema: Virtual-8086-Mode  (Gelesen 2969 mal)

nukthem

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
« am: 26. February 2006, 13:09 »
Hallo!
Ich habe es bereits erfolgreich hinbekommen "normale" Task-Switches via TSS und Jump auf das Task-Gate durchzuführen.
Ich möchte aber zeitweise 8086 Code ausführen, weshalb ich den Virtual-8086-Modus brauche. Intel sagt, man schaltet in den Virual-8086-Mode, indem man das VM-Bit im EFLAG-Image des TSS für den neuen Task setzt. Dies habe ich wie folgt gemacht:

pushfd
pop eax
or eax, 00020000h
mov [es:36], eax ; bei es:36 befindet sich das EFLAG-Image

Wenn ich nun weiter unten in meinem Code den Task-Switch durchführe, bekomme ich eine "General Protection Exception".
Setze ich das VM-Bit im EFLAG-Image nicht, wird der Task ordnungsgemäß geswitcht und es kommt keine Exception.
Kann mir bitte jemand sagen, was ich falsch mache bzw. wie ich richtig in den Virtual-8086-Mode schalte?

PS: Ich bin mir 100%-ig sicher, dass die "General Protection Exception" beim Task-Switch kommt, und nicht schon irgendwo davor.

GhostCoder

  • Beiträge: 187
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 26. February 2006, 17:33 »
Hi,


Hast du in deinem aufzurufenden TSS auch Realmode Segmente eingestellt und zeigt ip auf code der im Realmode ausführbar ist?

Gruß
A man, a legend!

nukthem

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 01. March 2006, 01:31 »
Vielen Dank für die Antwort.
Es waren die Segmente. Ich hatte sie nicht auf Realmode eingestellt.
 :oops:

Doch nun eröffnet sich für mich gleich die nächste Frage.
Um die Interrupts im Virtual86 Task zu handeln, habe ich IOPL auf 0 eingestellt, damit bei int, pushf, popf, iret, cli, sti eine General Protection Exception ausgelöst wird.
Dann schaue ich nach, welcher der genannten Befehle die Exception ausgelöst hat und emuliere diesen.
Z.B. bei "int 10h" speichere ich die Rüchsprungadresse auf dem V86-Stack und hole mir in der Realmode Interruptvektortabelle die Adresse vom Interrupt-Handler.
Um diesen dann auszuführen sieht Intel vor dies durch ein iret zu bewerkstelligen.
Leider funktioniert das bei mir nur in BOCHS. Auf dem echten PC und bei MS Virtual PC löst der iret Befehl für den Rücksprung zum V86 Interrupt-Handler wiederum eine General Protection Exception aus.

Ich poste mal einen Teil meines (teilweise) kommentierten Exceptionhandlers für General Protection Exception:
(CONST_FIRSTMB_SEGMENT beinhaltet einen Selektor, der als pseudo Datensegment auf das erste Megabyte des Arbeitsspeichers zeigt; Physikalische Adresse 0x0 bis 0x100000)

pop ecx ; Error Code
pop ecx ; eip
pop ebx ; cs
push ebx
push ecx

mov ax, CONST_FIRSTMB_SEGMENT
mov es, ax
shl ebx, 4
add ebx, ecx
mov edi, ebx
mov bx, [es:edi]

mov ax, bx
and ax, 00ffh
cmp ax, 00cdh
jne NEAR no_v86_int
shr bx, 8
shl bx, 2
mov di, bx
mov ax, [es:edi] ; ax = offset
mov bx, [es:edi+2] ; bx = segment
mov bp, ax

pop eax ; ip
pop ecx ; cs
pop edx ; FLAG
pop edi ; sp
pop esi ; ss

push bp ; save offset of int handler
push bx ; save segment of int handler
push eax
push ecx
push edx

mov bx, si
mov ax, di
shl bx, 4
add bx, ax
xor edi, edi
mov di, bx
mov ax, CONST_FIRSTMB_SEGMENT
mov es, ax ; es:edi pointer to stack of v86 task
sub edi, 2
pop eax
mov [es:edi], ax ; push FLAG on v86 stack
mov ecx, eax
sub edi, 2
pop eax
mov [es:edi], ax ; push cs on v86 stack
sub edi, 2
pop eax
mov [es:edi], ax ; push ip on v86 stack
shl esi, 4
sub edi, esi ; edi = new sp
shr esi, 4

pop bx ; segment of int handler
pop ax ; offset of int handler

push esi ; ss
push edi ; sp
push ecx ; FLAG
and ebx, 0000ffffh
push ebx
and eax, 0000ffffh
push eax

iret


Mir ist ein Rätsel warum BOCHS den iret Befehl ohne erneute Exception ausführt aber das in der Realität nicht so ist. Aber das mit BOCHS ist ja sowieso eine eigene Geschichte.  :roll:
Das VM-Bit im gepushten (E)FLAG ist auf jeden Fall gesetzt, sodas auch gewähleistet ist, dass wieder in den V86-Mode umgeschaltet wird.

 

Einloggen