Discussion:
"Unreal" Mode
(zu alt für eine Antwort)
Benjamin Boldt
2004-11-04 19:22:44 UTC
Permalink
Kennt jemand von euch gute Quellen für Artikel und Tutorials über den sog.
"Unreal Mode"?
Alles was ich mir bisher ergoogelt habe ist dass man ihn erhält, wenn man
in den Protected Mode geht, dort ein bestimmtes Register ändert und zum
Real Mode zurückkehrt. Dann kann man im Real Mode bis zu 4 GB adressieren.
Ich hab jedoch nirgends Erklärungen gefunden wie das denn jetzt genau
funktioniert. Eine Schritt-für-Schritt-Anleitung bei der jeder einzelne
Schritt erklärt wird wäre optimal...

gruß Benny
--
Erstellt mit M2, Operas revolutionärem E-Mail-Modul:
http://www.opera.com/m2/
Herbert Kleebauer
2004-11-06 15:19:34 UTC
Permalink
Post by Benjamin Boldt
Kennt jemand von euch gute Quellen für Artikel und Tutorials über den sog.
"Unreal Mode"?
Ich glaube kaum, daß es dafür ein Tutorial gibt. Es ist
nichts weiter als kurz in den protected mode umschalten,
das Segmentregister mit einem selctor für eine 4 GByte
Segment laden und wieder in den real mode zurückschalte.

00000000: fa big_s3: bclr.w #9,sr ; Interrupt sperren
00000001: 66 31 c0 eor.l r0,r0
00000004: 8c c8 move.w s6,r0
00000006: 66 c1 e0 04 lsl.l #4,r0 ; CS * 16
0000000a: 66 05 0000004f add.l #gdt,r0 ; plus Offset gdt
00000010: 66 a3 004b move.l r0,new_gdt_ptr+2 ; in Pointer auf gdt eintragen
00000014: 66 0f 01 06 0043 move.l gdtr,old_gdt_ptr ; alten gdtr-Inhalt merken
0000001a: 66 0f 01 16 0049 move.l new_gdt_ptr,gdtr ; gdtr laden
00000020: 0f 20 c0 move.l cr0,r0
00000023: 66 89 c2 move.l r0,r1
00000026: 0c 01 or.b #1,r0 ; PE-Bit setzen
00000028: 0f 22 c0 move.l r0,cr0 ; Protected Mode umschalten
0000002b: eb 00 br.b _10 ; flush prefetch queue
0000002d: b8 0008 _10: move.w #$8,r0 ; Datensegmentselector -> r0
00000030: 8e e8 move.w r0,s3 ; nach s3 (GS)
00000032: 0f 22 c2 move.l r1,cr0 ; Real Mode zurueckschalten
00000035: eb 00 br.b _20 ; flush prefetch queue
00000037: 66 0f 01 16 0043 _20: move.l old_gdt_ptr,gdtr; gdtr mit altem Wert laden
0000003d: fb bset.w #9,sr ; Interrupt freigeben
0000003e: 31 c0 eor.w r0,r0 ; alle Adressen ueber s3
00000040: 8e e8 move.w r0,s3 ; sollen absolute Adressen sein
00000042: c3 rts.w

old_gdt_ptr:
00000043: 0000 dc.w 0
00000045: 00000000 dc.l 0

new_gdt_ptr:
00000049: 0010 dc.w 16 ; 2 Eintraege = 16 Bytes
0000004b: 00000000 dc.l 0 ; Adresse noch unbekannt

gdt: ;******************************************************************
; 0. Segment: Null-Segment (dummy)
0000004f: 00000000 00000000 dc.l 0,0

