Nicht behebbarer Prozessorfehler beim Wechsel in P-Mode



  • 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


Anmelden zum Antworten