Grafik aus einem String lesen und anzeigen
-
Hallo
Ich habe mir eine Kernel geschrieben, die eine Grafik anzeigen soll.
Dazu wechsle ich erst in den VGA-Modus und lese dann die Grafik aus
einm String aus.
Das hat soweit auch gut funktioniert. Nur ist die Grafik extrem groß.Also habe ich das Bild mit hilfe eines schnell geschriebenen C++ Proggs
in Binäre Daten umgewandelt. Eins = Pixel wird gesetzt, Null = Kein Pixel wird gesetzt.Leider funzt das ganze nicht so wirklich
Code: (Bitte nicht meckern, hab erst seit kurzem mit ASM angefangen
)
;PARAMS: ; AX = BILDHÖHE ; BX = BILDBREITE ; ES:DI = ADRESSE DES GRAFIK-STRINGS ;-------------------------------------------------------------------------- putCompressedBMPString: mov cx,0 mov dx,0 jmp .cBMP_loop .cBMP_NextLine inc cx cmp cx,ax jz .cputBMP_end mov dx,0 jmp .cBMP_loop .SetP mov al,7 call putpixel jmp bx ;MAIN-LOOP .cBMP_loop push ax LODSB push bx inc dx mov bx,.Go1 test ah,10000000b jne .SetP .Go1 inc dx mov bx,.Go2 test ah,010000000b jne .SetP .Go2 inc dx mov bx,.Go3 test ah,001000000b jne .SetP .Go3 inc dx mov bx,.Go4 test ah,000100000b jne .SetP .Go4 inc dx mov bx,.Go5 test ah,00001000b jne .SetP .Go5 inc dx mov bx,.Go6 test ax,00000100b jne .SetP .Go6 inc dx mov bx,.Go7 test ax,00000010b jne .SetP .Go7 inc dx mov bx,.Go8 test ax,00000001b jne .SetP .Go8 pop bx pop ax cmp dx,bx jz .cBMP_NextLine jmp .cBMP_loop .cputBMP_end ret ;PARAMS: ; AL = FARBE ; CX = Y ; DX = X ;-------------------------------------------------------------------------- putpixel: push es push bx mov bx , 0xa000 mov es , bx mov bx , ax mov ax , 320 push dx mul cx pop dx add ax , dx xchg bx , ax mov [es:bx],al pop bx pop es ret
-
; ES:DI = ADRESSE DES GRAFIK-STRINGS
Meintest du hier vielleicht ds:si (von dieser Adresse laedt lods)?
BTW:
Diese ganzen tests koenntest du auch in einer Schleife zusammenfassen.
Dann zB. mit shl immer ein bit oben von ah abpfluecken und gucken, ob das cf gesetzt ist, oder nicht...
Zudem ist es IMO ein bissel zu viel des guten, den Index im Bildschirmspeicher fuer jeden Pixel extra aus den Koordinaten neu zu berechnen.
Das geht auch effektiver.
-
man sollte sich auch immer ueberlegen, wann und warum man assembler einsetzen will.
jeder c-compiler macht da 10x schnelleren und kuerzeren code draus, der algorithmus waere in 5-10 zeilen formuliert gewesen und wuerde ausserdem schon funktionieren...
-
hellihjb schrieb:
man sollte sich auch immer ueberlegen, wann und warum man assembler einsetzen will.
jeder c-compiler macht da 10x schnelleren und kuerzeren code draus, der algorithmus waere in 5-10 zeilen formuliert gewesen und wuerde ausserdem schon funktionieren...Ich bitte um ein Beispiel!
-
das ist schon ziemlicher spaghetti code - und das ist gar nicht so einfach mit so in paar anweisungen
der hinweis von nabuto ist gut. auf jedenfall solltest du auf bedingte sprünge in unterprogramme (SetP) verzichten - besser ist ein normaler call und vorher ein bedingter sprung um den call herum (bei den 8bit rechnern, mit denen ich assembler gelernt habe, gabs noch bedingte calls
) - das erleichtert die lesbarkeit enorm. was oder warum es jetzt nicht funktioniert, kann ich nicht sagen ohne bessere fehlerbeschreibung. ist zwar sehr umständlich, aber für mein verständnis nicht offensichtlich falsch.
-
Ich bitte um ein Beispiel!
ungefaehr so:
// parameter: // dst: zieladresse im grafikspeicher (0xa0000 + irgendwo) // data= zeiger auf 1bit monochrom daten (jedes uchar enthaelt 8 pixel) // sizex= breite der bitmap // sizey= hoehe der bitmap void drawBitmap(uchar *dst, uchar *data, int sizex, int sizey) { uchar palette[2]={0,255}; // farbpalette mappt pixel-bit 0/1 auf vga-farben for (int y=0;y<sizey;y++) { for (int x=0;x<sizex;x+=8) // in der innerloop werden jeweils 8 pixel gefuellt { uchar p= *data++; // 8bits // geht durch alle bits des gelesenen bytes, // schreibt die dem bit entsprechende farbe in den grafikspeicher // und geht zum naechsten pixel for (int bit=0;bit<8;bit++,p>>=1) *dst++= palette[p & 1]; } // spring vom ende der jetztigen zeile zum anfang der naechsten dst+=320-sizex; } }
die trivial-implementation nimmt an, dass die breite der bitmap durch 8 teilbar ist. das unterste bit entspricht dabei dem vordersten von 8 pixeln.
sollte sich leicht 1:1 auf assembler uebertragen lassen und wird dem lehrling zur uebung ueberlassen
-
THX @ all
Leide habe ich (tatsächlich) die Absicht, ein reines ASM-Programm zu schreiben
Ich hab den Code jetzt mal etwas umgeschrieben:
;PARAMS: ; AX = BILDHÖHE ; BX = BILDBREITE ; DS:SI = ADRESSE DES GRAFIK-STRINGS ;-------------------------------------------------------------------------- putCompressedBMPString: mov cx, 0 mov dx, 0 jmp .cBMP_loop .cBMP_NextLine inc cx cmp cx, ax jz .iputBMP_end mov dx, 0 jmp .cBMP_loop ;MAIN-LOOP .cBMP_loop push ax push cx push bx push dx LODSB mov [Zahl],ax mov bh, 10000000b .iBMPloop test ah, bh jne iputpixel .iLoopA SAL bh, 1 dec word [Zahl] cmp word [Zahl],0 jz . iBMPloop pop dx pop bx pop cx pop ax cmp dx, bx jge .cBMP_NextLine jmp .cBMP_loop .iputBMP_end ret
Aufrufen tu ich meine Funktion so:
mov SI,compressedBMPString mov ax,105;HÖHE DES BILDES mov bx,144;BREITE DES BILDES call putCompressedBMPString
Jedoch sehe ich bei dieser Version keinen einzigen Pixel auf dem Bildschirm.
Außerdem scheint sich eine Endlosschleife aufgetan zu haben, da die Programmausführung
nach der putCompressedBMPString Funktion nicht fortgesetzt wird...Vielen Dank schonmal!
-
innerhalb der "iBMPloop" willst du doch fuer jedes der 8 bits eines gelesenen bytes pruefen, ob es gesetzt ist oder nicht.
dieses byte laedst du mit lodsb nach al, pruefst aber ah.
dafuer benutzt du eine bitmaske die nach dem ersten sal bh,1 nur noch 0 enthaellt.
der zaheler fuer diese schleife ist zahl. sollte da nicht 8 drinstehen? stattdessen setzt der sich aus 8 pixel-bits und dem high-byte der bildhoehe zusammen.
da stimmt doch was nicht!edit: ich habe den algorithmus mal ungetestet "aufgeraeumt"
vielleicht hilft dir das was...register: cx= breite dx= hoehe al= farbe der bitmap es:di= grafikspeicher-position (a000h:0= oben links) ds:si= adresse der bitmap putCompressedBMPString: mov bx, 320 ; x-aufloesung mode 13 sub bx, cx mov pitch, bx ; step vom ende einer scanline zum anfang der naechsten shr cx, 3 ; breite /8 .yloop push cx ; breite retten .xloop mov bh, 10000000b ; oberstes bit zuerst pruefen mov bl, [ds:si] ; 8bit laden .bitloop test bl, bh ; bit pruefen jz skip ; nicht gesetzt: keinen pixel zeichnen mov [es:di], al ; pixel setzen .skip inc di ; naechster pixel shr bh,1 ; zu pruefendes bit um 1 verschieben jnc bitloop ; widerholen solang das pruefbit nicht weggeshiftet wurde inc si ; adresse vom naechsten bitmap-byte dec cx ; breite-- jnz xloop ; wiederholen solange ungleich 0 pop cx ; breite wiederherstellen add di, pitch ; zum anfang der naechsten zeile springen dec dx ; hoehe-- jnz yloop ; wiederholen solange ungleich 0 ret
-
Vielen Dank für deine Mühe!
Leider muss ich sagen, dass es bei mir noch immer nicht funktioniert
Ich rufe deinen Code wie folgt auf:... mov cx,144 mov dx,105 mov ax,0xa000 mov [es:di],ax mov ax,compressedBMPString mov [ds:si],ax mov al,7 call putCompressedBMPString CALL WaitBIOSKey ...
Doch mein Bildschirm bleibt schwarz. Meine "Bitmap" sieht dabei so aus:
compressedBMPString db 0000000b, 0000000b, 0000000b, 0000000b, 0000000b, 0000111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1110000b, 0000000b, 0000000b, 0000000b, db 0000000b, 0000000b, 0000000b, 0000000b, 0000000b, 1111000b, 0000000b, 0111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111110b, 0000000b, 0001100b, 0000000b, 0000000b, 0000000b, db 0000000b, 0000000b, 0000000b, 0000000b, 1111111b, 1111000b, 0000000b, 0000001b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111111b, 1100000b, 0000000b, 0001111b, 1111100b, 0000000b, 0000000b, db 0000000b, 0000000b, 0000000b, 0001111b, 1111111b, 1111000b, 0000000b, 0000000b, 0011111b, 1111111b, 1111111b, 1111111b, 1111111b, 1111110b, 0000000b, 0000000b, 0001111b, 1111111b, 1100000b, 0000000b, ...
(erste 4 Zeilen)
Hoffe, ich stress dich nicht zu sehr
-
mov ax,0xa000 mov [es:di],ax
das schreibt den 16bit wert "0xa000" in die speicherstelle auf die es:di zeigt.
richtiger waere wohlmov ax,0xa000 mov es,ax mov di,0
darueber hinaus solltest du nicht davon ausgehen, dass mein code-beispiel funktioniert, denn ich hatte wenig lust einen 16bit-assembler rauszuholen
-
ich hatte wenig lust einen 16bit-assembler rauszuholen
Es funzt zwar noch immer nicht, aber vielen Dank für deine Hilfe!
P.S. Einer der Admins des Forums scheinen nicht mitbekommen zu haben,
dass es nichts bringt, mich dauernd zu bannen. Einmal den Routerstecker
gezogen, schon komm ich wieder rein.Aber da hab ich mal ne Frage: War dieser Beitrag wirklich SO schlimm?
-
@PS: Pannen passieren hier auch mal. Wenn du unbedingt registriert schreiben willst, und meinst zu unrecht gebannt worden zu sein, schlage ich vor mal eine Mail an Marc++us zu schreiben.
-
Hallo!
Ich stress schonwieder!
Ich habs jetzt soweit hinbekommen, dass (was jetzt mal völlig neu ist) keine Endlosschleife oder ein Sprung ins nichts entsteht.Die Pixelreihen werden wie gewünscht durchlaufen, aber: Es werden keine entsprechenden Pixel gesetzt
putCompressedBMPString: ;PARAMS::::::::::::::::::: mov ax, 105;HÖHE DES BILDES mov bx, 137;BREITE DES BILDES mov si, compressedBMPString ;PARAMS::::::::::::::::::: mov [XMax],bx mov [YMax],ax mov ax, 0 mov word [XPos],0 mov word [YPos],0 .pCBS_loop LODSB ;AL = Zeichen im String (8 Bit) mov cl, 0 .pCBS_Bitloop inc word [XPos] push bx mov bx, [XPos] cmp bx, word [XMax] jge .pCBS_NextLine .pCBS_ret1 pop bx test al, bl ;Vergleiche jnz .pCBS_PutPixel .pCBS_ret2 shr bl, 1 inc cl cmp cl, 7 jz .pCBS_loop jmp .pCBS_Bitloop .pCBS_NextLine push bx mov word [XPos],0 inc word [YPos] mov bx, word [YPos] cmp bx, word [YMax] pop bx jge .pCBS_End jmp .pCBS_ret1 .pCBS_PutPixel push ax push cx push dx mov al,7 mov cx, word [YPos] mov dx, word [XPos] call putpixel pop dx pop cx pop ax jmp .pCBS_ret2 .pCBS_End pop bx ret
Wenn ich statt compressedBMPString einen anderen String angebe, werden irgendwelche Punkte gesetzt (was ja normal ist), wenn ich aber compressedBMPString angebe, wird entweder alles weiß, oder alles schwarz gelassen-.- (ja nach jnz oder jz .pCBS_PutPixel).
Ich versteh nicht warum
-
ja, ganz recht! Ich bins wieder. Ich habs jetzt hinbekommen. (Hat ja auch lang genug gedauert.)
Gefehlt hat diese Befehlszeile:
mov bl, 10000000b
unter
.pCBS_loop
-
schwere geburt
-
hellihjb schrieb:
schwere geburt
In der Tat