; 1. Segment: Datensegment (Code-Segment unnoetig)
00000057: ffff dc.w $ffff ; segment limit lo = $ffff
00000059: 0000 dc.w 0 ; segment base lo = 0
0000005b: 00 dc.b 0 ; segment base mid = 0
0000005c: 92 dc.b $92 ; acces rights = r/w expand up data segment
0000005d: 8f dc.b $8f ; page granular, segment limit hi = $f
0000005e: 00 dc.b 0 ; base hi=0
;******************************************************************
Heinz-Dietrich Saupe
2004-11-21 18:04:04 UTC
Permalink
Post by Benjamin Boldt
Kennt jemand von euch gute Quellen für Artikel und Tutorials über den sog.
"Unreal Mode"?
Dann kann man im Real Mode bis zu 4 GB adressieren. ... Eine
Schritt-für-Schritt-Anleitung bei der jeder einzelne

Du ist Opfer der MS/INTEL-x86-Lüge, daß im real mode nur 2^20 Byte
adressiert werden könnten. Zunächst einmal kann "überadressiert" werden,
wenn Du als Segment-Adresse 0FFFF wählst und nicht 0F000, wie die 1 MegByter
für richtig halten, damit bist bei linear 0F00000 + 0FFF0, also 0FFFF0. Von
dem Segment 0FFFF aus kannst Du noch weitere 64 KByte in den erweiterten
Speicher hineinadressieren, also bis 2^20 + 2^16 - 16. (Die "-16", da Du ja
nicht im Segment 0FFFFF angeben kannst.) .

Warum MS/INTEL-Lüge? Hast Du mal getestet, in welcher CPU-Betriebsart
HIMEM.SYS geladen wird und welche Betriebs-Art danach besteht. Und hast Du
mal gecheckt, wieviel Speicher sich damit (aber wieder mit Segment-Adressen
beginnend bei 0) adressieren läßt?

Aber, es kommt noch dicker: Beide Unternehmen behaupten, daß sich die CPU
nicht vom PM in den RM zurückschalten ließe, da sich Datenmüll in dem
Befehlscache befände. Das stimmt soweit. Aber, es gab den Befehl LOADALL,
mit dem alle Register auf einmal geladen werden konnten und dadurch jede
Betriebsart (in CR0 wird die CPU umgeschaltet). Natürlich hielten die beiden
Riesenunternehmen ihr Wissen geheim, um sich unfaire Vorteile im Wettbewerb
zu verschaffen. Aber, jeder Assembler-Programmierer kann darüber nachdenken,
wie wohl beim 80286 mit nur 16-Bit-Registern und 20-Bit-Segment-Registern
die 16 MByte adressiert worden sein sollen. Da war LOADALL und nichts
anderes zu der Zeit.

Im 80386 und im Derivat 80486SLC gab es LOADALL noch, dann soll die CIA
Intel gebeten haben, den Befehl aus der CPU-Maske zu entfernen. Mit LOADALL
konnten man alle Register auf einmal laden und damit mit der CPU quasi
machen, was man wollte (ich baute von 1998 bis 2000 eine LOADALL-Emulation
für damals 80486, Pentium und PII sowie wenig später PIII, daher mein
Wissen), z.B. real mode Code irgendwo oberhalb der offiziellen Grenzen
ausführen. Oho, mag da mancher sagen, ein Jump und Deine hohen Segmente sind
futsch. Richtig, muß ich dann sagen, aber ein Call tuts ohne Anpassung der
Segment-Register. Außerdem kannst Du "falsche" Jumps benutzen um Deine
Segment-Register von 32-Bit zu 20-Bit "zu shiften" und dies z.B. gegen
Code-Diebe/Hacker verwenden. Es gibt ein paar mehr wesentliche Dinge, die
ich hier jetzt nicht weiter ausführen will.

Wesentlich beim REAL BIG MODE (so steht es im Microsoft Quelltext für
himem.sys), dem eigentlichen real mode ist, daß Du vom PM in den RM
schaltest und den Datenmüll aus der Befehlspipe entfernst, nicht mit einem
Reset, sondern mit einem Jump. Denn das ist, was ein Jump auch macht, er
entfernt den Datenmüll aus dem Befehlscache. Da die CPU dadurch nicht wieder
in den Ursprungszustand zurückgesetzt wird (wie beim Reset), sondern die
Segment-Register-Caches geladen bleiben, genau wie das GDT, bleibt ein
großer Real Mode erhalten.

