Nicht behebbarer Prozessorfehler beim Wechsel in P-Mode
-
Ohjee..
Eigentlich hatte ich nicht vor das Forum mit Beiträgen zu füllen aber ich komme wieder mal nicht weiter.
Ich versuche vom Dos aus in den P-Mode zu schalten und direkt wieder zurück in den R-Mode.
Dazu habe ich mir die drei GDT-Einträge von Herrn Henkes zur Hilfe genommen.
Das A20 Gate wir über eine Prozedur von LowLeval angeschaltet.Da ich keine Bootloader habe sondern von DOS starte, lade ich die ersten beiden Byte der Segment Basis Adresse erst im Programm.
CS nach AX * 16 = Basis des Segments.
Ansonsten habe ich alles so gemacht wie Herr Henkes in seinem Projekt.
Hier mal der Code der den Prozessor lahmlegt.
org 100h xor eax, eax xor ebx, ebx xor ecx, ecx xor edx, edx mov ax, cs mov word [segm], ax mov cl, 4d shl eax, cl mov word [sbase1], ax mov word [dbase1], ax a1: in al, 0x64 ;Tastatur-Controller-Statusbyte lesen test al, 00000010b ;Ist Bit 1 gesetzt? jnz a1 ;Wenn ja, dann wiederhole mov al, 0xD0 ;Befehl zum Lesen des Output-Port-Statusbytes in AL speichern out 0x64, al ;Befehl an a2: in al, 0x64 ;Tastatur-Controller-Statusbyte lesen test al, 00000001b ;Bit 0 testen, ob es gesetzt ist jz a2 in al, 0x60 ;Output-Port-Statusbyte von Tastatur-Chip lesen or al, 00000010b ;Bit 1 auf 1 setzen (A20Gate-Enable-Bit) push eax a3: in al, 0x64 ;Tastatur-Controller-Statusbyte lesen test al, 00000010b ;Ist das Bit 1 gesetzt? jnz a3 mov al, 0xD1 ;Befehl zum Schreiben des Statusbytes des Output-Ports in AL schreiben out 0x64, al a4: in al, 0x64 ;Tastatur-Controller-Statusbyte lesen test al, 00000010b ;Ist das Bit 1 gesetzt? jnz a4 pop eax ;Statusbyte vom Stack holen out 0x60, al cli lgdt [gdtr] ;Laden der GDT via GDTR mov eax, cr0 ;Springe zum P-Mode or eax, 1 ; setze Bit 0 auf 1 mov cr0, eax ; jmp 0x8:pmode pmode: mov ax, 0x10 mov ds, ax ; GDT'S zuordnen mov ss, ax mov es, ax mov fs, ax mov gs, ax mov eax, cr0 ; Umschalten zum Real Mode xor eax, eax ; Bit 0 löschen mov cr0, eax ; jmp rmode rmode: mov ax, word [segm] mov cs, ax mov ds, ax sti pende: ;call modus3 ;Videomodus 3 einstellen mov eax, 4C00h int 21h ;programm beenden ;### Variablen NULL_Desc: dd 0 dd 0 CODE_Desc: dw 0xFFFF ; segment length bits 0-15 ("limit") sbase1 dw 0 ; segment base byte 0,1 db 0 ; segment base byte 2 db 10011010b ; access rights db 11001111b ; bit 7-4: 4 flag bits: granularity, default operation size bit, ; 2 bits available for OS ; bit 3-0: segment length bits 16-19 db 0 ; segment base byte 3 DATA_Desc: dw 0xFFFF ; segment length bits 0-15 dbase1 dw 0 ; segment base byte 0,1 db 0 ; segment base byte 2 db 10010010b ; access rights db 11001111b ; bit 7-4: 4 flag bits: granularity, ; big bit (0=USE16-Segm., 1=USE32-Segm.), 2 bits avail. ; bit 3-0: segment length bits 16-19 db 0 ; segment base byte 3 gdtr: Limit dw 24 ; length of GDT Base dd NULL_Desc ; base of GDT ( linear address: RM Offset + Seg<<4 ) segm dw 0
Für Tipps zur Prozessorrettung bin ich wie immer dankbar.
Gruß, Nicky
-
Sieht bei mir so aus:
Prot: xor eax,eax mov ax,cs ;eax = Adresse dieses Code-Segments shl eax,4 ;eax=eax*16 lea ebx,[eax] ;ebx = lineare Adressse dieses Segments mov [Sel01+2],bx mov [Sel02+2],bx shr ebx,16 mov [Sel01+4],bl ; mov [Sel02+4],bl mov [Sel01+7],bh ; mov [Sel02+7],bh mov [Base],ebx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; gdtr und idtr setzen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lea ebx,[eax+gdt] ;ebx = lineare Adresse der gdt mov [gdtr+2],ebx lea ebx,[eax+idt] ;ebx = lineare Adresse der idt mov [idtr+2],ebx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Jetzt in den Protect Mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cli lgdt [gdtr] lidt [idtr] mov eax,cr0 or al,1 mov cr0,eax jmp Selektor01:Go ..... ;Parameter der Globalen Deskriptor Table gdtr: dw gdt_ende-gdt-1 ;Die GrӇe der gdt dd gdt ;Die Adresse der gdt ;Parameter der Interrupt Deskriptor Table idtr: dw idt_ende-idt-1 ;Die GrӇe der idt dd idt ;Die Adresse der idt ;Hilfstabelle fr die Selektoren gdt: Sel00: dw 0 ;Der Null Deskriptor dw 0 db 0 db 0 db 0 db 0 Sel01: dw 0xffff ;Fr das DS (Protect Mode) dw 0 ;Wird beim Start Up gesetzt db 0 ;auch db 0x9a ;Present,Ring 0,Code,Non-Conforming,Readable db 0xcf ;Page-Granular,32-Bit db 0 Sel02: dw 0xffff ;Fr das CS (Protect Mode) dw 0 ;Wird beim Start Up gesetzt db 0 ;auch db 0x92 ;Present,Ring 0,Data,Expant Up,Writeble db 0xcf ;Page-Granular,32-Bit db 0 Sel03: dw 0xffff ;Fr das DS (Protect Mode) Linear Modus dw 0 ; db 0 ; db 0x92 ;Present,Ring 0,Data,Expant Up,Writeble db 0xcf ;Page-Granular,32-Bit db 0 Sel04: dw 0xfff ;Fr das DS (Real Mode) dw 0 ; db 0 ; db 0x92 ;Present,Ring 0,Data,Expant Up,Writeble db 0xcf ;Byte-Granular,16-Bit db 0 Sel05: dw 0xffff ;Fr das CS (Real Mode) dw 0 ;Wird beim Start Up gesetzt db 0 ;auch db 0x9a ;Present,Ring 0,Code,Non-Conforming,Writeble db 0xcf ;Byte-Granular,16-Bit db 0 Sel06: ;dw s_tss_e-s_tss_a ;Der Selektor fr das TSS dw 0 ;Wird beim Start Up gesetzt db 0 ;auch db 0xe9 ;present, ring 3,32 Bit,avilable TSS db 0 db 0 gdt_ende: ;Hilfstabelle fr die Selektoren Selektor00 equ Sel00-gdt Selektor01 equ Sel01-gdt Selektor02 equ Sel02-gdt Selektor03 equ Sel03-gdt Selektor04 equ Sel04-gdt Selektor05 equ Sel05-gdt Selektor06 equ Sel06-gdt
Ich benutzt nur die PM-Selektoren -> Die RM Selektoren müssen noch richtig gesetzt werden (Am Anfang)
-
Hallo,
Fehlermeldung ist weg.. aber er bleibt mit blinkendem Cursor stehen.
Eine Sache noch..
mov ax, cs shl eax, 4 lea ebx, [eax]
Wenn ich den Wert von EAX nach dem shl mit dem Wert von EBX nach dem LEA Befehl
vergleiche, erhalte ich die selben Werte (bei mir 65024 = FE00h).
Aber ohne den LEA Befehl gehts auch nicht... Ich dachte immer CS * 16 währe schon
die physikalische Adresse (Start des Segments)?
Welche Aufgabe hat LEA hierbei?Gruß und Danke schonmal
Nicky
-
Ist lea ebx, [eax] nicht gleichbedeutend mit mov ebx, eax? Geht es so schneller?
Ich würde zumindest mit letzerem 1 Byte sparen.
-
Ich weis es auch nicht genau.
Es funktioniert, gut ist.
-
Vieleicht solltest du das CR0 nicht löschen.
-
supernicky schrieb:
Hallo,
Fehlermeldung ist weg.. aber er bleibt mit blinkendem Cursor stehen.
Eine Sache noch..
mov ax, cs shl eax, 4 lea ebx, [eax]
Wenn ich den Wert von EAX nach dem shl mit dem Wert von EBX nach dem LEA Befehl
vergleiche, erhalte ich die selben Werte (bei mir 65024 = FE00h).
Aber ohne den LEA Befehl gehts auch nicht... Ich dachte immer CS * 16 währe schon
die physikalische Adresse (Start des Segments)?
Welche Aufgabe hat LEA hierbei?Gruß und Danke schonmal
Nicky
Mit LEA witd die effektive Adresse geholt/berechnet.
Bei "lea ebx, [eax]" wird die Adresse nur geholt wie bei "mov ebx, eax"Berechnungen über LEA werden schneller und von anderen CPU-Einheiten ausgeführt, als andere Integer-Operationen.
lea eax, [eax+1] ; kann man als Ersatz nehmen anstelle für "inc eax"
lea ebx, [eax+ecx*4+22224444h] ; Ersatz für 1 mul-Befehl und 3 add-Behehle
Dirk
-
Hallo und Guten Abend..
Das umschalten in den PMode und das beschreiben des Videospeichers klappt schon ganz gut...
mein letztes Problem ist das zurückschalten in den RMode.
Herr Meßmer und Herr Tischer schreiben daß das Löschen des Bit 0 von CR0 dafür reicht. Ich habe dazu auch am Anfang CS gesichert und nach dem löschen von CR0 wieder geladen. Außer einem blinkenden Courser erhalte ich aber keine Reaktion mehr vom System. (Aber auch keinen Prozessorfehler :-))Wie komme ich "sauber" zurück?
Mein Programmcode ist im ersten Posting.Nicky
-
mov eax, cr0 ; Umschalten zum Real Mode xor eax, eax ; Bit 0 löschen mov cr0, eax ;
Warum speicherst du cr0 im Register eax, das du dann ohnehin leerst?
-
Die erste Zeile könnte ich weglassen.. stimmt..
Hab noch kein Programm geschrieben das größer als 4Kb ist.. an einer Zeile mehr stör ich mich erstmal nicht so
Gruß, Nicky
-
Mit oder ohne Zeile heißt das allerdings, dass cr0 id. 0 ist. Wenn du nur das erste Bit löschen willst:
mov eax, cr0 xor eax, 1 mov cr0, eax
Edit: Oder noch schneller mit
mov eax, cr0 dec al mov cr0, eax
unter der Annahme, dass es vorher 1 war.
-
Ich hab mich damit nochnicht rum geärgert.
Würde aber als LeadIn zumindest ein Pusha spendieren.
Ev. noch das SS extra speichern.
Entsprechend als LeaOut SS zurück und Popa
-
Ich habe mir das Listing nun mal etwas näher angeschaut.
Dort wird ja gar nicht der NMI deaktiviert.Routine zum Wechseln vom RM in den 16 Bit-Unrealmode(MASM-Syntax):
START: cli ; Software-Interrupts ausschalten in al, 70h ; Über CMOS-Baustein auch or al, 80h ; die NMIS abschalten out 70h, al call ESEG ; Segmente erweitern auf 32 Bit in al, 70h ; NMIs wieder einschalten and al, 7Fh out 70h, al sti ; Software-Interrupts einschalten ;---------------------------------------------------------------------------- ; GDT für den Protected Mode ;---------------------------------------------------------------------------- org START + ((($-START)/64)*64)+64 ; Code-Ausrichtung ;---------------------------------------------------------------------------- GDTZEIGER DW ? ; Länge der GDT DW ? ; Adresse low -Word:SEGMENTE DW ? ; Adresse high-Word:SEGMENTE DW 0 ; reserviert SEGMENTE DW 0 ; Bits: 0-15 Seg.länge(Bit0-15) DW 0 ; Bits: 0-15 Basis-Adresse Deskriptor-Table DB 0 ; Bits:16-23 Basis-Adresse Deskriptor-Table DB 0 ; Bits: 0- 7 Zugriffsrechte DB 0 ; Bits: 0- 3 Seg.länge(Bit16-19)/Bit7:1=4KByte/0=1Byte DB 0 ; Bits:24-31 Basis-Adresse Deskriptor-Table ;-------------------------------------------- Selektor Segmente DW 0FFFFh ; Segmentlänge Bits: 0-15 DW 0 ; Adresse low Bits: 0-15 08h Code (CS) DB 0 ; Adresse high Bits:16-23 DB 9Ah ; Zugriffsrechte DB 0 ; Seg.Länge Bits:16-19 im Bit0-3 /Bit7:1=4KByte/0=1Byte DB 0 ; Seg.Adresse Bits:24-31 ;--------------------------------------------------- Selektor Segmente DW 0FFFFh ; Segmentlänge Bits: 0-15 DW 0 ; Adresse low Bits: 0-15 10h (SS) DB 0 ; Adresse high Bits:16-23 DB 92h ; Zugriffsrechte DB 0 ; Seg.Länge Bits:16-19 im Bit0-3 /Bit7:1=4KByte/0=1Byte DB 0 ; Seg.Adresse Bits:24-31 ;--------------------------------------------------- Selektor Segmente DW 0FFFFh ; Segmentlänge Bits: 0-15 DW 0 ; Seg.Adresse Bits: 0-15 18h (DS,ES,FS,GS) DB 0 ; Seg.Adresse Bits:16-23 DB 92h ; Zugriffsrechte DB 0FFh ; Seg.Länge Bits:16-19 im Bit0-3//Bit7:1=4KByte/0=1Byte DB 0FFh ; Seg.Adresse Bits:24-31 ;--------------------------------------------------- SEGMENTE_END label WORD Gdt_Groesse equ (OFFSET SEGMENTE_END - SEGMENTE -1) ;---------------------------------------------------------------------------- ; Setzt für das DS,ES,FS,GS-Register eine neue Segmentlänge von 00FFFFFFh. ; Dazu wird in den Protected Mode umgeschaltet. ;---------------------------------------------------------------------------- org START + ((($-START)/32)*32)+32 ; Code-Ausrichtung ;---------------------------------------------------------------------------- ESEG: xor eax, eax mov ax, cs mov ds, ax shl eax, 4 ; EAX ist nun physikalische mov ebx, eax ; Segmentstartadresse mov WORD PTR[SEGMENTE+0Ah], ax ; in den Deskriptoren mov WORD PTR[SEGMENTE+12h], ax ; für CS ror eax, 10h ; und SS in der mov BYTE PTR[SEGMENTE+0Ch], al ; GDT abspeichern mov BYTE PTR[SEGMENTE+14h], al xor eax, eax ; EAX auf null mov ax, OFFSET SEGMENTE ; 16-Bit-Offset add ebx, eax ; GDT-Adresse im mov WORD PTR[GDTZEIGER], Gdt_Groesse ; GDT-Deskriptor mov DWORD PTR[GDTZEIGER+2], ebx pushf ; Flags retten lgdt FWORD PTR[GDTZEIGER] ; GDT laden mov dx, ss ; SS retten mov eax, cr0 ; Steuerwort 0 nach EAX or al, 1 ; Protected Mode ein mov cr0, eax ; im Steuerwort ; Prefetch-Puffer löschen DB 0EAh ; die folgenden Zeilen DW (OFFSET PMODE) ; erzeugen: DW 8 ; JMP FAR CS:PMODE ;------------------------------------------------ org START + ((($-START)/32)*32)+32 ; Code-Ausrichtung ;------------------------------------------------ PMODE: mov ax, 10h ; SS-Selektor auf 64 mov ss, ax ; KByte begrenzen mov ax, 18h mov ds, ax ; DS,ES,FS,GS-Selektoren ; mov es, ax ; mov fs, ax ; mov gs, ax mov eax, cr0 ; Steuerwort 0 nach EAX and eax, not 1 ; Protected Mode aus mov cr0, eax ; im Steuerwort ; Prefetch-Puffer löschen DB 0EAh ; Die folgenden Zeilen er- DW (OFFSET RMODE) ; zeugen das Kommando AKTSEG DW (SEG RMODE) ; JMP FAR CS:RMODE ;------------------------------------------------ org START + ((($-START)/32)*32)+32 ; Code-Ausrichtung ;------------------------------------------------ RMODE: mov ss, dx ; SS zurueck popf ; Flags holen ;---------------------------------------------------------------------------- ; Schaltet das 21. Adreßbit des Prozessors ein. ;---------------------------------------------------------------------------- BIT_FREI: call W_8042 jnz BACK mov al, 0D1h out 64h, al call W_8042 jnz BACK mov al, 0DFh out 60h, al ;----------------------------------------------------------- ; Wartet darauf, bis der 8042 bereit ist. ;------------------------------------------------------------ W_8042: xor cx, cx STATUS: in al, 64h and al, 2 loopnz STATUS BACK: ret
-
Das mit dem NMI hab ich auch nicht.
Bringt aber anscheinend kein Problem.
Ich hatte da bisher keine Sorgen wegen.Ausserdem gebe ich zu bedenken das NMI ja Nicht Maskierbarer Interrupt heist.
-
Hallo zusammen,
ich habe den Fehler gefunden.
Hier der alte Code:
cli lgdt [gdtr] ;Laden der GDT via GDTR mov eax, cr0 ;Springe zum P-Mode or eax, 1 ; setze Bit 0 auf 1 mov cr0, eax ; jmp 0x8:pmode pmode: mov ax, 0x10 mov ds, ax ; GDT'S zuordnen mov ss, ax mov es, ax mov fs, ax mov gs, ax mov eax, cr0 ; Umschalten zum Real Mode xor eax, eax ; Bit 0 löschen mov cr0, eax ; jmp rmode rmode: mov ax, word [segm] mov cs, ax mov ds, ax sti
und hier mein neuer
push ds cli lgdt [gdtr] ;Laden der GDT via GDTR mov eax, cr0 ;Springe zum P-Mode or eax, 1 ; setze Bit 0 auf 1 mov cr0, eax ; jmp 0x8:pmode pmode: mov ax, 18h ; GDT'S zuordnen mov es, ax mov fs, ax mov gs, ax xor eax, eax xor eax, eax mov eax, cr0 ; Umschalten zum Real Mode and al, 11111110b ; Bit 0 löschen mov cr0, eax ; jmp rmode rmode: pop ds sti
Im Grunde brauche ich ja nur die Segmentregister ES, FS und GS auf 32Bit zu erweitern. DS und CS bleiben unverändert.
So funktioniert es jetzt bei mir.Ich probier dann mal weiter.
Gruß und Danke
Nicky
-
gargyle schrieb:
Das mit dem NMI hab ich auch nicht.
Bringt aber anscheinend kein Problem.
Ich hatte da bisher keine Sorgen wegen.Aha. Ist wohl auch nur wenn ein Speicherfehler auftritt?
Ausserdem gebe ich zu bedenken das NMI ja Nicht Maskierbarer Interrupt heist.
Nicht Maskierbar bedeutet aber nur, dass der NMI sich weder über den PIC1(PORT 20h-003Fh), oder PIC2(Port 00A0h-00AFh) selektiv maskieren läßt, noch durch die cli/sti-Befelhle beeinflusst wird, die sonst alle maskierbaren Interrupts generell sperren/freigeben, aber nicht den NMI.
- Generelle Interrupt-Maskierung betrifft alle maskierbaren Interrupts
- Selektive Interrupt-Maskierung betrifft nur den gewählten Interrupt
- Maskenbits (je Interrupt) werden üblicherweise zu Maskenregistern zusammengefasst
- Neben der Interrupt-Maskierung werden üblicherweise auch Interrupt-Prioritäten verwaltet (konfigurierbar)Bitfields for PIC output control word OCW1: Bit(s) Description (Table P0014) 7 disable IRQ7 (parallel printer interrupt) 6 disable IRQ6 (diskette interrupt) 5 disable IRQ5 (fixed disk interrupt) 4 disable IRQ4 (serial port 1 interrupt) 3 disable IRQ3 (serial port 2 interrupt) 2 disable IRQ2 (video interrupt) 1 disable IRQ1 (keyboard, mouse, RTC interrupt) 0 disable IRQ0 (timer interrupt) SeeAlso: #P0015,#P0016,#P0418 Bitfields for PIC2 output control word OCW1: Bit(s) Description (Table P0418) 7 disable IRQ15 (reserved) 6 disable IRQ14 (fixed disk interrupt) 5 disable IRQ13 (coprocessor exception interrupt) 4 disable IRQ12 (mouse interrupt) 3 disable IRQ11 (reserved) 2 disable IRQ10 (reserved) 1 disable IRQ9 (redirect cascade) 0 disable IRQ8 (real-time clock interrupt) SeeAlso: #P0014
0070 -W CMOS RAM index register port (ISA, EISA) bit 7 = 1 NMI disabled from reaching CPU = 0 NMI enabled Note: any write to PORT 0070h should be followed by an action to PORT 0071h or the RTC wil be left in an unknown state.
Bei mir ist auch noch nie ein unbekannter Zustand im RTC vorgekommen.
Für diesen Fall wäre es dann wohl besser einen Zugriff auf Port 71h zu machen:cli ; Software-Interrupts ausschalten in al, 70h ; Über CMOS-Baustein auch or al, 80h ; die NMIS abschalten out 70h, al [b]in al, 71h[/b] call ESEG ; Segmente erweitern auf 32 Bit in al, 70h ; NMIs wieder einschalten and al, 7Fh out 70h, al [b]in al, 71h[/b] sti ; Software-Interrupts einschalten
Dirk
-
supernicky schrieb:
Hallo zusammen,
ich habe den Fehler gefunden.
Prima.
Im Grunde brauche ich ja nur die Segmentregister ES, FS und GS auf 32Bit zu erweitern. DS und CS bleiben unverändert.
So funktioniert es jetzt bei mir.Ich probier dann mal weiter.
Gruß und Danke
Nicky
Ich erweitere meistens nur DS, weil dann seltener Segment-Override Prefixe benötigt werden.
(Ausnahme: Wenn (E)BP oder (E)SP als Adressregister verwendet wird, dann wird ggf. ein Segment-Override Prefix mit DS nötig, wenn darüber adressiert werden soll.
Das läßt sich aber oft vermeiden, wenn man diese beiden Offsetregister nicht zum Adressieren verwendet, wenn man über DS adressieren möchte.)Um über FS und GS zu adressieren braucht man aber immer ein Segment-Override Prefix.
Wenn DS erweitert wurde, dann kann DS auch weiterhin auf unseren Datenbereich zeigen und alle linearen Adressen lassen sich relativ dazu berechnen und darauf anpassen.
Dirk