Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Assembly: BMP-kuva assemblyllä

Antti Laaksonen [31.01.2004 01:01:43]

#

Tässä on parannettu versio taannoisesta assembly-kielisestä BMP-kuvan näyttäjästä. Perusidea on pysynyt ennallaan: ohjelma näyttää ruudulla 320x200-kokoisen 256-värisen BMP-kuvan. VGA-tilassa tällainen kuva on koko ruudun kokoinen. Ohjelmassa ei ole virheentarkistusta, mutta pahin mahdollinen seuraus vääränmuotoisesta tiedostosta lienee ruudulle tuleva pikselisekasotku. Kommentteja pyrin laittamaan niin paljon, ettei mikään asia jäisi epäselväksi. Ohjelma kääntyy TASMilla ja varmaan pienten muutosten jälkeen MASMillakin.

; 256-värisen 320x200-kokoisen BMP-kuvan näyttäminen
   ; tekijä Antti Laaksonen, kääntyy TASMilla
   DOSSEG
   .MODEL SMALL
   .STACK 100h
   .DATA
   ; näytettävän kuvan hakemistopolku ja tiedostonimi,
   ; käytetään myöhemmin paletin värien tallentamiseen
tieto db 'c:\antti\320200.bmp$', 0, '$'
   .CODE
   ; dataosion aloituskohta segmenttirekisteriin ds
   ; ja tieto-muuttujan aloituskohta rekisteriin dx
   mov ax, @data
   mov ds, ax
   mov dx, OFFSET tieto

   ; siirrytään 256 värin grafiikkatilaan:
   ;   o keskeytys 10h
   ;   o ah = 00h
   ;   o al = näyttötila = 13h = 320x200x256
   mov ax, 0013h
   int 10h

   ; avataan tiedosto:
   ;   o keskeytys 21h
   ;   o ah = 3dh
   ;   o al = avaustapa = 00h = lukeminen
   ;   o ds:dx = osoitin tiedostonimeen
   ;   o palauttaa ax = tiedostokahva
   mov ax, 3d00h
   int 21h
   ; siirretään saatu tiedoston kahva bx:ään
   mov bx, ax

   ; siirrytään tiedostossa paletin alkuun:
   ;   o keskeytys 21h
   ;   o ah = 42h
   ;   o al = siirtokohdan alku = 00h = tiedoston alku
   ;   o bx = tiedostokahva
   ;   o cxdx = siirroksen suuruus tavuina
   mov ax, 4200h
   mov cx, 0
   mov dx, 36h
   int 21h

   ; -- PALETTI -----------------------------------------------
   ; BMP-kuvan 256-värinen paletti on tallennettu kuvaan niin,
   ; että jokainen väri vie neljä tavua. Puna-, viher- ja
   ; sinisävyn lisäksi jokaisen värin kohdalla on yksi ylimää-
   ; räinen tavu, josta ei tarvitse välittää. Värit on tallen-
   ; nettu järjestyksessä sininen, vihreä ja punainen.
   ;
   ; Koko VGA-paletin muuttaminen tapahtuu lähettämällä ensin
   ; porttiin 03c8h tavu 0 ja sitten porttiin 03c9h kaikkien
   ; värien RGB-arvot perätysten. Täytyy tosin ottaa huomioon,
   ; että VGA-paletissa värisävyjen on oltava välillä 0 - 63
   ; kun taas BMP-formaatissa ne ovat 0 - 255. Siksi väriarvot
   ; jaetaan neljällä.
   ; ----------------------------------------------------------

   ; lähetetään porttiin 03c8h tavu 0
   mov dx, 03c8h
   mov al, 0
   out dx, al
