home *** CD-ROM | disk | FTP | other *** search
- ; -----------------------------------------------------------------
- ; Programm: PROT386.ASM
- ; Funktion: demonstriert den Protected Mode auf der 386-CPU
- ; sowie Exception-Handling
- ;
- ; Autor: Sven Letzel
- ; Datum: 17.04.1993
- ; -----------------------------------------------------------------
-
- MODEL SMALL, PASCAL
-
- .386P ; Aktivierung aller 386er-Befehle
-
- .STACK 1000h
-
- PROTDATA SEGMENT WORD
- ASSUME FS:PROTDATA
- ; --------------------------------------------------------------
- ; Diverse Variablen
- ; --------------------------------------------------------------
- DummyVar DW 0
- CurY DW 0 ; benötigt zur Cursorsteuerung
- Last DW 101h ; Zeichen- und Farbsteuerung
- InProt DB 0 ; PM-Flag
- SaveESP DD ? ; Stackzeiger
-
- Feld LABEL DWORD ; Testfeld für BOUND
- Limitlow DW 0
- Limithigh DW 7
- FeldVar DB 7 DUP (?)
-
- ; -------------------------------------------------------------
- ; Meldungen
- ; -------------------------------------------------------------
- Meld1 DW Meld2-$
- DB 'PROTECTED MODE DEMO - von Sven Letzel',10,10
- DB 'Drücken Sie <ESC>, um das Programm jetzt '
- DB 'zu beenden.',10
- DB 'Jede andere Taste schaltet die CPU in den '
- DB 'Protected Mode ', 10
- Meld2 DW Meld3-$
- DB 10,'Die CPU ist jetzt im Protected Mode.',10
- DB 'Sie können nun einige Ausnahmen erzeugen.',10,10
- DB 'Drücken Sie',10
- DB '<1> für Division durch Null',10
- DB '<2> für Feldüberschreitung durch BOUND',10
- DB '<3> für Beschreiben des Code-Segments',10
- DB '<4> für Lesen jenseits der Segmentgrenze',10
- DB '<ESC> für Real Mode.',10,10
- Meld3 DW Meld4-$
- DB 'CPU jetzt im Real Mode.',10
- DB 'Programm normal beendet.',10,10
- Meld4 DW Meld5-$
- DB 'Ausnahme-Fehler Nr.: ',10,10
- Meld5 DW Meld6-$
- DB 'Bitte wählen Sie',10
- DB '(1) Befehl ohne Korrektur wiederholen',10
- DB '(2) Befehl mit Korrektor wiederholen',10
- DB '(3) Bearbeitung abbrechen',10,10
- Meld6 DW Meld7-$
- DB 'Ursache korrigiert.',10
- Meld7 DW Meld8-$
- DB 'Bearbeitung abgebrochen.',10
- Meld8 LABEL
-
- PROTDATA ENDS
-
-
- .CODE
-
- Deskriptor STRUC ; Deskriptor-Struktur
- Limit DW ?
- LowBase DW ?
- HighBase DB ?
- Acess DB ?
- Res DW ?
- Deskriptor ENDS
-
- ; ------------------------------------------------------------
- ; Globale Deskriptortabelle
- ; ------------------------------------------------------------
-
- GDTRECORD LABEL FWORD
- DW 48
- DD OFFSET GDT
- GDT LABEL DWORD
-
- Des0 Deskriptor<0,0,0,0,0> ; Dummy-Deskriptor
- Des1 Deskriptor<-1,,,9Ah,0> ; Deskriptor für Codesegment
- Des2 Deskriptor<-1,,,92h,0> ; Deskriptor für Stacksegment
- Des3 Deskriptor<-1,,,92h,0> ; Deskriptor für DS
- Des4 Deskriptor<-1,8000h,0Bh,92h,0> ; Deskriptor für Video-RAM
- Des5 Deskriptor<0FFFFh,,,92h,0> ; Deskriptor für Daten
- Des6 Deskriptor<400h,400h,0,92h,0> ; Deskriptor für BIOS-Daten
- Des7 Deskriptor<800h,8000h,0Bh,92,0>; Deskriptor für VideoRam
-
- ; ------------------------------------------------------------
- ; Selektoren für Deskriptoren
- ; ------------------------------------------------------------
-
- SelCSEG EQU 8
- SelSSEG EQU 16
- SelDSEG EQU 24
- SelVid EQU 32
- SelDaten EQU 40
-
- ; -----------------------------------------------------------
- ; Interrupt-Deskriptor-Tabelle
- ; -----------------------------------------------------------
-
- DUMMY LABEL FWORD ; alte
- DD 0,0
-
-
- IDTRECORD LABEL FWORD ; neue
- DW 14*8
- DD OFFSET IDT
- IDT LABEL DWORD
-
- Deskriptor<Int00, SelCSEG, 0, 86h, 0>
- Deskriptor<Int01, SelCSEG, 0, 86h, 0>
- Deskriptor<Int02, SelCSEG, 0, 86h, 0>
- Deskriptor<Int03, SelCSEG, 0, 86h, 0>
- Deskriptor<Int04, SelCSEG, 0, 86h, 0>
- Deskriptor<Int05, SelCSEG, 0, 86h, 0>
- Deskriptor<Int06, SelCSEG, 0, 86h, 0>
- Deskriptor<Int07, SelCSEG, 0, 86h, 0>
- Deskriptor<Int08, SelCSEG, 0, 86h, 0>
- Deskriptor<Int09, SelCSEG, 0, 86h, 0>
- Deskriptor<Int10, SelCSEG, 0, 86h, 0>
- Deskriptor<Int11, SelCSEG, 0, 86h, 0>
- Deskriptor<Int12, SelCSEG, 0, 86h, 0>
- Deskriptor<Int13, SelCSEG, 0, 86h, 0>
- Deskriptor<Int14, SelCSEG, 0, 86h, 0>
-
- REAL_SS DW ? ; Hier wird SS gesichert
-
- ; -----------------------------------------------------------
- ; Exception - Handler
- ; -----------------------------------------------------------
-
- Int00: ; Division durch Null
- PUSH AX
- XOR AX, AX
- CALL WAHL
- CMP AL, 3
- JC @@KeinK
- JZ @@K00
- JG @@Abort
- @@K00:
- OR BX, 1 ; Fehlerkorrektur
- POP AX
- IRET
-
- Int01: ; Debug-Fehler
- MOV AX, 01
- JMP @@Default
-
- Int02: ; NMI
- MOV AX, 02
- JMP @@Default
-
- Int03: ; Breakpoint
- MOV AX, 03
- JMP @@Default
-
- Int04: ; Überlauf (INTO)
- MOV AX, 04
- JMP @@Default
-
- Int05: ; BOUND
- PUSH AX
- MOV AX, 05
- CALL WAHL
- CMP AL, 3
- JC @@KeinK
- JZ @@K05
- JG @@Abort
- @@K05:
- POP AX
- XOR BX, BX ; Fehlerursache korrigiert
- IRET
-
- Int06: ; invalid Opcode
- MOV AX, 06
- JMP @@Default
-
- Int07: ; FPU fehlt
- MOV AX, 07
- JMP @@Default
-
- Int08: ; Doppelfehler
- MOV AX, 08
- JMP @@Default
-
- Int09: ; FPU-Segmnet-Fehler
- MOV AX, 09
- JMP @@Default
-
- Int10: ; Ungültiges TSS
- MOV AX, 100h
- JMP @@Default
-
- Int11: ; Segment nicht gegenwärtig
- MOV AX, 101h
- JMP @@Default
-
- Int12:
- MOV AX, 102h
- JMP @@Default
-
- Int13: ; Allgemeine Schutzverl.
- PUSH AX
- MOV AX, 103h
- CALL WAHL
- CMP AL, 3
- JC @@KeinK
- JZ @@K13
- JG @@Abort
- @@K13:
- XOR BX, BX ; Fehlerkorrektur für
- POP AX ; FEHLER13_2
- IRET
-
- Int14: ; Seitenfehler
- MOV AX, 104h
- JMP @@Default
-
- @@Abort:
- MOV AX, SelDaten
- MOV FS, AX
- LEA SI, Meld7
- CALL DISP
- MOV ESP, FS:[SaveESP]
- JMP @@MainProg
-
- @@KeinK:
- POP AX
- IRET
-
- @@Default:
- CALL WAHL
- JMP @@Abort
-
-
- WAHL PROC ; In AX Fehlernummer
- PUSH SI
- CALL BEEP ; kurz hupen bitte
- LEA SI, Meld5
- ADD AX, '00'
- XCHG AH, AL
- MOV FS:[SI-3], AX ; Fehlernummer eintragen
- LEA SI, Meld4
- CALL DISP
- LEA SI, Meld5
- CALL DISP
- @@11:
- CALL READKEY ; auf Taste warten
- AND AL, 7Fh
- CMP AL, 1
- JZ @@11
- CMP AL, 4
- JG @@11
- POP SI
- RET
- WAHL ENDP
-
-
- SetDesk PROC Selektor:Word, Segm: WORD, Offs: WORD
- MOVZX EAX, Segm ; Segmentadresse nach EAX
- SHL EAX, 4 ; in 24-Bit-Adresse umrechnen
- MOVZX EBX, Offs ; Offset nach EBX
- ADD EAX, EBX ; zum Segment addieren
- MOVZX EDI, Selektor ; Selektor laden
- MOV GDT[EDI].LowBase, AX ; Eintrag modifizieren
- SHR EAX, 8
- MOV GDT[EDI].HighBase, AH
- LEAVE
- RET 0006
- SetDesk ENDP
-
-
- BEEP PROC ; kurz hupen bitte
- PUSH AX
- PUSH ECX
- MOV AL, 0B6h ; Zeitgeber init.
- OUT 43h, AL
- MOV AX, 200h ; etwa 2kHz
- OUT 42h, AL
- XCHG AH, AL
- OUT 42h, AL
- IN AL, 61h ; 61er Status holen
- MOV AH, AL ; und merken
- OR AL, 3 ; untersten 2 Bits für Pieper
- OUT 61h, AL ; anschalten
- MOV ECX, 0FFFFFh ; eventuell verkleinern
- @Warte:
- LOOPD @Warte ; warten
- MOV AL, AH
- OUT 61h, AL ; ausschalten
- POP ECX
- POP AX
- RET
- BEEP ENDP
-
-
- READKEY PROC
- IN AL, 60h ; Tastatur lesen
- XCHG AL, AH
- @@1:
- IN AL, 60h ; Tastatur lesen
- CMP AL, AH
- JZ @@1 ; warte bis Taste gedrückt
- MOV AH, AL
- @@2:
- IN AL, 60h ; Tastatur lesen
- CMP AL, AH
- JZ @@2 ; warte bis Taste losgelassen
- RET ; Scancode in AH zurück
- READKEY ENDP
-
-
- DISP PROC ; Übergabe der Adresse in SI
- PUSH DS
- PUSH FS
- POP DS
- MOV AX, SelVid
- MOV ES, AX ; Selektor für VideoRam
- CLD
- LODSW ; Länge der Zeichenkette
- MOV CX, AX
- SUB CX, 2
- MOV DI, FS:[CurY]
- MOV AX, 160
- MUL DI ; Position neu berechnen
- MOV DI, AX
- CMP BYTE PTR FS:[InProt], 1
- JZ @@3
- PUSH 0B800h ; wenn im Real Mode
- POP ES ; dann normales Segment
- @@3:
- LODSB ; Zeichen holen
- CMP AL, 10 ; neue Zeile ?
- JNZ @@4
- CALL NewLine
- LOOP @@3
- JMP @@5
- @@4:
- MOV AH, 07
- STOSW ; Zeichen schreiben
- LOOP @@3 ; nächstes
- @@5:
- POP DS
- RET
- DISP ENDP
-
-
- NEWLINE PROC ; neue Zeile auf Bildschirm
- INC WORD PTR FS:[CurY]
- CMP WORD PTR FS:[CurY], 25 ; wenn 25, dann scrollen
- JNE @@6
- DEC WORD PTR FS:[CurY]
- PUSH DS ; wichtige Register sichern
- PUSH SI
- PUSH CX
- PUSH ES
- POP DS
- XOR DI, DI ; Bildschirmstart
- MOV SI, 160 ; Beginn Zeile 2
- MOV CX, 1920 ; 24 Zeilen
- REP MOVSW ; und kopieren
- MOV AX, 0720h
- MOV CX, 79h
- REP STOSW ; mit Leerzeichen auffüllen
- POP CX ; Register zurück
- POP SI
- POP DS
- @@6:
- MOV DI, FS:[CurY] ; Zieladresse neu berechnen
- MOV AX, 160
- MUL DI
- MOV DI, AX
- RET
- NEWLINE ENDP
-
- ; ----------------------------------------------------------------
- ; Hauptprogramm
- ; ----------------------------------------------------------------
-
- MAIN PROC FAR ; Hauptprogramm
- MOV AX, CS ; hier gehts los
- MOV DS, AX ; Datensegment init.
- MOV CS:[RSEG], AX
- MOV AX, 3
- INT 10h ; Videomodus 3
-
- ; ---------------------------------------------------------
- ; Deskriptoren initialisieren
- ; ---------------------------------------------------------
-
- MOV AX, SEG PROTDATA
- MOV FS, AX ; FS verwenden
-
- PUSH SelCSEG
- PUSH CS
- PUSH 0000
- CALL SETDESK ; CS-Deskriptor
-
- PUSH SelDSEG
- PUSH CS
- PUSH 0000
- CALL SETDESK ; DS-Deskriptor
-
- PUSH SelSSEG
- PUSH SS
- PUSH 0000
- CALL SETDESK
-
- PUSH SelDaten
- PUSH FS
- PUSH 0000
- CALL SETDESK
-
- MOV AX, CS ; Adresse der GDT
- CDQ ; korrigieren
- SHL EAX, 4
- ADD DWORD PTR [GDT-4], EAX
- ADD DWORD PTR [IDT-4], EAX
-
- LEA SI, Meld1
- CALL DISP ; Meldung ausgeben
- CALL READKEY ; Auf Taste warten
- AND AL, 7Fh
- CMP AL, 1 ; wenn ESC
- JZ @@EXIT
-
-
- LGDT GDTRECORD ; GDT laden
- SIDT DUMMY
- LIDT IDTRECORD ; IDT laden
- MOV BYTE PTR FS:[InProt], 1;
- MOV EAX, CR0 ; CR0 laden
- BTS EAX, 0 ; Bit 0 setzen
-
- CLI ; Interrupts müsssen hier aus
- MOV CR0, EAX ; Steuerregister laden
-
- DB 0EAh ; FAR-JMP, um Befehls-
- DW Offset @@PM ; warteschlange zu leeren
- DW SelCSEG ; und CS zu initialisieren
- @@PM:
- MOV AX, SelSSEG
- MOV SS, AX ; Stack init.
- MOV AX, SelDSEG
- MOV DS, AX ; sowie DS
- MOV AX, SelDaten
- MOV FS, AX ; und FS
- MOV FS:[SaveESP], ESP
-
- @@MainProg:
- LEA SI, Meld2
- CALL DISP ; Meldung ausgeben
- @@Y:
- CALL READKEY ; auf Taste warten
- AND AL, 7Fh
- CMP AL, 1 ; ist ESC ?
- JZ @@ToReal
- CMP AL, 2 ; ist 1 ?
- JZ @@FEHLER00
- CMP AL, 3
- JZ @@FEHLER05
- CMP AL, 4
- JZ @@FEHLER13_1
- CMP AL, 5
- JZ @@FEHLER13_2
- JMP @@Y
-
- @@ToReal:
- MOV EAX, CR0
- BTR EAX, 0
- MOV CR0, EAX ; PE-Bit gelöscht
- DB 0EAh ; FAR-JMP
- DW Offset @@RM
- RSEG DW 0
- @@RM:
- MOV SS, CS:[Real_SS] ; altes SS holen
- LIDT CS: DUMMY
- STI
- MOV AX, CS
- MOV DS, AX ; altes DS
- MOV AX, SEG PROTDATA
- MOV FS, AX ; altes FS
- MOV BYTE PTR FS:[InProt], 0
- LEA SI, Meld3
- CALL DISP
- CALL BEEP ; mal hupen
- @@Exit:
- XOR DL, DL
- MOV DH, BYTE PTR FS:[CurY]
- MOV AH, 02h
- INT 10h ; Cursorposition korrigieren
- MOV AH, 4Ch
- INT 21h ; Programmende
- MAIN ENDP
-
- ; ----------------------------------------------------------------
- ; Hier folgen die fehlerbehafteten Routinen
- ; ----------------------------------------------------------------
-
- @@FEHLER00:
- XOR BX, BX
- DIV BX ; Division durch 0
- JMP @@Fertig
-
- @@FEHLER05:
- MOV BX, 1
- BOUND BX, Feld ; Hier passiert nichts
- MOV BX, 10
- BOUND BX, Feld ; Hier wird INT 5 ausgelöst
- JMP @@Fertig
-
- @@FEHLER13_1:
- MOV WORD PTR CS:[GDT], 0 ; Schreibzugriff auf CS
- JMP @@Fertig ; Was soll hier korrigiert
- ; werden
- @@FEHLER13_2:
- MOV BX, -1
- MOV AX, FS:[BX] ; Lesen jenseits der
- ; Segmentgrenze
- @@FERTIG:
- LEA SI, Meld6
- CALL DISP
- JMP @@MainProg
-
- END MAIN ; Prog.ende bei MAIN beg.
-