Ich hoffe, das genügt Dir an Info und Unterweisung, wenn Du mehr von mir
wissen willst, muß ich Dir eine Rechnung stellen.
Vinzent 'Gadget' Hoefler
2004-11-22 11:09:14 UTC
Permalink
Post by Benjamin Boldt
Post by Benjamin Boldt
Kennt jemand von euch gute Quellen für Artikel und Tutorials über den
sog. "Unreal Mode"?
Dann kann man im Real Mode bis zu 4 GB adressieren. ... Eine
Schritt-für-Schritt-Anleitung bei der jeder einzelne
Du ist Opfer der MS/INTEL-x86-Lüge, daß im real mode nur 2^20 Byte
adressiert werden könnten.
Interessant. Jemand, der behauptet 2**32 Speichereinheiten adressieren
zu koennen, ist ein Opfer der Luege, dass man in Wirklichkeit nur 2**20
Speichereinheiten adressieren koennte?
Post by Benjamin Boldt
Zunächst einmal kann "überadressiert"
werden, wenn Du als Segment-Adresse 0FFFF wählst und nicht 0F000, wie
die 1 MegByter für richtig halten,
Und dazu nicht vergessen, die A20 einzuschalten, sonst ist ganz fix die
Interrupt-Tabelle futsch. MS/Intel haben diesen Speicherbereich oberhalb
1MB seinerzeit HMA (High Memory Area) genannt.
Post by Benjamin Boldt
Warum MS/INTEL-Lüge? Hast Du mal getestet, in welcher CPU-Betriebsart
HIMEM.SYS geladen wird
Real Mode mit 64K-Limits.
Post by Benjamin Boldt
und welche Betriebs-Art danach besteht.
Real Mode mit 64K-Limits. :-) Ja. Tatsache.
Post by Benjamin Boldt
Aber, es kommt noch dicker: Beide Unternehmen behaupten, daß sich die
CPU nicht vom PM in den RM zurückschalten ließe, da sich Datenmüll in
dem Befehlscache befände.
Das ist in zweierlei Hinsicht Unsinn. Erstens *empfiehlt* Intel ein
Leeren der Befehlspipeline aus Kompatibilitaetsgruenden. Zweitens gab
es das Problem des Nicht-Zurueckschalten-Koennens nur beim 286er, seit
dem i386er ist das ueber das CR0-Register trivial machbar.
Post by Benjamin Boldt
Das stimmt soweit. Aber, es gab den Befehl
LOADALL, mit dem alle Register auf einmal geladen werden konnten und
dadurch jede Betriebsart (in CR0 wird die CPU umgeschaltet).
Ein Befehl, dessen Opcode und exaktes Verhalten sich von CPU zu CPU
geaendert hat und wegen relativer Nutzlosigkeit (wahlweise: Zwang durch
nicht genauer benannte US-Behoerden) seit dem 386er ab Generation
Pentium eingestampft wurde (SMM ist BTW weitaus praktischer).
Post by Benjamin Boldt
um sich unfaire Vorteile im Wettbewerb zu verschaffen.
Fuer mich sieht der Befehl LOADALL eher nach einer Debug-Routine fuer
Hardware-Designer, denn nach einer Verschwoerung aus. Gerade, *weil* er
einige nicht im normalen Betrieb nicht ganz sinnlose Checks eben nicht
macht. Immerhin wurde der Befehl auf dem 286er auch von genuegend
Leuten verwendet, denen man nicht unbedingt extrem nahe Verbindungen zu
Microsoft vorwerfen koennte. Von Wettbewerbsvorteilen kann also wohl
kaum die Rede sein.

