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
Vaikka tästä taitaa olla hyötyä aika harvalle (kovin moni ei taida käyttää Assemblyä), on kuitenkin kiva saada lisää Assembly-koodivinkkejä.
Harmi vaan, että nuo ääkköset ovat muuntuneet tuolla lailla.
Nyt ääkköset näkyvät oikein täällä, mutta DOS-editorissa ne täytyy muuttaa.
Sinä se oot sitten monipuolinen näitten kielten suhteen :)
Loistava ohjelma.
Aihe on jo aika vanha, joten et voi enää vastata siihen.