communityWir suchen ständig neue Tutorials und Artikel! Habt ihr selbst schonmal einen Artikel verfasst und seid bereit dieses Wissen mit der Community zu teilen? Oder würdet ihr gerne einmal über ein Thema schreiben das euch besonders auf dem Herzen liegt? Dann habt ihr nun die Gelegenheit eure Arbeit zu veröffentlichen und den Ruhm dafür zu ernten. Schreibt uns einfach eine Nachricht mit dem Betreff „Community Articles“ und helft mit das Angebot an guten Artikeln zu vergrößern. Als Autor werdet ihr für den internen Bereich freigeschaltet und könnt dort eurer literarischen Ader freien Lauf lassen.

BIOS-Level Programmierung - Grafik-Modi Drucken E-Mail
Benutzerbewertung: / 47
SchwachPerfekt 
Geschrieben von: StarShaper   
Donnerstag, den 01. Juni 2006 um 10:30 Uhr
Beitragsseiten
BIOS-Level Programmierung
Die Tastatur
Video Programmierung
Grafik-Modi
Mausprogrammierung
Alle Seiten

Grafik-Modus

Neben den verschiedenen Text-Modi existieren auch einige Grafik-Modi (Graphics Mode). Mithilfe der INT 10h Funktion 0Ch lassen sich Pixel und Linien sehr einfach auf den Bildschirm zeichnen. Bevor Sie jedoch Pixel auf den Bildschirm zeichnen können, müssen Sie den Video Adapter in einen standardisierten Grafik-Modus bringen. Einen Überblick über die vorhandenen Video-Modi finden Sie in der Tabelle 4. Der Modus lässt sich genau wie im Abschnitt "Text-Modus" erklärt über die Funktion INT 10h 00h setzen.

Table 4: Video Modes
Modus Typ Karte Auflösung Farben
00 Text CGA, EGA, VGA 40 x 25 1
01 Text CGA, EGA, VGA 40 x 25 16
02 Text CGA, EGA, VGA 80 x 25 2
03 Text CGA, EGA, VGA 80 x 25 16
04 Grafik CGA, EGA, VGA 320 x 200 4
05 Grafik CGA, EGA, VGA 320 x 300 1
06 Grafik CGA, EGA, VGA 640 x 200 2
07 Text MDA, Hercules, EGA an MDA-Monitor 80 x 25 Monochrom
0D Grafik EGA, VGA 320 x 200 16
0E Grafik EGA, VGA 640 x 200 16
0F Grafik EGA an MDA-Monitor 640 x 350 Monochrom
10 Grafik EGA, VGA 640 x 350 16
11 Grafik VGA 640 x 480 2
12 Grafik VGA 640 x 480 16
13 Grafik VGA 320 x 200 256
14 Text VGA 132 x 25 16
6A Grafik VGA 800 x 600 16
weitere hardwareabhängig

Die Funktion 0Ch schreibt nicht direkt in den Video RAM, so dass es beim Zeichnen vieler Pixel zu geringfügigen Verzögerungen kommen kann. Die Verzögerung hängt proportional mit der Anzahl der Zeichenaufrufe für einen Pixel zusammen. Neben der Möglichkeit Pixel zu zeichnen ist es auch möglich ein Pixel vom Bildschirm zu lesen. Der prinzipielle Code für das Schreiben und Lesen eines Pixels kann folgendermaßen aussehen.

;--------------------------------------------------
; INT 10h Funktion 0Ch
; Schreibt einen Pixel auf den Bildschirm.
;--------------------------------------------------
mov ah, 0Ch
mov al, pixelValue         ; Der Pixelwert
mov bh, videoPage          ; Die Bildschirmseite
mov cx, xcoord             ; X-Koordinate
mov dx, ycoord             ; Y-Koordinate
int 10h
 
;--------------------------------------------------
; INT 10h Funktion 0Dh
; Liest einen Pixel vom Bildschirm. Die Funktion
; gibt das Pixel im AL-Register zurück.
;--------------------------------------------------
mov ah, 0Dh
mov bh, 0                 ; Die Bildschirmseite
mov cx, xcoord
mov dx, ycoord
int 10h