Auch spricht "The 286 LOADALL is widely known because a 15-page lntel
confidential document describing its use was given to many developers."
nicht gerade von uebertriebener Geheimhaltung.
Quelle: <URI:http://www.x86.org/articles/loadall/tspec_a3_doc.htm>
Post by Benjamin Boldt
Aber, jeder
Assembler-Programmierer kann darüber nachdenken, wie wohl beim 80286
mit nur 16-Bit-Registern und 20-Bit-Segment-Registern die 16 MByte
adressiert worden sein sollen.
Ueber die Descriptor-Cache-Register, die man primaer im Protected Mode
"gesetzt" hat (wenn auch indirekt)?
Post by Benjamin Boldt
Da war LOADALL und nichts anderes zu der Zeit.
Variante 2 war ein Umschalten in dem Protected Mode, Zugriff auf den
Speicher und Zurueckschalten in den Real Mode via Prozessor-Reset.
Recht langwierige Sache, zugegeben.
Post by Benjamin Boldt
Im 80386 und im Derivat 80486SLC gab es LOADALL noch, dann soll die
CIA Intel gebeten haben, den Befehl aus der CPU-Maske zu entfernen.
*prust* <ironisch>Das war die NSA. Ich muss das wissen.</ironisch>

Obiges Dokument meint dazu uebrigens:

"Unlike the 286 LOADALL, the 386 LOADALL is still an Intel top secret. l
do not know of any document that describes its use, format, or
acknowledges its existence. Very few people at Intel wil1 acknowledge
that LOADALL even exists in the 80386 mask. The official Intel line is
that, due to U.S. Military pressure, LOADALL was removed from the 80386
mask over a year ago. However, running the program in Listing-2
demonstrates that LOADALL is alive, well, and still available on the
latest stepping of the 80386."

Es war also das Militaer. :-)
Post by Benjamin Boldt
(ich baute von 1998 bis 2000 eine
LOADALL-Emulation für damals 80486, Pentium und PII sowie wenig später
PIII, daher mein Wissen),
Wozu braucht man LOADALL fuer 386+? (Ausser fuer esoterische Tests,
meine ich?)
Post by Benjamin Boldt
z.B. real mode Code irgendwo oberhalb der
offiziellen Grenzen ausführen. Oho, mag da mancher sagen, ein Jump und
Deine hohen Segmente sind futsch.
Dafuer muesste es mindestens ein FAR JUMP sein. Und wenn ich mich schon
in Speicher befinde, der sich ausserhalb der "offiziellen Grenzen"
befindet, ist ein FAR JUMP damit doch das ideale Mittel, wieder in Code
zu springen, der innerhalb der offiziellen Grenzen liegt.
Post by Benjamin Boldt
Wesentlich beim REAL BIG MODE (so steht es im Microsoft Quelltext für
himem.sys), dem eigentlichen real mode ist, daß Du vom PM in den RM
schaltest und den Datenmüll aus der Befehlspipe entfernst, nicht mit
einem Reset, sondern mit einem Jump.
Das ist weniger wesentlich, als man gemeinhin zu denken scheint.
Saemtliche CPUs, mit denen ich in diesem Zusammenhang bisher zu tun
hatte, interessiert es nicht, ob man den FAR JUMP nun ausfuehrt oder
nicht. Viel wesentlicher ist das Anpassen der Segmentregister-Limits,
solange man sich im Protected Mode befindet.
Post by Benjamin Boldt
Ich hoffe, das genügt Dir an Info und Unterweisung, wenn Du mehr von
mir wissen willst, muß ich Dir eine Rechnung stellen.
Ist das die Vorform von "Wenn ich Dir mehr erzaehlen wuerde, muesste ich
Dich toeten?". Entschuldigung, aber das hier ist Usenet. Und das Wissen
zum Big Real Mode ist hier auch noch weit genug verbreitet, so dass hier
niemand dieses Allgemeinwissen kaufen muss. Die Quelle habe ich ja
weiter oben angegeben. :-> Share your knowledge.


