Bildschirm mit Farben füllen - wie geht das?



  • Ich habe ein kurzes Programm in Assembler geschrieben.
    Es soll den Bildschirm in allen 256 Farben füllen.
    Leider tut es das nicht ganz, denn es werden nur ca. 4 Farben angezeigt.
    Ich habe ein ähnliches Programm geschrieben, das den Bildschirm nur einmal füllt und zwar mit einer anderen Farbe in jeder Zeile. Das klappt überragend und zeigt einen gangen Schirm voller prächtiger Farben.
    Aber wenn ich den Schirm in 256 Durchgängen mit je einer Farben ganz (d.h. es sind ca. 75% ) fülle, dann bricht das Programm nach der 4. Farbe ab.
    Ich kann leider keinen Fehler finden. Denn an den Port Befehlen liegt es wohl kaum, da das ja schon mal geklappt hat und einen Schleifenfehler oder sowas ähnliches finde ich nicht.
    Wer kann mir helfen?

    --------------------------------------------------------------------------------

    Data SEGMENT WORD 'DATA'
    Msg DB 13,10,'Nun wird gleich der Video-Grafik Modus eingeschaltet ! Danach wird der Bildschirm direkt mit Maschinensprache beschrieben! (Schnell, wa?) ',13,10,'Msg2DB13,10,ZurueckimTextmodusSchnell,gell?!!,13,10,' Msg2 DB 13,10,'Zurueck im Textmodus - Schnell, gell? !! ',13,10,''
    Warten1 DW 0
    Farbe DW 0
    Farbe1 DB 0
    Fuell DW 12*256*16
    Data ENDS

    Code SEGMENT BYTE 'CODE'
    ASSUME CS:CODE, DS:DATA
    Start: mov ax, DATA ; Segmentgrenze des Segmentes DATA in AX
    mov ds, ax ; AX in DS kopieren -> Segmentgrenze in DS
    mov dx,OFFSET Msg ; Offset des "Labels" Msg in DATA in DX
    mov ah, 009h ; AH mit Wert 9 belegen
    int 021h ; Interrupt $21 aufrufen

    CALL Warten

    mov ax, 00013h
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 100
    mov cx, 100
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 102
    mov cx, 100
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 101
    mov cx, 101
    int 010h

    mov dx,3ceh
    mov ax,04005h
    out dx,ax
    mov al,0003h
    out dx,ax
    mov ax,00108h
    out dx,ax
    mov ax,0f00h
    out dx,ax
    mov ax,0f01h
    out dx,ax

    mov dx,0a000h
    mov es,dx
    mov di,00000h
    Fuellen:
    mov ax,es:di
    xor ax,0ffffh
    mov es:di,ax
    add di,002h
    cmp di, Fuell
    jne Fuellen

    sub Fuell, 2

    mov di,0

    mov dx,03ceh
    mov ax,00008h
    mov ah,Farbe1
    out dx,ax

    add Farbe1,1
    cmp Farbe1,0
    jne Fuellen

    CALL Warten

    mov ax, 00003h
    int 010h

    mov ax, DATA ; Segmentgrenze des Segmentes DATA in AX
    mov ds, ax ; AX in DS kopieren -> Segmentgrenze in DS
    mov dx,OFFSET Msg2 ; Offset des "Labels" Msg in DATA in DX
    mov ah, 009h ; AH mit Wert 9 belegen
    int 021h ; Interrupt $21 aufrufen

    Ende: mov ah, 04Ch ; Funktion 4Ch
    int 021h ; Interrupt 21

    Warten PROC near
    mov Warten1,0
    Schleife:
    mov ax, 0
    Schleife2:
    add ax,1
    cmp ax, 0fff0h ; ein wenig
    jne Schleife2 ; warten
    add Warten1,1
    cmp Warten1, 064e0h ; ein wenig
    jne Schleife ; warten
    ret

    Warten ENDP

    Code ENDS

    END Start



  • Was sollen die ganzen Operationen zw. initialisieren des Mode 13 und dem eigentl. Füllen?
    Habe auch mal so ein Programm geschrieben, sa in etwa so aus (ohne Funktionsgarantie 🙂 ):

    ScreenSize        equ 320 * 200
    ScreenAddrSeg     equ 0A00h
    ScreenAddrOff     equ 0000h
    ScreenMode        equ 13h
    ScreenModeIntFunc equ 00h
    ScreenModeInt     equ 10h
    Color             equ 0F0h ;nur so als Bsp.
    
    ExitCode          equ 4C00h
    ExitInt           equ 21h
    ;----------------
    start:
     mov ax,(ScreenModeIntFunc<<8)+ScreenMode
     int ScreenModeInt
    
     mov cx, ScreenSize/4
     mov ax, ScreenAddrSeg
     mov es, ax
     mov di, ScreenAddrOff
     mov eax, Color<<24+Color<<16+Color<<8+Color
     rep stosd
    
    exit:
     mov ax, ExitCode [edit]upsy, hier war bis gerade noch ein Fehler, Dank an Nobuo T[/edit]
     int ExitInt
    

    [ Dieser Beitrag wurde am 04.11.2002 um 16:30 Uhr von -bg- editiert. ]

    [ Dieser Beitrag wurde am 25.11.2002 um 15:36 Uhr von -bg- editiert. ]



  • @-bg-: es geht auch umstaendlich, oder? 😃
    Ausserdem gehoert der Parameter fuer int 21h in ax. 😉

    @<EricFa>:
    aehm, ja, was sollen diese ganzen Kommandos an den Graphic-Controller genau bewirken?
    Bin irgendwie zu faul meine VGA-Referenz nochmal durchzuwuehlen 🙄



  • Da sind noch die Befehle, um die drei blauen Punkte auf den Bildschirm zu schreiben. Die sind noch von vorherigen versuchen da geblieben und haben eigentlich keine Funktion.
    Dann sind da noch die Portbefehle:

    mov dx,3ceh Graphics Controller adressieren
    mov ax,04005h Graphics Mode (ups da sit ja 'ne Null zu viel- sollte es das sein?)
    out dx,ax
    mov al,0003h function select
    out dx,ax
    mov ax,00108h bit mask
    out dx,ax
    mov ax,0f00h set/reset - Farbwert
    out dx,ax
    mov ax,0f01h enable set/reset
    out dx,ax



  • Dieses Programm, ein etwas älteres funktioniert.
    Es füllt den Schirm in allen 256 Farben mit je einer Farbe pro Zeile.

    Data SEGMENT WORD 'DATA'
    Msg DB 13,10,'Nun wird gleich der Video-Grafik Modus eingeschaltet ! Danach wird der Bildschirm direkt mit Maschinensprache beschrieben! (Schnell, wa?) ',13,10,'Msg2DB13,10,ZurueckimTextmodusMannwardaseinelahmeBIOSFunktion!!!,13,10,' Msg2 DB 13,10,'Zurueck im Textmodus - Mann war das eine lahme BIOS Funktion !!! ',13,10,''
    Warten DW 0
    Farbe DW 0
    Farbe1 DB 0
    Linie DW 0
    Data ENDS

    Code SEGMENT BYTE 'CODE'
    ASSUME CS:CODE, DS:DATA
    Start: mov ax, DATA ; Segmentgrenze des Segmentes DATA in AX
    mov ds, ax ; AX in DS kopieren -> Segmentgrenze in DS
    mov dx,OFFSET Msg ; Offset des "Labels" Msg in DATA in DX
    mov ah, 009h ; AH mit Wert 9 belegen
    int 021h ; Interrupt $21 aufrufen

    mov Warten,0
    Schlei_2te:
    mov ax, 0
    Schleife:
    add ax,1
    cmp ax, 0fff0h ; ein wenig
    jne Schleife ; warten
    add Warten,1
    cmp Warten, 044e0h ; ein wenig
    jne Schlei_2te ; warten

    mov ax, 00013h
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 100
    mov cx, 100
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 102
    mov cx, 100
    int 010h

    mov ax, 00c01h
    mov bh, 00
    mov dx, 101
    mov cx, 101
    int 010h

    mov dx,3ceh
    mov ax,04005h (hier sind es auch 4005 muesste also OK sein)
    out dx,ax
    mov al,0003h
    out dx,ax
    mov ax,00008h
    out dx,ax
    mov ax,0f00h
    out dx,ax
    mov ax,0f01h
    out dx,ax

    mov dx,0a000h
    mov es,dx
    mov di,00000h
    Fuellen:
    mov ax,es:di
    xor ax,0ffffh
    mov es:di,ax
    add di,002h
    add Linie,1
    cmp Linie,160
    jne Fuellen
    mov Linie,0

    mov dx,3ceh
    mov ax,00008h
    mov ah,Farbe1
    out dx,ax

    add Farbe1,1
    cmp Farbe1,190
    jne Fuellen

    mov Farbe,0
    Schleife3_3:
    mov dx, 1
    Schleife3_2:
    mov cx, 1
    Schleife3_1:
    mov ax,Farbe
    add ax, 00c00h
    mov bh, 00
    ; int 010h
    add cx, 1
    cmp cx, 300
    jne Schleife3_1
    add dx, 1
    cmp dx, 200
    jne Schleife3_2
    add Farbe,1
    cmp Farbe,258
    jne Schleife3_3

    mov Warten,0
    Schlei2_2te:
    mov ax, 0
    Schleife2:
    add ax,1
    cmp ax, 0fff0h ; ein wenig
    jne Schleife2 ; warten
    add Warten,1
    cmp Warten, 0e4e0h ; ein wenig
    jne Schlei2_2te ; warten

    mov ax, 00003h
    int 010h

    mov ax, DATA ; Segmentgrenze des Segmentes DATA in AX
    mov ds, ax ; AX in DS kopieren -> Segmentgrenze in DS
    mov dx,OFFSET Msg2 ; Offset des "Labels" Msg in DATA in DX
    mov ah, 009h ; AH mit Wert 9 belegen
    int 021h ; Interrupt $21 aufrufen

    Ende: mov ah, 04Ch ; Funktion 4Ch
    int 021h ; Interrupt 21

    Code ENDS

    END Start



  • Niemand hier, der sich auskennt?



  • was hast du denn für ein OS, also wo läuft dein Prog?
    könntest du vielleicht nochmal die Wesentlichen Teile aufzeigen (also ohne überflüssige I/Os)?
    Funktionieren denn die anderen Varianten die wir aufgezeigt haben bei dir?

    mfg
    -bg-



  • Hier ist der wesentliche Teil mit den Portbefehlen und der Füllroutine.
    Hoffe es ist ausführlich genug beschrieben.

    mov dx,3ceh Graphics Controller
    mov ax,04005h Graphics Mode -> VGA 256 Farben Modus
    out dx,ax
    mov al,0003h Funktion Select -> keine Verknüpfung
    out dx,ax
    mov ax,00108h Bit Mask -> 1 für Farbe 2
    out dx,ax
    mov ax,0f00h Set/Reset -> alle 4 Bitplanes
    out dx,ax
    mov ax,0f01h Enable Set/Reset -> alle 4 Bitplanes
    out dx,ax

    mov dx,0a000h Adresse Bitmaps
    mov es,dx
    mov di,00000h Erste Speicherstelle
    Fuellen:
    mov ax,es:di word aus Bitmap lesen
    xor ax,0ffffh Farbe in Bits umrechnen
    mov es:di,ax und in den Speicher schreiben
    add di,002h nächstes word
    cmp di, Fuell diese Farbe schon fertig?
    jne Fuellen

    sub Fuell, 2 bei der nächsten Farbe 2 Byte weniger malen

    mov di,0 Index zurücksetzten

    mov dx,03ceh Graphics controller
    mov ax,00008h Bitmask
    mov ah,Farbe1 Farbwert
    out dx,ax in den port schreiben

    add Farbe1,1 erhöhten Farbwert merken
    cmp Farbe1,0 alle Farben durch?
    jne Fuellen



  • Mal abgesehen davon, dass ich diese Methode, bestimmte Farben zu setzen fuer "etwas" umstaendlich halte, verstehe ich diese Zeilen noch net so ganz:

    Original erstellt von <wesentliche Teile>
    **mov ax,es:di word aus Bitmap lesen
    xor ax,0ffffh Farbe in Bits umrechnen
    mov es:di,ax und in den Speicher schreiben
    **

    Waere es nicht sinnvoller, den Speicher stattdessen einfach immer wieder auf FFh zu setzen?
    So funktionierte das ganze bei mir zumindest schon so ungefaehr... Aus irgendeinem Grund lieferten 3 Bitplanes aber komische Farbwerte zurueck... 😕
    Die Schleife zur Aktualisierung des Speichers sollte so zumindest funktionieren...



  • Mal abgesehen davon, dass ich diese Methode, bestimmte Farben zu setzen >fuer "etwas" umstaendlich halte, verstehe ich diese Zeilen noch net so ganz:
    Habe das für spätere Zwecke so gemacht, falls ich die vorhadenen Punkte noch mit umsetzen will.
    Original erstellt von <wesentliche Teile>
    mov ax,es:di word aus Bitmap lesen
    xor ax,0ffffh Farbe in Bits umrechnen
    mov es:di,ax und in den Speicher schreiben
    Liest verknüpft und schreibt wieder zurück in den Grafikspeicher.
    Waere es nicht sinnvoller, den Speicher stattdessen einfach immer wieder auf >FFh zu setzen?
    Ja, mov ax,0ffffh wäre auch ok. Bringt aber im Endeffekt dasselbe.
    So funktionierte das ganze bei mir zumindest schon so ungefaehr... Aus
    Wie ungefähr?
    irgendeinem Grund lieferten 3 Bitplanes aber komische Farbwerte zurueck...
    3? Das sind 4 Bitplanes.
    Die Schleife zur Aktualisierung des Speichers sollte so zumindest >funktionieren...
    Wie oben schon gesagt. Das eine Programm, das so ähnlich ist, funktioniert.
    Es füllt aber jede Zeile mit einer anderen Farbe. Bisher habe ich es noch nicht richtig hinbekommen, dass der Prozessor den gesamten Bildschirm mit nur einer Farbe korrekt füllt.
    Da ein Farbpunkt korrekt gesetzt wird muss es anversich an der Schleife und an den Weiterzähl-Befehlen liegen.



  • Weiss keiner Bescheid?


Anmelden zum Antworten