Bevor wir uns einer deutlich schnelleren Variante Pixel auf den Bildschirm zu zeichnen zuwenden, werden wir das bisher errungene Wissen dazu benutzen ein einfaches Schachbrett auf den Bildschirm zu zeichnen. Das folgende Programm zeichnet zunächst das einfache Gitternetz und füllt danach die weißen Felder auf. Dies dient ledeglich Demonstrationszwecken und ist für das Endresultat nur bedingt erforderlich.

TITLE Chess field        (chessfield.asm)
 
COMMENT ! Dieses Programm schaltet in den Grafik-Modus 6Ah (800 x 600)
          und zeichnet zunächst ein Gitternetz aus Schachfeldern.
          Anschließend füllt das Programm abwechselnd die
          entsprechenden Felder weiß auf, so dass am Ende ein
          Schachbrett auf dem Bildschirm zu sehen ist.
          Last update: 25/05/06 !
 
.model small, stdcall
.stack 200h
.386
 
;------------------------------------------------------
; Video-Modi Konstanten
;------------------------------------------------------
Mode_06 = 6         ; 640x200,  2 colors
Mode_0D = 0Dh       ; 320 x 200, 16 colors
Mode_0E = 0Eh       ; 640 x 200, 16 colors
Mode_0F = 0Fh       ; 640 x 350,  2 colors
Mode_10 = 10h       ; 640 x 350, 16 colors
Mode_11 = 11h       ; 640 x 480,  2 colors
Mode_12 = 12h       ; 640 x 480, 16 colors
Mode_13 = 13h       ; 320 x 200, 256 colors
Mode_6A = 6Ah       ; 800 x 600, 16 colors
 
white = 1111b
 
.data
    saveMode BYTE ?         ; Speichert den Video-Modus
    fRows WORD 20           ; Speichert die Reihe der horizontalen Linie
    fCols WORD 120          ; Speichert die Spalte der vertikalen Linie
    tmp WORD 0              ; Temporäre Variable
    innerCounter Word 0     ; Innerer Schleifenzähler
    outerCounter WORD 1     ; Äußerer Schleifenzähler
    fields BYTE 0           ; Anzahl der Felder pro Spalte
    fieldsCols WORD 0       ; Anzahl der Spalten
 
.code
main PROC
    mov ax, @data
    mov ds, ax
 
    mov  ah, 0Fh            ; Empfange den aktuell eingestellten Video-Modus
    int  10h
    mov  saveMode, al       ; Speichere diesen Video-Modus
 
    mov  ah, 0              ; Setze den Video-Modus 
    mov  al, Mode_6A        ; Nimm den Grafik-Modus mit 800 x 600 und 16 Farben
    int  10h
 
 
Rows:                       ; Zeichne die horizontalen Gitterlinien
    mov  cx, 120            ; X-Koordinate der Starlinie
    mov  dx, fRows          ; Y-Koordinate der Starlinie
    mov  ax, 560            ; Länge der Linie
    mov  bl, white          ; Farbe der Linie
    call DrawHorizLine      ; Zeichne die horizontale Linie
    add  fRows, 70          ; Nächste Linie
    cmp  fRows, 580         ; Sind wir fertig?  
    jbe  Rows               ; Falls fRows <= 580 springe zurück                           
 
Cols:
    mov  cx, fCols          ; Zeichne die vertikalen Gitterlinien
    mov  dx, 20
    mov  ax, 560
    mov  bl, white
    call DrawVerticalLine   ; Zeichne die vertikale Linie
    add  fCols, 70
    cmp  fCols, 680
    jbe  Cols               ; Falls fCols <= 680 springe zurück
 
    mov tmp, 20             ; Setze die temporäre Variable auf x = 20
    add fieldsCols, 120     ; Setze die Variable auf y = 120
                            ; Oberer linker Eckpunkt P(120|20)
 