palalku:
   ; cx on tiedostokahvan siirtämisen jäljiltä nolla;
   ; nyt sitä käytetään laskurimuuttujana
   ; siksi rekisteri täytyy laittaa talteen pinoon
   ; tiedostonluvun ajaksi
   push cx
   ; luetaan tiedostosta neljä tavua, seuraava väriarvo
   mov ah, 3fh
   mov cx, 04h
   mov dx, OFFSET tieto
   int 21h
   ; tästä sijoituksesta on hyötyä, kun rekisterin arvo
   ; kohta täytyy jakaa neljällä
   mov cl, 2
   ; porttiin 03c9h lähetetään väriarvot
   mov dx, 03c9h
   ; ensin lähetettävänä on punainen arvo, BMP-paletissa
   ; se oli tallennettu viimeiseksi
   mov al, [tieto+2]
   ; neljällä jakaminen vastaa bittien siirtoa kahdesti
   ; oikealle (tämä on paljon nopeampaa kuin divin käyttö)
   shr al, cl
   ; lähetetään punainen väri porttiin 03c9h
   out dx, al
   mov al, [tieto+1]
   shr al, cl
   ; lähetetään vihreä väri porttiin 03c9h
   out dx, al
   mov al, [tieto]
   shr al, cl
   ; lähetetään sininen väri porttiin 03c9h
   out dx, al
   ; palautetaan laskurimuuttuja
   pop cx
   ; tarkastetaan, onko laskurimuuttujan arvo 255 eli
   ; onko kaikki paletin värit jo asetettu
   cmp cl, 255
   ; kasvatetaan laskurin arvoa ensi kierrosta varten
   inc cl
   ; palataan alkuun jos laskuri ei vielä ole lopussa
   jne palalku

   ; -- KUVADATA -----------------------------------------------
   ; BMP-formaatissa kuva on tallennettu hieman eri tavalla
   ; kuin näyttömuistissa. Ensin on näet tallennettu alimman
   ; rivin pikselit, sitten toisiksi alimman jne. Tiedostosta
   ; pikselit on näppärää lukea suoraan näyttömuistiin
   ; rivi kerrallaan. Siksi silmukkarekisterin arvo vähenee
   ; joka kierroksella 320:lla.
   ; -----------------------------------------------------------

   ; laitetaan segmenttirekisteriin näyttömuistin aloitusosoite
   ; ja dx-rekisteriin viimeisen rivin osoite (rivejä on 200,
   ; jokaisella rivillä on 320 merkkiä ja ensimmäinen rivi alkaa
   ; nollasta => 199 * 320 = 63680)
   mov ax, 0a000h
   mov ds, ax
   mov dx, 63680
   ; laitetaan cx:ään valmiiksi tiedostosta kerrallaan luettavien
   ; tavujen määrä eli 320 eli yhden rivin pikselit
   mov cx, 320
uusirivi:
   ; luetaan tiedostosta 320 pikseliä näyttömuistiin
   mov ah, 3fh
   int 21h
   ; vähennetään laskurin arvoa 320:lla -> rivi ylös
   sub dx, 320
   ; jatketaan kunnes laskuri saavuttaa nollan
   cmp dx, 0
   jne uusirivi

   ; suljetaan tiedosto:
   ;   o keskeytys 21h
   ;   o ah = 3eh
   ;   o bx = tiedostokahva
   mov ah, 3eh
   int 21h

   ; odotetaan näppäimenpainallusta:
   ;   o keskeytys 16h
   ;   o ah = 00h
   ;   (palauttaa:
   ;   o ah = näppäimen scan-koodi
   ;   o al = näppäimen ASCII-koodi)
   mov ah, 00h
   int 16h

   ; palataan takaisin tekstitilaan:
   ;   o keskeytys 10h
   ;   o ah = 00h
   ;   o al = näyttötila = 03h = tekstitila 80x25
   mov ax, 0003h
   int 10h

   ; suljetaan ohjelma:
   ;   o keskeytys 21h
   ;   o ah = 4ch
   ;   (o al = palautusarvo)
   mov  ah,4ch
   int  21h

   END

KimmoKM [31.01.2004 11:09:23]

#

Vaikka tästä taitaa olla hyötyä aika harvalle (kovin moni ei taida käyttää Assemblyä), on kuitenkin kiva saada lisää Assembly-koodivinkkejä.

arcatan [31.01.2004 13:00:23]

#

Harmi vaan, että nuo ääkköset ovat muuntuneet tuolla lailla.

Antti Laaksonen [31.01.2004 13:30:19]

#

Nyt ääkköset näkyvät oikein täällä, mutta DOS-editorissa ne täytyy muuttaa.

AK [31.01.2004 14:22:49]

#

Sinä se oot sitten monipuolinen näitten kielten suhteen :)

ZcMander [10.02.2005 18:27:38]

#

Loistava ohjelma.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta