Autor Thema: Grafik im Real-Mode  (Gelesen 5355 mal)

TPSeverino

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« am: 11. August 2004, 12:08 »
Hi,
ich hab mir aus Spaß und Interesse eine kleine Grafikdemo im Real-Mode gebastelt. Dazu hab ich den Grafik-Modus 13h (320*200, 256 Farben) benutzt. Mein Ziel war es einen Interpolationseffekt zu erzeugen. Für alle die nicht wissen was ich meine, erklär ich es mal. Ich hab die Farbpalette über Ports mit 240 Farben belegt, wobei Eintrag 0 schwarz ist und die Palette mit aufsteigenden Einträgen dunkelrot, hellrot, gelb und bei Eintrag Nummer 240 schließlich mit weiß belegt ist. Wenn ich jetzt ein weißes Objekt zeichne und der Interpolationseffekt anwende, entsteht eine Art Feuereffekt. Ist keine neue Sache, aber ich wollte es halt mal machen.
Mein Problem ist die Geschwindigkeit der Interpolationsroutine. Ich habe vor Jahren den gleichen Algorithmus mit Pascal umgesetzt und es lief auf einem 60 MHz - Rechner recht gut. Jetzt mit NASM und auf einem 2,7 GHz - Rechner, kann ich die Durchgänge fast mitzählen. Vielleicht hab ich irgendwas verhauhen. Hier ist der Quelltext des Interpolationsalgorithmus:

   
.start:
mov ax, 0a000h            ; Segment-Adresse vom Bildschirmspeicher
mov es, ax                    ; nach es schreiben
mov si, 0                    ; si auf null setzen -> Anfang des Bildschirmspeichers
mov cx, 64000           ; Zähler auf 64000 -> jeder Punkt

.loop:
xor dx, dx           ; dx auf null setzen
xor ax, ax                   ; ax auf null setzen
mov al, [es:si-1]          ; Farbwert des linken Punktes nach al
mov dl, [es:si+1]         ; Farbwert des rechten Punktes nach al
add ax, dx                  ; Beide Werte addieren, Ergebnis in ax
mov dl, [es:si-320]      ; Farbwert des oberen Punktes nach dl
add ax, dx                  ; und zu ax addieren
mov dl, [es:si+320]      ; Farbwert des unteren Punktes nach dl
add ax, dx                  ; und zu ax addieren
shr ax, 2              ; Summenfarbwert in ax durch 4 teilen
or ax, ax              ; Flags setzen
jz .zero              ; Wenn ax = 0, springe zu .zero
dec ax              ; Wenn ax nicht null, um eins erniedrigen

.zero:
mov [es:si], al           ; neuen Farbwert setzen
inc si                 ; si erhöhen -> nächster Punkt
dec cx                      ; Zähler erniedrigen
jnz .loop                   ; Solange Zähler nicht 0, springe zu .loop

mov ah, 01h               ; Funktion zur Überprüfung des Tastaturpuffers
int 16h             ; Wenn ZF = 1 dann ist kein Zeichen vorhanden
jz .start             ; Wenn kein Taste gedrückt, dann nächster Durchgang

       
Noch mal zur Erklärung: Der Algorithmus berechnet für jeden der 64000 Bildpunkte den Farbwert aus den 4 angrenzenden Punkten, indem ein Mittelwert ihrer Farbwerte gebildet wird und dieser um eins erniedrigt wird.
thx for your help!!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #1 am: 11. August 2004, 17:31 »
Falls du es in Bochs laufen lässt ist natürlich da klar das die Emulation derb langsam ist. Wenn nicht versuchs mal damit laufen zu lassen da lassen sich performancefrsser manchmal finden. Der Interrupt wird einiges an Zeit fressen, Biosint's sind verdammt langsam, weil die ja mit allem Kompatibel sein müssen. Ganz am Ende den Sprung jz .start könntest du ändern also das Sprungziel nich ganz vor, sondern nach mov es,ax denn es ändert sich nicht, so hast du bei jedem durchlauf ein paar takte mehr. Dann nach .zero:
das mov [es:si],al  inc si würde ich durch stosb ersetzten der Befehl ist um einiges schneller als die andern beiden, also wieder ein paar takte, und nochwas ganz am Anfang das mov si,0 mach ein xor si,si draus ist auch etwas ersparniss, ist zwar alles nicht viel aber immerhin er bringt was
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

TPSeverino

  • Beiträge: 33
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 18. August 2004, 22:43 »
Also wen es interessiert, ich habs! Wenn man direkt in den Videospeicher an der Adresse 0a000h schreibt, scheint das enorme Geschwindigkeitseinbußen zu bringen. Als Lösung schreibt man die Daten an eine andere Adresse im Speicher und kopiert diesen Bereich anschließend mit movsw. In meinem Fall hat es die Ausführung mindestens um das 30-fache (wenn nicht weit mehr) beschleunigt.

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #3 am: 19. August 2004, 18:10 »
Jap da haste recht, hätt ich auch drauf kommen können. die Addi a0000h ist direkt mit dem Video Ram gekoppelt und der ist schweinelangsam^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

 

Einloggen