L1:                         ; Fülle nun die weißen Felder aus indem jeweils
                            ; 70 horizontale Linien gezeichnet werden
    mov  cx, fieldsCols
    mov  dx, tmp
    mov  ax, 70
    mov  bl, white
    call DrawHorizLine
    inc innerCounter        ; Inkrementiere den inneren Schleifenzähler
    add tmp, 1
    cmp innerCounter, 70
    jb L1
    add fields, 1           ; Inkrementiere die Anzahl der weißen Felder in der Spalte
    cmp fields, 4           ; Haben wir 4 Felder gezeichnet?
    jae NextCol
    mov innerCounter, 0     ; Nein, inkrementiere die innere Schleife
    add tmp, 70             ; Addiere 70 dazu und überspringe damit das schwarze Feld
    jmp L1
 
NextCol:
    cmp outerCounter, 8     ; Haben wir die achte Spalte erreicht?
    jae Finished            ; Falls outerCounter >= 8 springe
    inc outerCounter
    mov fields, 0
    mov innerCounter, 0
    add fieldsCols, 70
    mov dx, 0
    mov ax, outerCounter
    mov cx, 2               ; Teile durch 2. Dies überprüft ob die Spalte gerade
                            ; oder ungerade ist.
    div cx                  ; 16-Bit unsigned Division
    cmp dx, 0               ; Checke ob der Rest (Remainder) in DX gleich 0
                            ; (Modulo Division) ist
    je EVENx                ; Springe an EVENx, falls gleich
    jmp ODDx                ; Andernfalls an ODDx
 
EVENx:
    mov tmp, 90
    jmp L1
 
ODDx:
    mov tmp, 20
    jmp L1
 
Finished:
    mov  ah, 10h            ; Warte auf einen Tastendruck
    int  16h
 
    mov  ah, 0              ; Stelle den anfangs gespeicherten Video-Modus wieder her
    mov  al, saveMode
    int  10h
 
    mov ax, 4C00h   ; Beende das Programm samt Exit Code
    int 21h         ; Gebe die Kontrolle wieder an DOS zurück
main endp
 
;------------------------------------------------------
; DrawHorizLine
; Zeichnet eine horizontale Linie beginnend an der
; Position X,Y mit einem übergebenen Längenwert und Farbe.
; Empfängt: CX = X-Koordinate, DX = Y-Koordinate,
;           AX = Länge, und BL = Farbe
; Rückgabewert: -
;------------------------------------------------------
DrawHorizLine PROC
.data
currX WORD ?
 
.code
    pusha
    mov  currX, cx          ; Speichert die X-Koordinate
    mov  cx, ax             ; Schleifenzähler
 
DHL1:
    push cx                 ; Speichert den Schleifenzähler
    mov  al, bl             ; Farbe
    mov  ah, 0Ch            ; Zeichne Pixel
    mov  bh, 0              ; Video Page
    mov  cx, currX          ; Empfabge die X-Koordinate
    int  10h
    inc  currX              ; Gehe 1 Pixel nach rechts
    pop  cx                 ; Stelle den Schleifenzähler wieder her
    Loop DHL1
 
    popa
    ret
DrawHorizLine ENDP
 
;------------------------------------------------------
; DrawVerticalLine
; Zeichnet eine vertikale Linie beginnend an der
; Position X,Y mit einem übergebenen Längenwert und Farbe.
; Empfängt: CX = X-Koordinate, DX = Y-Koordinate,
;           AX = Länge, und BL = Farbe
; Rückgabewert: -
;------------------------------------------------------
DrawVerticalLine PROC
.data
currY WORD ?
 
.code
    pusha
    mov  currY, dx          ; Speichert die Y-Koordinate
    mov  currX, cx
    mov  cx, ax             ; Schleifenzähler
 
DVL1:
    push cx                 ; Speichert den Schleifenzähler
    mov  al, bl             ; Farbe
    mov  ah, 0Ch            ; Zeichne Pixel
    mov  bh, 0
    mov  cx, currX          ; Setze die X-Koordinate
    mov  dx, currY          ; Setze die Y-Koordinate
    int  10h                ; Zeichne Pixel
    inc  currY              ; Gehe 1 Pixel nach unten
    pop  cx                 ; Stelle den Schleifenzähler wieder her
    Loop DVL1
 
    popa
    ret
DrawVerticalLine ENDP
END main

Vergessen Sie nicht das Programm unter Windows im Vollbildmodus auszuführen!

Memory-Mapped I/O

Das Zeichnen mittels Interrupt 10h ist bei vielen Pixeln oft eine träge Angelegenheit. Der Grund liegt darin das sehr oft sehr viele Codezeilen ausgeführt werden müssen. Dies verlangsamt das Programm ganz erheblich. Eine wesentlich effizientere und oft verwendete Variante ist eine Technik namens memory-mapped graphics, die alle Daten direkt im VRAM ablegt bevor sie auf dem Bildschirm gezeichnet werden.

Der Video-Modus 13h ist der bevorzugte Modus sobald man direkt mit dem Speicher arbeitet. Der Modus besitzt eine Auflösung von 320 x 200 und kann 256 Farben darstellen. Die Bildschirm-Pixel werden als zweidimensionale Arrays von Bytes dargestellt, indem jeder Pixel ein eigenes Byte belegt. Das Array beginnt mit dem Pixel in der oberen linken Ecke des Bildschirms und erstreckt sich bis zum Pixel der oberen rechten Ecke. Im Video-Modus 13h sind das exakt 320 Bytes. Das nächste Byte bildet das Pixel in der zweiten Zeile ab und so weiter. Ein Byte kann einschließlich der 0 insgesamt 256 verschiedene Ganzzahlenwerte darstellen. Damit lassen sich die 256 verschiedene Farben repräsentieren. Alle Pixel und Farbwerte können zum Video Adapter transferiert werden indem die OUT Instruktion verwendet wird. Dazu wird eine 16-Bit Port Adresse an DX zugewiesen und der Wert der an den Port gesendet wird, wird in AL abgelegt. Die Video Farbpalette befindet sich an der Port Adresse 3C8h. Die Farben werden mithilfe einer RGB Farbpalette dargestellt. Es können insgesamt 262144 verschiedene Farben ausgegeben werden. Zeitgleich können natürlich nur 256 Farben angezeigt werden, jedoch kann die Ausgabe zur Laufzeit geändert werden.

Im nächsten Programm werden wir sehen wie sich Animationen programmieren lassen. Das Programm FireScreen bildet ein flackerndes Feuer auf dem Bildschirm ab. Falls Sie Probleme haben den folgenden, etwas komplexeren Quellcode nachzuvollziehen, können Sie sich parallel dazu die anderen Beispiele zum Memory-Mapping im Anhang dieses Tutorials ansehen. Diese sind teilweise einfacher strukturiert.

TITLE Fire Screen          (firescreen.asm)
 
COMMENT ! Dieses Programm nutzt memory-mapped graphics
          um mithilfe einer RGB Farbpalette ein
          Feuereffekt auf dem Bildschirm darzustellen.
          Last update: 25/05/06 !
 
.model small, stdcall
.stack 200h
.386
 
.data
    saveMode BYTE ?                                ; Gespeicherter Video Modus
    urlmessage BYTE "http://www.codeplanet.eu/$"   ; Wird am Ende angezeigt
    xVal = 80                                      ; Bildschirmweite in Pixeln
    yVal = 112                                     ; Bildschirmhöhe in Pixeln + 2
    seed WORD ?                                    ; Zufallszahlen
 
    ; RGB Farbpalette von 0-63 (maximum), die Palette repräsentiert das Feuer
    palette BYTE  0,  0,  0,  0,  0,  6,  0,  0,  6,  0,  0,  7,  0,  0,  8,  0,  0,  8
            BYTE  0,  0,  9,  0,  0, 10,  2,  0, 10,  4,  0,  9,  6,  0,  9,  8,  0,  8
            BYTE 10,  0,  7, 12,  0,  7, 14,  0,  6, 16,  0,  5, 18,  0,  5, 20,  0,  4
            BYTE 22,  0,  4, 24,  0,  3, 26,  0,  2, 28,  0,  2, 30,  0,  1, 32,  0,  0
            BYTE 32,  0,  0, 33,  0,  0, 34,  0,  0, 35,  0,  0, 36,  0,  0, 36,  0,  0
            BYTE 37,  0,  0, 38,  0,  0, 39,  0,  0, 40,  0,  0, 40,  0,  0, 41,  0,  0
            BYTE 42,  0,  0, 43,  0,  0, 44,  0,  0, 45,  0,  0, 46,  1,  0, 47,  1,  0
            BYTE 48,  2,  0, 49,  2,  0, 50,  3,  0, 51,  3,  0, 52,  4,  0, 53,  4,  0
            BYTE 54,  5,  0, 55,  5,  0, 56,  6,  0, 57,  6,  0, 58,  7,  0, 59,  7,  0
            BYTE 60,  8,  0, 61,  8,  0, 63,  9,  0, 63,  9,  0, 63, 10,  0, 63, 10,  0
            BYTE 63, 11,  0, 63, 11,  0, 63, 12,  0, 63, 12,  0, 63, 13,  0, 63, 13,  0
            BYTE 63, 14,  0, 63, 14,  0, 63, 15,  0, 63, 15,  0, 63, 16,  0, 63, 16,  0
            BYTE 63, 17,  0, 63, 17,  0, 63, 18,  0, 63, 18,  0, 63, 19,  0, 63, 19,  0
            BYTE 63, 20,  0, 63, 20,  0, 63, 21,  0, 63, 21,  0, 63, 22,  0, 63, 22,  0
            BYTE 63, 23,  0, 63, 24,  0, 63, 24,  0, 63, 25,  0, 63, 25,  0, 63, 26,  0
            BYTE 63, 26,  0, 63, 27,  0, 63, 27,  0, 63, 28,  0, 63, 28,  0, 63, 29,  0
            BYTE 63, 29,  0, 63, 30,  0, 63, 30,  0, 63, 31,  0, 63, 31,  0, 63, 32,  0
            BYTE 63, 32,  0, 63, 33,  0, 63, 33,  0, 63, 34,  0, 63, 34,  0, 63, 35,  0
            BYTE 63, 35,  0, 63, 36,  0, 63, 36,  0, 63, 37,  0, 63, 38,  0, 63, 38,  0
            BYTE 63, 39,  0, 63, 39,  0, 63, 40,  0, 63, 40,  0, 63, 41,  0, 63, 41,  0
            BYTE 63, 42,  0, 63, 42,  0, 63, 43,  0, 63, 43,  0, 63, 44,  0, 63, 44,  0
            BYTE 63, 45,  0, 63, 45,  0, 63, 46,  0, 63, 46,  0, 63, 47,  0, 63, 47,  0
            BYTE 63, 48,  0, 63, 48,  0, 63, 49,  0, 63, 49,  0, 63, 50,  0, 63, 50,  0
            BYTE 63, 51,  0, 63, 52,  0, 63, 52,  0, 63, 52,  0, 63, 52,  0, 63, 52,  0
            BYTE 63, 53,  0, 63, 53,  0, 63, 53,  0, 63, 53,  0, 63, 54,  0, 63, 54,  0
            BYTE 63, 54,  0, 63, 54,  0, 63, 54,  0, 63, 55,  0, 63, 55,  0, 63, 55,  0
            BYTE 63, 55,  0, 63, 56,  0, 63, 56,  0, 63, 56,  0, 63, 56,  0, 63, 57,  0
            BYTE 63, 57,  0, 63, 57,  0, 63, 57,  0, 63, 57,  0, 63, 58,  0, 63, 58,  0
            BYTE 63, 58,  0, 63, 58,  0, 63, 59,  0, 63, 59,  0, 63, 59,  0, 63, 59,  0
            BYTE 63, 60,  0, 63, 60,  0, 63, 60,  0, 63, 60,  0, 63, 60,  0, 63, 61,  0
            BYTE 63, 61,  0, 63, 61,  0, 63, 61,  0, 63, 62,  0, 63, 62,  0, 63, 62,  0
            BYTE 63, 62,  0, 63, 63,  0, 63, 63,  1, 63, 63,  2, 63, 63,  3, 63, 63,  4
            BYTE 63, 63,  5, 63, 63,  6, 63, 63,  7, 63, 63,  8, 63, 63,  9, 63, 63, 10
            BYTE 63, 63, 10, 63, 63, 11, 63, 63, 12, 63, 63, 13, 63, 63, 14, 63, 63, 15
            BYTE 63, 63, 16, 63, 63, 17, 63, 63, 18, 63, 63, 19, 63, 63, 20, 63, 63, 21
            BYTE 63, 63, 21, 63, 63, 22, 63, 63, 23, 63, 63, 24, 63, 63, 25, 63, 63, 26
            BYTE 63, 63, 27, 63, 63, 28, 63, 63, 29, 63, 63, 30, 63, 63, 31, 63, 63, 31
            BYTE 63, 63, 32, 63, 63, 33, 63, 63, 34, 63, 63, 35, 63, 63, 36, 63, 63, 37
            BYTE 63, 63, 38, 63, 63, 39, 63, 63, 40, 63, 63, 41, 63, 63, 42, 63, 63, 42
            BYTE 63, 63, 43, 63, 63, 44, 63, 63, 45, 63, 63, 46, 63, 63, 47, 63, 63, 48
            BYTE 63, 63, 49, 63, 63, 50, 63, 63, 51, 63, 63, 52, 63, 63, 52, 63, 63, 53
            BYTE 63, 63, 54, 63, 63, 55, 63, 63, 56, 63, 63, 57, 63, 63, 58, 63, 63, 59
            BYTE 63, 63, 60, 63, 63, 61, 63, 63, 62, 63, 63, 63
 
    screen BYTE xVal * yVal dup (?)                ; Virt. Bildschirm (nach der palette!)
 
.code
main PROC
    mov ax, @data
    mov ds, ax
 
    call SetUpScreen
    mov seed, 7895h
    mov si, OFFSET screen
    mov cx, LENGTHOF screen
    xor ax, ax
    rep stosb                  ; Leere den Bildschirm.
 
ML1:                           ; Das nächste Bit gibt entweder 0 oder 255 entlang der
    mov si, OFFSET screen      ; untersten Reihe des virtuellen Bildschrims aus.
    add si, LENGTHOF screen
    sub si, xVal               ; SI=OFFSET(screen)+LENGTHOF(screen)-xVal. Letzte Reihe
    mov cx, xVal               ; Wiederhole die komplette letzte Reihe
    xor dx, dx
 
L1:
    call Randomize             ; Erzeuge Zufallswerte
    mov ds:[si], dl
    inc si
    dec cx
    jnz L1
 
    mov cx, LENGTHOF screen    ; Mildere die Werte im virtuellen Array ab,
    sub cx, xVal               ; so dass ein sanfter Feuereffekt entsteht
    mov si, OFFSET screen
    add si, xVal
 
L3:
    xor ax, ax
    mov al, ds:[si]
    add al, ds:[si+1]
    adc ah, 0
    add al, ds:[si-1]
    adc ah, 0
    add al, ds:[si+xVal]
    adc ah, 0
    shr ax, 2
    jz ZERO                    ; Am Ende?
    dec ax
 
ZERO:
    mov ds:[si-xVal], al       ; AL=((pos)+(pos+1)+(pos-1)+(pos+80))/4 - 1
    inc si
    dec cx
    jnz L3
    mov dx, 3DAh               ; VGA-Ausgabe
 
L4: in  al, dx
    and al, 8h
    jnz L4
 
L5: in  al, dx
    and al, 8h
    jz  L5
 
    mov cx, LENGTHOF screen
    shr cx, 1
    mov si, OFFSET screen
    xor di, di
    rep movsw
 
    mov ah, 11h                ; Überprüfe den Tastaturpuffer
    int 16h                    ; Wurde eine Taste gedrückt (ZF)?
    jz ML1                     ; Nein, mache weiter
 
    call RestoreVideoMode      ; Warte auf Tastendruck, stelle VM wieder her
    mov ah, 9                  ; Ausgabe eines $-terminierter Strings
    mov dx, OFFSET urlmessage  ; DS:DX = Segment/Offset des Strings
    int 21h
 
    mov ah, 10h                ; Warte auf Tastendruck
    int 16h
 
    mov ax, 4C00h              ; Beende das Programm samt Exit Code
    int 21h                    ; Gebe die Kontrolle wieder an DOS zurück
main ENDP
 
 
;----------------------------------------------------------
; Randomize
; Diese Prozedur erzeugt Zufallswerte für den bewegenden
; Feuereffekt.
;----------------------------------------------------------
Randomize PROC NEAR
    mov ax, seed               ; Initialisiere
    mov dx, 8405h
    mul dx                     ; DX:AX = AX * DX
    inc ax
    mov seed, ax
    ret
Randomize ENDP
 
;----------------------------------------------------------
; SetUpScreen
; Diese Prozedur bereitet den Bildschrim vor. Mithilfe der Prozedur
; SetVideoMode wird der Video-Modus umgeschaltet. Die Werte
; an Port 3C8h gesendet, zeigen welche Video Palette geändert wird.
;----------------------------------------------------------
SetUpScreen PROC NEAR
    call SetVideoMode          ; Schalte in den Mode 13h, 320 x 200, 256 Farben
    cli                        ; Leere die Interrupt Flags (Clear Interrupt Flag)
    cld
    mov dx, 3C4h
    mov ax, 604h
    out dx, ax
    mov ax, 0F02h
    out dx, ax
    xor ax, ax
    mov cx, 32767
    rep stosw                  ; Leere den Bildschirm
    mov dx, 3D4h
    mov ax, 14h                ; Deaktiviere DWORD-Modus
    out dx, ax
    mov ax, 0E317h             ; Aktiviere Byte-Modus
    out dx, ax
    out dx, ax
    mov ax, 00409h             ; Zellenhöhe
    out dx, ax
 
    mov si, OFFSET palette
    mov dx, 3C8h               ; Video Paletten Port
    mov al, 0                  ; Setze den Palettenindex
    out dx, al                 ; Beginne bei der Farbe null
    inc dx
    mov cx, 768
 
PLOOP:
    outsb                      ; Stringausgabe seitens ES:(E)DI auf Port zeigend
    dec cx
    jnz PLOOP
    ret
SetUpScreen ENDP
 
;----------------------------------------------------------
; SetVideoMode
; Diese Prozedur speichert den aktuellen Video-Modus, schaltet
; in einen neuen Modus und zeigt ES auf das Video Segment.
;----------------------------------------------------------
SetVideoMode PROC
    mov ah, 0Fh                ; Empfange den aktuellen current Video-Modus
    int 10h
    mov saveMode, al           ; Speichere den Modus
 
    mov ah, 0                  ; Setze den Video-Modus
    mov al, 13h                ; auf Modus 13h
    int 10h
 
    push 0A000h                ; Video Segment Adresse
    pop es                     ; ES = A000h (Video Segment).
 
    ret
SetVideoMode ENDP
 
;----------------------------------------------------------
; RestoreVideoMode
; Diese Prozedur wartet auf die Betätigung einer Taste und
; stellt den Video Modus wieder her.
;----------------------------------------------------------
RestoreVideoMode PROC
    mov ah, 10h                ; Warte auf Tastendruck
    int 16h
    mov ah, 0                  ; Resete den Video-Modus
    mov al, saveMode           ; auf den gespeicherten Video-Modus.
    int 10h
    ret
RestoreVideoMode ENDP
 
END main


Zuletzt aktualisiert am Samstag, den 22. Mai 2010 um 17:08 Uhr
 
AUSWAHLMENÜ