Tm tiedosto on koottu CyberDyne Magazine:ssa ilmestyneen
'Assy Ohjelmointikurssi' -sarjan toisesta osasta. Sen
levittminen elektronisessa muodossa muuttamattomana on
sallittua ja jokainen saa omaa kyttn varten printata
sen kokonaisuudessaan tai osia siit. Sarjan toimitti
alunperin Antti Niskanen. Tmn tiedoston on koonnut
Antti Niskanen.

=====Kurssin toinen osa===============================================
=====Ilmestyi numerossa 10/94==============================================

  ķ
   Viime  kerralla opimme hieman konekielisi komentoja,  komennot MOV  ja 
   INT. Niiden avulla onnistuimme tekemn ohjelman, joka lukee nppimis- 
   tst yhden merkin ja antaa sen DOS:lle ERRORLEVEL arvona.  DOS  versio 
   6.00:sta  lhtien DOS:ssa on oma vastaava ohjelmansa,  ja  olemassa  on 
   toki parempiakin apuohjelmia,  joilla voi tehd BAT-tiedostoihin  menu- 
   rakenteita. Jatkamme silti samalla linjalla opetellessamme uudet kskyt 
   CMP, JZ ja JMP.                                                         
                                                                           
   Olettakaamme,  ett haluamme tehd BAT-tiedoston,  joka haluaa K tai  E 
   vastauksen  kysymykseen  Kyll tai Ei.   Voisimme  kytt  edellisess 
   osassa tekemmme ohjelmaa,  mutta BAT-tiedostossa joutuisimme  kytt- 
   mn  turhan montaa IF ERRORLEVEL -ksky.  Helpommalla psemme,   jos 
   teemme  ohjelman,   joka lukee nppimistst painalluksia  niin  kauan 
   kunnes painallus on  k, K, e tai E,  ja palauttaa ERRORLEVEL:in arvoksi 
   1, jos vastaus oli K tai k (kyll)  tai 0 jos vastaus oli E tai e (ei). 
   Tt varten tarvitsemme vertailukskyn.  Tm ksku on CMP. Sen rakenne 
   on seuraava:                                                            
                                                                           
       CMP <lhde1>,<lhde2>                                               
                                                                           
  ͼ

    Lhde1   ja lhde2  voivat olla vaikkapa rekisteri ja numeroarvo.   CMP
    vertaa  lhteit  ja  asettaa tiettyj lippuja  FLAGS-rekisteriss  sen
    mukaan,   kumpi lhde oli isompi vai olivatko ne  samankokoiset.   Itse
    lhteiden  arvot eivt muutu.  CMP-kskyn jlkeen voimme suorittaa  ns.
    ehdollisen  hyppykskyn,   joka suorittaa hypyn  (BASIC:in  GOTO-kskyn
    tavoin)   tiettyyn kohtaan ohjelmassa.  Ehdollisia hyppykskyj ovat JZ
    (Jump on Zero = hypp,  jos lhteet olivat yhtsuuret),  JNZ (Jump  on
    Not  Zero = hypp,  jos erisuuret),  JA (Jump on Above = hypp,   jos
    lhde1   on  suurempi),  JB (Jump on Below = hypp,   jos  lhde1   on
    pienempi)   ja ert muut,  joihin emme nyt perehdy.  On olemassa  mys
    ehdoton hyppyksky, joka hypp riippumatta siit,  mik edeltvn CMP-
    operaation tulos oli,  tai vaikka sit ei edeltisikn  CMP-operaatio.
    Ehdoton  hyppyksky  on JMP (JuMP).  Kaikilla  hyppykskyill  on  sama
    rakenne:

        JMP <osoite>
    tai
        JZ <osoite>
    jne.

  ķ
   Mutta  mik se osoite sitten on?  QuickBASIC:lla tai C:ll  osoite  voi 
   olla jokin sana tai kirjainyhdistelm,  joka on sama kuin tietyn  rivin 
   alussa oleva tunnistin, esim:                                           
     ķ                                      
      uudestaan:                                                         
      PRINT "Kauanko tt kest?"                                       
      GOTO uudestaan                                                     
     ͼ                                      
   Assemblerilla ohjelmoitaessa tehdn samalla tavalla,  mutta  DEBUG:lla 
   ohjelmoitaessa on vain jtettv hyppykskyn osoitteeksi vaikkapa 0100, 
   kirjoitettava ohjelma valmiiksi ja katsottava sitten, mik oikea osoite 
   on, ja kytv kirjoittamassa hyppykskyyn oikea osoite.                
                                                                           
   Katsommekin  nyt  haluamamme  K  vai  E  -ohjelman  ohjelmointia  askel 
   askeleelta.   Valkoisella nkyvt merkit ovat  tietokoneen  tulostamia, 
   keltaiset ovat itse kirjoitettuja.  Vihret ovat kommentteja,  niit ei 
   kirjoiteta lainkaan. (Listaus on seuraavalla sivulla)                   
  ͼ

  ķ
   C:\>debug                   ;Nin kynnistetn DEBUG                    
   -a100                       ;Alamme kirjoittamaan osoitteesta 100h       
   0BC4:0100 mov ah,08         ;Kytmme INT 21h keskeytyst arvolla AH=08h 
   0BC4:0102 int 21            ;joka lukee merkin nyttmtt sit ruudulla 
   0BC4:0104 cmp al,4b         ;Nyt vertailemme sit K:n ASCII-koodiin      
   0BC4:0106 jz 0100           ;Jos se on sama, hyppmme jonnekin          
   0BC4:0108 cmp al,6b         ;Vertailemme k:n ASCII-koodiin               
   0BC4:010A jz 0100           ;Jos se on sama, hyppmme jonnekin          
   0BC4:010C cmp al,6b         ;Vertailemme E:n ASCII-koodiin               
   0BC4:010E jz 0100           ;Jos se on sama, hyppmme jonnekin          
   0BC4:0110 cmp al,65         ;Vertailemme e:n ASCII-koodiin               
   0BC4:0112 jz 0100           ;Jos se on sama, hyppmme jonnekin          
   0BC4:0114 jmp 0100          ;Ei ollut K,k,E tai e. Paluu alkuun.         
   0BC4:0116 mov ax,4c01       ;Tnne tullaan, jos kirjain oli K tai k.     
   0BC4:0119 int 21            ;Paluu DOS:iin, ERRORLEVEL=1                 
   0BC4:011B mov ax,4c00       ;Tnne tullaan, jos kirjain oli E tai e.     
   0BC4:011E int 21            ;Paluu DOS:iin, ERRORLEVEL=0                 
   0BC4:0120                   ;Tyhj rivi palauttaa DEBUG:n kehoitteeseen  
   -rcx                        ;Tm opetettiin viime numerossa.            
   CX 0000                     ;Kerrotaan siis ohjelman pituus tavuina.     
   :20                         ;Ohjelman pituus on 20h tavua.               
  ͼ
 
    Mit siis teimme? Kytmme keskeytyst INT 21 AH:n arvolla 08h, joka on
    "Input character without echo"  eli lukee merkin tulostamatta sit ruu-
    dulle.   (Mist tiet,  mik keskeytys tekee mitkin?  Ne  voi  katsoa
    vaikkapa asiaa ksittelevst kirjasta. Luettelen toki muutaman hydyl-
    lisimmn keskeytyksen, kunhan opimme hieman lis ensin.) Tmn jlkeen
    on painetun kirjaimen ASCII-arvo rekisteriss AL.  Seuraavaksi  vertai-
    lemme  sit  ison K:n ASCII-arvoon,  joka on 4Bh.   ASCII-arvot  lytyy
    vaikkapa  DOS-oppaasta.   Muista  kytt   heksadesimaalijrjestelm!
    Vertailukomento on siis CMP AL,4B.  Seuraava komento,  JZ 0100,  hypp
    annettuun  osoitteeseen,  jos edellinen vertailu meni tasan,  siis  jos
    painettu nppin oli iso K. Emme vain tied, mihin osoitteeseen pitisi
    hypt,  joten annamme osoitteeksi 0100. Kun saamme ohjelman valmiiksi,
    palaamme muuttamaan osoitteen oikeaksi. Seuraavat kaksi rivi vertaile-
    vat ASCII-koodia pieneen k:hon, ja suorittavat taas hypyn, jos vertailu
    meni tasan.  Emme taaskaan tied osoitetta,  joten annamme arvon  0100.
    Seuraavat nelj rivi tekevt saman vertailun isolle ja pienelle E:lle.
    Seuraava  rivi  hypp  takaisin koko ohjelman  alkuun,   sill  mikli
    painettu nppin ei ollut K,k,E tai e,  haluamme lukea uuden  nppimen
    painalluksen,  ja uuden, ja uuden, kunnes painettu nppin on K,k,E tai
    e.  Tmn hypyn osoitteen tiedmme,  haluamme sen hyppvn  ohjelmamme
    ensimmiseen  kskyyn.   Sen osoite on aina 0100h,  ja sen  nkee  mys
    kyseist rivi edeltvist numeoista. Ksky on siis JMP 0100.
 

    Se osuus ohjelmasta,  jonka olemme jo kyneet lpi, vertailee painettua
    nppint selvittkseen,  mik nppin se oli.  Nyt meidn on  kirjoi-
    tettava  ne kskyt,  jotka palaavat DOS:iin eri ERRORLEVEL:in  arvoilla
    kutakin nppint painettaessa. Tmn tekevt kskyparit
        MOV AX,4C01
        INT 21
    joka sijoittaa AH:hon arvon 4C (INT 21 arvolla AH=4Ch palaa DOS:iin) ja
    AL:n arvon 01 (ERRORLEVEL=1), ja
        MOV AX,4C00
        INT 21
    joka tekee saman,  paitse palauttaa AL:n kautta ERRORLEVEL:ksi arvon 0.
    Olisimme voineet mys kirjoittaa
        MOV AH,4C
        MOV AL,01
    kskyn
        MOV AX,4C01
    sijasta, mutta jlkimminen vaihtoehto on suositeltavampi, sill se vie
    vhemmn  tilaa.  Ensimmisess vaihtoehdossa ei kuitenkaan ole  mitn
    vikaa, se toimisi aivan yht hyvin.

    Nyt olemme kirjoittaneet sek sen osan ohjelmaa,  joka tarkistaa,  mit
    nppint painettiin, ett sen osan,  joka palaa DOS:iin eri ERRORLEVEL
    arvoilla.   Nyt meidn on vain kytv kirjoittamassa ensimmisen  osan
    hyppykskyihin  ne  osoitteet,  joihin on hypttv haluttaessa  palata
    DOS:iin ERRORLEVEL:in arvoilla 1 tai 0. Ksky MOV AX,4C01  edeltvist
    numeroista (kaksoispisteen jlkeen tulevat numerot.  Ennen  kaksoispis-
    tett ovat numerot ovat ns.  segmenttiosoite, joka vaihtelee. Sit emme
    ohjelmassamme edes tarvitse.)  nemme, ett sen osoite on 0116h,  joten
    kaksi  ensimmist ksky JZ 0100  olisi korvattava kskyill JZ  0116.
    Vastaavasti  nemme,  ett MOV AX,4C00:n muistiosoite on 011Bh,   joten
    kaksi  seuraavaa  JZ 0100  -ksky on korvattava  JZ  011B  -kskyill.
    Teemme sen nyt.

    -a106                       ;Hyppyksky oli osoitteessa 0106h. Siihen
    0BC4:0106 jz 0116           ;osoitteeseen kirjoitamme uuden hyppykskyn
    0BC4:0108                   ;Tyhj rivi palauttaa DEBUG:n kehoitteeseen
    -a10a                       ;Nyt teemme saman, seuraavalle hyppykskylle
    0BC4:010A jz 0116           ;Oikea osoite on sama 0116h.
    0BC4:010C
    -a10e                       ;Sen hyppykskyn, joka suoritetaan painaessa
    0BC4:010E jz 011b           ;E:t tulisi vied meidt osoitteeseen 011Bh
    0BC4:0110
    -a112                       ;Ja jos painoimme e,
    0BC4:0112 jz 011b           ;hyppmme samaan osoitteeseen.
    0BC4:0114
    -

    Ennen  kuin tallennamme ohjelmamme levylle,  kannattaa tarkistaa,  ett
    tekemmme  muutokset tuli tehty oikein.  Olemme nyt DEBUG:in  komento-
    tasolla,   sill kursorimme vilkkuu viiva-kehoitteen vieress.  Kirjoi-
    tamme  komennon u100.  Ensimminen DEBUG-komentomme,  a100,   tarkoitti
    Assemble,   jolla voidaan kirjoittaa konekielikoodia,  ja  100   kertoo
    muistiosoitteen.  Komento u100  tarkoittaa Un-assemble,  eli lue  kone-
    kielikoodia,  ja osoite 100 on sama tuttu osoite,  josta .COM-tyyppiset
    ohjelmat  aina alkavat.  Kuvaruudulle tulostuu ohjelmamme.  Ohjelma  ei
    vlttmtt  aina ny kokonaan yhdell kuvaruudulla,  sill se ei  ehk
    mahdu  siihen,   tai sitten oman ohjelman lopussa on jnteit  jostain
    muusta ohjelmasta,  joka oli muistissa ennen kuin latasimme oman ohjel-
    mamme,  mutta tm ohjelma sattuu olemaan juuri sopivan mittainen, ett
    se nkyy kokonaisuudessaan yhdell ruudulla,  ilman ylimrist koodia
    lopussa. (Listaus seuraavalla sivulla).

    -u100
    0BC4:0100 B408          MOV AH,08
    0BC4:0102 CD21          INT 21
    0BC4:0104 3C4B          CMP AL,4B
    0BC4:0106 740E          JZ 0116
    0BC4:0108 3C6B          CMP AL,6B
    0BC4:010A 740A          JZ 0116
    0BC4:010C 3C45          CMP AL,45
    0BC4:010E 740B          JZ 011B
    0BC4:0110 3C65          CMP AL,65
    0BC4:0112 7407          JZ 011B
    0BC4:0114 EBEA          JMP 0100
    0BC4:0116 B8014C        MOV AX,4C01
    0BC4:0119 CD21          INT 21
    0BC4:011B B8004C        MOV AX,4C00
    0BC4:011E CD21          INT 21
    -nkvaie.com
    -w
    Writing 00020 bytes
    -q

    C:\>
 
    Kydn  viel  kerran lpi,  miten ohjelma toimii.  Ensimmiset  kaksi
    komentoa  odottavat,   ett  nppint painetaan ja  hakevat  nppimen
    ASCII-koodin  AL-rekisteriin.  Seuraavat nelj rivi  testaavat,   onko
    koodi sama kuin ison tai pienen K-kirjaimen,  ja hyppvt osoitteeseen
    0116h,   jos koodi on sama.  Tst osoitteesta alkavat  kaksi  komentoa
    puolestaan palauttavat jrjestelmn takaisin DOS:iin, ja ERRORLEVEL:iin
    arvon 1.  Jos painettu nppin ei ollutkaan iso tai pieni K,  ei hyppy
    tapahdu  ja  ohjelman suoritus jatkuu.  Osoitteesta 010Ch alkvat  nelj
    komentoa  testaavat,   onko  nppin iso tai  pieni  E,   ja  hyppvt
    osoitteeseen  011Bh,  jos nin oli.  Tllin jrjestelm palaa  DOS:iin
    ERRORLEVEL:in ollessa 0.  Mikli painettu nppin ei ollut myskn  E,
    suoritetaan ehdoton hyppyksky osoitteessa 114h, jolloin ohjelma jatkaa
    taas  suoritustaan osoitteesta 0100h,  eli ohjelman  alusta.   Ohjelman
    pitisi toimia, tallennamme sen nimell kvaie.com (K-vai-E) ja palaamme
    DOS:iin.

    Erittin hauska ohjelma,  eik olekin?  Kai jo osaat kytt sit?  No,
    tss on pieni .BAT-tiedosto, joka nytt, miten sit kytetn:

    echo off
    echo Haluatko, ett tervehdin?
    kvaie
    if errorlevel 1 goto tervehdi
    goto end
    :tervehdi
    echo Hyv piv.
    :end

    Se ei kaivanne selityst,  miten se toimii. Seuraavassa Assy ohjelmoin-
    tikurssin  osassa  tulemme  sitten  tekemisiin  sen  segmenttiosoitteen
    kanssa,  jonka aiemmin ohimennen mainitsin.  Silloin nimittin laitamme
    NumLock:in  ja CapsLock:in plle ja pois plt  pienill  .COM-ohjel-
    milla, ja tutustumme samalla PC:n muistin osoittamisen hienouksiin.

                     Kurssi jatkuu seuraavassa lehdess... -Antti Niskanen
 