Vinzent.
Stefan Reuther
2004-11-22 19:55:50 UTC
Permalink
Post by Vinzent 'Gadget' Hoefler
Post by Benjamin Boldt
um sich unfaire Vorteile im Wettbewerb zu verschaffen.
Fuer mich sieht der Befehl LOADALL eher nach einer Debug-Routine fuer
Hardware-Designer, denn nach einer Verschwoerung aus. Gerade, *weil* er
einige nicht im normalen Betrieb nicht ganz sinnlose Checks eben nicht
macht.
Welche eigentlich? Meines Wissens geht der doch nur auf Ring 0. Und wenn
der Kernel sich in den Fuss schießen will, darf er das gerne tun :)
Bleiben eigentlich nur Spielereien mit ungültigen Zugriffsrechten o.ä.,
die normalerweise beim Laden in ein Segmentregister ein #GP ergeben.
Post by Vinzent 'Gadget' Hoefler
Immerhin wurde der Befehl auf dem 286er auch von genuegend
Leuten verwendet, denen man nicht unbedingt extrem nahe Verbindungen zu
Microsoft vorwerfen koennte. Von Wettbewerbsvorteilen kann also wohl
kaum die Rede sein.
Und abgesehen davon gab es doch den Quelltext von HIMEM 2.77 ziemlich legal.
Post by Vinzent 'Gadget' Hoefler
Post by Benjamin Boldt
Aber, jeder
Assembler-Programmierer kann darüber nachdenken, wie wohl beim 80286
mit nur 16-Bit-Registern und 20-Bit-Segment-Registern die 16 MByte
adressiert worden sein sollen.
Ueber die Descriptor-Cache-Register, die man primaer im Protected Mode
"gesetzt" hat (wenn auch indirekt)?
Es gibt auch eine Routine im AT-BIOS (irgendwas im INT 15), mit der man
Speicher kopieren kann. Meines Wissens macht die das so. HIMEM verwendet
diese Routine ebenfalls, und zwar dann, wenn EMM386 geladen ist und dem
HIMEM den Protected Mode verwehrt. Denn die INT 15 Routine bietet der
EMM386 an. Ist übrigens sehr praktisch, damit kann man den EMM386
rauskegeln, ohne VCPI verwenden zu müssen :)

Und dann böte sich noch ein Memory/Memory-DMA an, aber das konnten wohl
nicht alle DMA-Controller. Jedenfalls schreibt das DMA-Tutorial, was ich
hier auf totem Baum hab, sowas.
Post by Vinzent 'Gadget' Hoefler
Post by Benjamin Boldt
z.B. real mode Code irgendwo oberhalb der
offiziellen Grenzen ausführen. Oho, mag da mancher sagen, ein Jump und
Deine hohen Segmente sind futsch.
Dafuer muesste es mindestens ein FAR JUMP sein.
Naja, ein normaler NEAR-JMP kappt dir die obersten 16 Bit vom EIP.
Post by Vinzent 'Gadget' Hoefler
Post by Benjamin Boldt
Wesentlich beim REAL BIG MODE (so steht es im Microsoft Quelltext für
himem.sys), dem eigentlichen real mode ist, daß Du vom PM in den RM
schaltest und den Datenmüll aus der Befehlspipe entfernst, nicht mit
einem Reset, sondern mit einem Jump.
Das ist weniger wesentlich, als man gemeinhin zu denken scheint.
Saemtliche CPUs, mit denen ich in diesem Zusammenhang bisher zu tun
hatte, interessiert es nicht, ob man den FAR JUMP nun ausfuehrt oder
nicht.
Das dürfte vor allem dann relevant sein, wenn der Protected-Mode-Teil im
32-Bit-Modus läuft. Dann muss der Prefetcher nämlich "umdenken" bei der
Decodierung :) Getestet hab ich das allerdings noch nicht.

Hmmm, ich weiß gar nicht, ob ich auf diesem neumodischen Rechner
überhaupt je eins meiner tollen Assembler-Protected-Mode-Programme
laufen hatte.


Stefan
Vinzent 'Gadget' Hoefler
2004-11-23 09:07:01 UTC
Permalink
Post by Stefan Reuther
Post by Vinzent 'Gadget' Hoefler
Fuer mich sieht der Befehl LOADALL eher nach einer Debug-Routine fuer
Hardware-Designer, denn nach einer Verschwoerung aus. Gerade, *weil*
er einige nicht im normalen Betrieb nicht ganz sinnlose Checks eben
nicht macht.
Welche eigentlich? Meines Wissens geht der doch nur auf Ring 0.
Yup.
Post by Stefan Reuther
Und wenn der Kernel sich in den Fuss schießen will, darf er das gerne
tun :)
Naja. Man kann es auch uebertreiben. Und es ist ja nicht so, dass man
sich mit dem Zeug nicht auch so schon das halbe Beimn wegschiessen
kann.
Post by Stefan Reuther
Bleiben eigentlich nur Spielereien mit ungültigen Zugriffsrechten
o.ä., die normalerweise beim Laden in ein Segmentregister ein #GP
ergeben.
Ja. Und das ist im Produkivbetrieb ja wohl eher selten zu irgendetwas
nuetze. Deswegen tippe ich auch eher auf Debug-Zwecke. Zumindest in der
Uridee.
Post by Stefan Reuther
Post by Vinzent 'Gadget' Hoefler
Post by Heinz-Dietrich Saupe
Aber, jeder
Assembler-Programmierer kann darüber nachdenken, wie wohl beim 80286
mit nur 16-Bit-Registern und 20-Bit-Segment-Registern die 16 MByte
adressiert worden sein sollen.
Ueber die Descriptor-Cache-Register, die man primaer im Protected
Mode "gesetzt" hat (wenn auch indirekt)?
Es gibt auch eine Routine im AT-BIOS (irgendwas im INT 15),
Funktionen 87/88h, IIRC.
Post by Stefan Reuther
mit der
man Speicher kopieren kann. Meines Wissens macht die das so.
Depends. Wuerde ich zumindest sagen. ;) Kaeme auf ein paar Disassemblate
an.
Post by Stefan Reuther
Und dann böte sich noch ein Memory/Memory-DMA an, aber das konnten
wohl nicht alle DMA-Controller. Jedenfalls schreibt das DMA-Tutorial,
was ich hier auf totem Baum hab, sowas.
Ja. Ich erinnere mich. Ich nehme an, ich habe das gleiche gelesen.
Post by Stefan Reuther
Post by Vinzent 'Gadget' Hoefler
Post by Heinz-Dietrich Saupe
z.B. real mode Code irgendwo oberhalb der
offiziellen Grenzen ausführen. Oho, mag da mancher sagen, ein Jump
und Deine hohen Segmente sind futsch.
Dafuer muesste es mindestens ein FAR JUMP sein.
Naja, ein normaler NEAR-JMP kappt dir die obersten 16 Bit vom EIP.
Ja schon (was auch eher selten sinnvoll eingesetzt werden kann).
Irgendwie hatten wir das Thema beim 32-Bit-Real-Mode doch vor Jahren
schon mal...

Ich meinte aber, es ginge darum, dass der CS-Deskriptor neu geladen
wird. Das passiert AFAIK nur bei einem FAR JUMP.
Post by Stefan Reuther
Post by Vinzent 'Gadget' Hoefler
Post by Heinz-Dietrich Saupe
Wesentlich beim REAL BIG MODE (so steht es im Microsoft Quelltext für
himem.sys), dem eigentlichen real mode ist, daß Du vom PM in den RM
schaltest und den Datenmüll aus der Befehlspipe entfernst, nicht mit
einem Reset, sondern mit einem Jump.
Das ist weniger wesentlich, als man gemeinhin zu denken scheint.
Saemtliche CPUs, mit denen ich in diesem Zusammenhang bisher zu tun
hatte, interessiert es nicht, ob man den FAR JUMP nun ausfuehrt oder
nicht.
Das dürfte vor allem dann relevant sein, wenn der Protected-Mode-Teil
im 32-Bit-Modus läuft.
Ich nehme es an. Intel wird einen Grund haben, warum sie das empfehlen.
(Obwohl ich mich dunkel entsinne, dass Intel seinerzeit sogar selbst
schrieb, dass das nicht wirklich notwendig ist, aber aus
Kompatibilitaetsgruenden ("future processors") beibehalten werden
sollte. IIRC war die Doku schon fuer die PIII-Reihe).
Post by Stefan Reuther
Hmmm, ich weiß gar nicht, ob ich auf diesem neumodischen Rechner
überhaupt je eins meiner tollen Assembler-Protected-Mode-Programme
laufen hatte.
Hehe. Das Problem moderner Betruebssysteme. Letztens musste ich doch
sogar noch einem Kollegen DOSBox auf seinem XP-Rechner installieren,
damit er $GEWISSES_PROGRAMM im Grafikmodus korrekt zum Laufen bekommt.
Aber mein Big Real Mode Programm wird auch dort auf XMS zurueckfallen.
Was im uebrigen keinen (messbaren) Deut langsamer ist.


Vinzent.
juergen B.
2004-12-02 07:34:23 UTC
Permalink
On Thu, 04 Nov 2004 20:22:44 +0100, Benjamin Boldt
Post by Benjamin Boldt
Kennt jemand von euch gute Quellen für Artikel und Tutorials über den sog.
"Unreal Mode"?
Folgendes hab ich in Tasm geschrieben, um es auch von z.B Turbo
Pascal aufzurufen, natürlich nicht in Windows Fenstern. Nur vom Real
Mode

Kann z.B. von Pascal aufgerufen werden, danach bleiben FS und GS
32-bit Register, nullbasiert.
Ohne Gewähr ich habe das aus einem größerern Zusammenhang
rauseditiert.
Haupprogramm etwa so:

call _Prot2Real
call _Real2Prot
ret


Copyright Juergen

// Tasm 6.0:

.386P ; --- 1995-2003 Juergen Behrndt

IDEAL

dssave dw 0
essave dw 0
sssave dw 0
on equ 0dfh
OFF equ 0ddh
idtreal dw 03ffh,0,0

dessize equ 8 ; Size of a descriptor in GDT

des1 equ (1*dessize)
des2 equ (2*dessize)
des3 equ (3*dessize)
des4 equ (4*dessize)
des5 equ (5*dessize)
ldes8 equ (8*dessize+4)
ldes9 equ (9*dessize+4)

writecmd equ 0d1h
readcmd equ 0d0h
statport equ 064h
porta equ 060h

segment DATA use16 public 'data'

ends

segment CODE page use16 public 'code'

assume cs:CODE,DS:DATA


proc _Real2Prot near
mov ah,on
call setlocala20 ;

ww2: pushf
cli
push ds
push ebx
mov bx,DATA
mov ds,bx ;!!
lidt [fword ds:Pas_Idt_Ptr];muss nicht wenn Int
; gesperrt, sonst Absturz.
pop ebx
pop ds
mov eax,cr0
or al,1 ; setze PE !
mov CR0,eaX ; Nur in Ring 0
mov bl,[0ffh] ; False
cmp bl,0
jz mpoff ; wenn MP nicht gesezt werden soll
or al,2 ; setze MP !
mov CR0,eaX ; Nur in Ring 0

mpoff:
db 0eah ; Jmp Ptr 16:16
rpz: dw offset(rpmode)
dw des1 ; 08h
rpmode: mov ax,030h
lldt ax
call init_fsgs; neu hier mit drin ,damit ist fs 32
bit
mov ax,des2
mov ds,ax
mov ax,des3
mov es,ax
mov ax,des4
mov ss,ax
rp1: popf ; Vorsicht Hier Interrupt evtl. wieder frei
ret
endp

proc init_fsgs near
push ax
mov ax,ldes8
mov fs,ax
mov ax,ldes9
mov gs,ax
pop ax
ret
endp

setlocala20 proc near
pushf
cli
and ah,02h
jz soff
call testa20
mov byte ptr cs:oldax,ah
mov ah,on
jmp doit
soff: mov ah,byte ptr cs:oldax
doit: call seta20
popf
ret
oldax dw 09
setlocala20 endp

seta20 proc near
pushf
cli
call empty8042
mov al,writecmd
out statport,al
call empty8042
jnz sa201
mov al,ah
out porta,al
call empty8042
sa201: popf
ret
seta20 endp

empty8042 proc near
xor cx,cx
emark1: in al,statport
and al,02
loopnz emark1
ret
empty8042 endp

testa20 proc near
call empty8042
mov al,readcmd
out statport,al
call empty8042
jnz ta201
wloop1: in al,statport
test al,1
jz wloop1
mov ah,0ffh
in al,porta
and al,2
jz ta201
mov ah,on
ta201: ret
testa20 endp

proc _Prot2Real near
push ds
mov ax,10h
mov ds,ax
inc [dword ds:inters+253*scale] ; inters[$fd]
pop ds
mov eax,cr0
and eax,07fffffffh ;clear Page enable
mov CR0,eaX
mov eax,Cr3
mov [dword ds:ccr3],eax
xor eax,eax
mov CR3,eaX
mov ax,des5 ; GDT Selbst
mov ES,aX
mov sS,aX
; fs, gs not!
mov ax,des2
mov dS,aX
pushf
cli
mov eax,cr0
and al,not 3 ; Reset PE and MP
mov CR0,eaX
db 0eah ; jmp Ptr 16:16
dw offset(prmode)
cssave dw 0 ; real mode cs aus main

prmode:
lidt [fword cs:idtreal]
mov ax,[word cs:dssave]
mov ds,ax
mov ax,[word cs:essave]
mov es,ax
mov ax,[word cs:sssave]
mov ss,ax
; mov ax,0
; mov fs,ax
; mov gs,ax
; fs, gs of coures not !
popf
mov ah,OFF
call setlocala20
ww5: ret
endp

ends



ends
Dirk Wolfgang Glomp
2004-12-03 10:26:34 UTC
Permalink
Dieses nutze ich unter MASM:

.686P

START: ...
...
cli
in al, 70h
or al, 80h
out 70h, al
call ESEG
in al, 70h
and al, 7Fh
out 70h, al
sti
...
...
;-------------------------------------
org START + ((($-START)/32)*32)+32
GDTZEIGER DW ?
DW ?
DW ?
DW 0

SEGMENTE DW 0
DW 0
DB 0
DB 0
DB 0
DB 0

DW 0FFFFh
DW 0
DB 0
DB 9Ah
DB 0
DB 0

DW 0FFFFh
DW 0
DB 0
DB 92h
DB 0
DB 0

DW 0FFFFh
DW 0
DB 0
DB 92h
DB 0FFh
DB 0FFh
SEGMENTE_END label WORD
Gdt_Groesse equ (OFFSET SEGMENTE_END - SEGMENTE -1)
;-------------------------------------
org START + ((($-START)/32)*32)+32
ESEG: xor eax, eax
mov ax, cs
mov ds, ax
shl eax, 4
mov ebx, eax
mov WORD PTR[SEGMENTE+0Ah], ax
mov WORD PTR[SEGMENTE+12h], ax
ror eax, 10h
mov BYTE PTR[SEGMENTE+0Ch], al
mov BYTE PTR[SEGMENTE+14h], al
xor eax, eax
mov ax, OFFSET SEGMENTE
add ebx, eax
mov WORD PTR[GDTZEIGER], Gdt_Groesse
mov DWORD PTR[GDTZEIGER+2], ebx
pushf
lgdt FWORD PTR[GDTZEIGER]
mov dx, ss
mov eax, cr0
or al, 1
mov cr0, eax
DB 0EAh
DW (OFFSET PMODE)
DW 8
org START + ((($-START)/32)*32)+32
PMODE: mov ax, 10h
mov ss, ax
mov ax, 18h
mov ds, ax
mov eax, cr0
and eax, not 1
mov cr0, eax
DB 0EAh
DW (OFFSET RMODE)
DW (SEG RMODE)
org START + ((($-START)/32)*32)+32
RMODE: mov ss, dx
popf
BIT_FREI: call W_8042
jnz BACK
mov al, 0D1h
out 64h, al
call W_8042
jnz BACK
mov al, 0DFh
out 60h, al
W_8042: xor cx, cx
STATUS: in al, 64h
and al, 2
loopnz STATUS
BACK: ret
;-------------------------------------

Dirk

Loading...