Artikkelit

Artikkelit olivat Suomipelit.comissa sivuston sulkeuduttua. Näin ollen niihin saattaa sisältyä rikkinäisiä linkkejä tai epämääräisiä viitteitä asioihin, joita ei enää ole olemassa, ja joskus jokin saattaa näkyä väärin.

Palaa artikkelilistaan

Kuinka tietokonepeli toimii - Osa 1: Johdatus ohjelmoitavuuteen

Tämä artikkelisarja on tarkoitettu aloittelijoille, eikä sen lukemiseen tarvita mitään ennakkotietoja tietotekniikasta. Artikkelin tarkoitus on antaa perinpohjainen selvitys siitä, kuinka yksi aikamme ihmeistä, tietokonepeli, toimii, ja mikä tärkeintä, auttaa alkuun omien tietokonepelien tekemisessä. Samalla selviää myös, kuinka tietokoneet ylipäätään toimivat ja joitakin mielenkiintoisia asioita niiden historiasta ja takana olevasta teoriasta.

8.8.2006 julkaistun artikkelin on kirjoittanut Markus.

  1. Esipuhe
  2. Johdanto
  3. Algoritmin käsite
  4. Turingin kone
  5. Churchin-Turingin teesi
  6. Hajasaantikone
  7. IO-laitteet

Esipuhe #

Monien Internet-sivujen keskustelupalstoilla näkee usein kysyttävän: "Kuinka tietokonepelejä tehdään?". Valitettavasti tällaiseen kysymykseen ei voi vastata romaania lyhyemmällä tekstinpätkällä ja jokainen lyhyempi vastaus vain synnyttää lisää kysymyksiä. Tämä artikkelisarja on syntynyt tästä tarpeesta.
Artikkelisarja tulee sisältämään suunnitelmien mukaan seuraavat osat.

1. Johdatus ohjelmoitavuuteen
2. Fyysistä tietokonetta rakentamassa
3. Kohti korkeampaa abstraktiotasoa
4. Teoriasta käytäntöön

Tämä on artikkelisarjan ensimmäinen osa.

Lähetäthän kaikki tästä artikkelista löytämäsi virheet osoitteeseen markus.ilmola@pp.inet.fi, niin korjaan ne mahdollisimman pian. Jos et ymmärrä jotain tässä artikkelissa, kysymys on todennäköisesti siitä, että en ole esittänyt asioita tarpeeksi selvästi. Ilmoitathan täten myös kaikki epäselvyydet ja muut hankaluudet, niin muokkaan artikkelia helpommin luettavaksi.

Johdanto #

Tietokonepeli on oikeastaan hieman harhaanjohtava sana tämän kirjoituksen otsikoksi, sillä sanalla "tietokone" tarkoitetaan yleensä PC-tietokonetta ja täten otsikosta saa sellaisen kuvan, että muilla elektronisilla laitteilla, kuten pelikonsoleilla ja matkapuhelimilla, pelattavat pelit toimisivat jotenkin eri tavalla kuin PC-pelit. Tietokoneeksi kuitenkin kelpaavat monet muutkin laitteet PC:n lisäksi.

Tietokoneelle on vähän hankala löytää virallista määritelmää, mutta itse määrittelisin tietokoneen laitteeksi, joka suorittaa laskentaa automaattisesti, tietyn ohjelmaksi kutsutun ohjeistuksen mukaan. Tärkeää on etenkin se, että laskenta tapahtuu ohjeistuksen mukaan, eikä ole rakennettu kiinteäksi osaksi konetta. Niinpä jos koneen toimintaan halutaan muutoksia, ei tarvitse rakentaa uutta konetta, ainoastaan muuttaa koneen ohjeistusta.

Sanaa "laskenta" ei myöskään saa käsittää liian suppeasti. Se nimittäin tuo lähinnä mieleen yhteen- ja vähennyslaskun, mutta laskentaa on myös paljon muunlaista. Itse asiassa laskenta voi tarkoittaa mitä tahansa tapahtumaa, jossa jokin tieto tai joukko tietoja muuttuu jonkin tarkkaan määritellyn säännön tai joukon sääntöjä perusteella joksikin toiseksi tiedoksi tai joukoksi tietoja.

Tietokone on siis periaatteessa mikä tahansa laite, joka osaa muuttaa tietoa toiseksi ohjelmaksi kutsutun ohjeistuksen mukaan. Tämä tieto voi olla mikä tahansa, esim. numero, sana tai yksittäinen kirjain. Tästä tiedosta käytetään tietokoneiden yhteydessä yleensä latinan kielestä juontuvaa sanaa data. Tietokoneita ovat siis tavallisen PC:n lisäksi mm. taskulaskin, matkapuhelin, DVD-soitin ja digiboksi. Taskulaskinta lukuun ottamatta näiden laitteiden ei näin äkkiseltään olettaisi laskevan yhtään mitään. Tietokoneen toiminta kuitenkin perustuu mekaaniseen laskentaan. Kaikki muut toiminnot, kuten DVD-elokuvan näkyminen TV-ruudulla tai meidän tapauksessamme interaktiivinen peli, tulee tämän tuotteena. Nykyään lähes missä tahansa kodinkoneessa on sisällä tietokone aina pesukoneesta kahvinkeittimeen ja autosta lentokoneeseen.

Mikä siis on tietokonepeli? Tietokonepeli on aivan tavallinen tietokoneohjelma eli ohjeistus tietokoneelle siitä, mitä sen pitää laskea. Ei mitään muuta. Tämä on kuitenkin kaikki mitä tarvitaan tietokonepelien taikamaailman luomiseen.

Aikamme yhden suosituimman tietokonepelin The World of Warcraftin maailma on itse asiassa vain tietokoneen suorittaman mekaanisen laskennan tuote. (Kuva pelistä War of Warcraft)Aikamme yhden suosituimman tietokonepelin The World of Warcraftin maailma on itse asiassa vain tietokoneen suorittaman mekaanisen laskennan tuote. (Kuva pelistä War of Warcraft)

Tämän ensimmäisen osan tarkoituksena on esitellä kaksi yksinkertaista teoreettista tietokoneen mallia "Turingin kone" ja "hajasaantikone". Tarkoituksena on näyttää, kuinka näillä kahdella toimintaperiaatteeltaan äärimmäisen yksinkertaisella laitteella on mahdollista tuottaa lähes äärettömän monimutkaista toiminnallisuutta ohjeistamalla niitä sopivasti hyvin yksinkertaisilla alkeisoperaatioilla. Lähestymistapa on ehkä hieman erilainen kuin monissa muissa artikkeleissa, mutta uskon tämän auttavan ymmärtämään miksi oikeat tietokoneet toimivat niin kuin toimivat. Pelkkään teoriaan ei tarvitse tyytyä, vaan esitettyjä asioita voi kokeilla ihan käytännössä myöhemmin esiteltävien apuvälineiden avulla.

Algoritmin käsite #

Algoritmi on äärellinen joukko tarkkaan määriteltyjä ohjeita jonkin tehtävän suorittamiseksi äärellisessä ajassa. "Tarkkaan määritelty" tarkoittaa tässä tapauksessa sitä, että ohjeet eivät saa jättää seuraajalleen minkäänlaista tulkinnan varaa! Käsite algoritmi on nimetty noin vuosina 800 - 840 eläneen keksijänsä Abu Abdullah Muhammad bin Musa al-Khwarizmin mukaan.

Algoritmiksi kelpaa siis esim. ruokaresepti. Resepti kertoo, kuinka tietty ruoka valmistetaan. Jos resepti on kirjoitettu kunnolla, kuka tahansa voi reseptiä sokeasti seuraamalla valmistaa siinä kuvatun ruuan. Toinen hyvä esimerkki algoritmista ovat nuotit. Nuotteja seuraamalla voi soittaa nuoteilla kuvatun kappaleen, vaikka ei olisi sitä koskaan ennen kuullut.

Persialainen matemaatikko Abu Abdullah Muhammad bin Musa al-Khwarizmi antoi (onneksi vain suku)nimensä algoritmi-käsitteelle. (Kuva neuvostoliittolaisesta postimerkistä)Persialainen matemaatikko Abu Abdullah Muhammad bin Musa al-Khwarizmi antoi (onneksi vain suku)nimensä algoritmi-käsitteelle. (Kuva neuvostoliittolaisesta postimerkistä)

Resepti ja nuotit ovat algoritmeja, jotka on tarkoitettu ihmisen (tai miksei hyvin koulutetun simpanssin) suoritettavaksi. Algoritmin suorittaja voi kuitenkin olla myös mekaaninen kone. Kun algoritmi on tarkoitettu minkä tahansa koneen suoritettavaksi, kutsutaan algoritmia ohjelmaksi, ohjelmakoodiksi tai joskus myös pelkäksi koodiksi. Ohjelman laatimista koneelle kutsutaan koneen ohjelmoinniksi.

Hyvä esimerkki ohjelmasta on soittorasiassa. Soittorasian sisällä on rulla, johon on on tehty kohoumia. Kun rasia laitetaan käyntiin, alkaa rulla pyöriä. Soittorasian koskettimissa on kiinni varret, joiden toiset päät hankaavat rullan pintaa. Kun varren pää osuu kohoumaan, painaa varsi kosketinta ja kosketin päästää näin äänen. Lopputuloksena on, että jos kohoumat on tehty sopiviin kohtiin, soittaa rasia oikeaa musiikkia. Periaate on sama kuin nuoteissa, mutta nyt algoritmin suorittajana on kone. Tämä rulla on siis soittorasian ohjelma.

Sana tietokoneohjelma tarkoittaakin ohjelmaa eli algoritmia, joka on tarkoitettu tietokoneen suoritettavaksi. Juuri tällainen, ja vain tällainen, tietokonepelikin on: tietokoneohjelma eli algoritmi eli joukko tarkkaan määriteltyjä ohjeita tietokoneelle siitä, mitä sen pitää laskea.

Turingin kone #

Yksi ensimmäisistä formaaleista malleista automaattisesti laskentaa suorittavaksi koneeksi oli matemaatikko Alan Turingin vuonna 1936 keksimä Turingin kone. Mainittakoon nyt ihan ensin, että Turingin kone EI ole se malli, jonka mukaan oikeat tietokoneet toimivat, mutta se yhtä hyvin voisi olla, kuten tulemme huomaamaan. Itse asiassa yhtään oikeaa Turingin konetta ei ole edes koskaan rakennettu. Esittelen Turingin koneen siksi, että se on erittäin yksinkertainen ja historiallisesti mielenkiintoinen, koska se oli ensimmäisiä yrityksiä formalisoida tietokone. En kuitenkaan tarkoita yksinkertaisuudella tässä sitä, että ohjelman laatiminen sille olisi yksinkertaista, vaan sitä, että se on toimintaperiaatteeltaan yksinkertainen. Toinen mielenkiintoinen ja äärimmäisen tärkeä siihen liittyvä asia on Churchin-Turingin teesi, joka on seuraavan kappaleen aiheena.

Turingin koneen rakenne

Turingin kone koostuu kahdesta osasta: logiikkayksiköstä ja äärettömästä muistinauhasta.

Ääretön muistinauha jatkuu äärettömänä kumpaankin suuntaan ja koostuu vierekkäisistä ruuduista, joista jokainen voi sisältää yhden mielivaltaisen aakkoston mielivaltaisen merkin: esim. merkin "a", "b", "ä", "1", "€" tai "?". Alussa muistinauhan jokainen ruutu on tyhjä tai selvyyden vuoksi sisältää jonkin tyhjää tarkoittavan merkin. Käytän tässä merkkiä "_" ilmaisemaan tyhjää.

Jossakin nauhan ruudussa on kiinni lukupää, joka osaa lukea ruudussa olevan merkin ja välittää sen logiikkayksikölle, kirjoittaa ruutuun logiikkayksikön sille lähettämän merkin sekä siirtyä tarvittaessa nauhalla yhden (ja vain yhden) pykälän kerrallaan vasemmalle tai oikealla.

Logiikkayksikkö taas koostuu mekanismista, jonka avulla se voi kohta kuvailtavan ohjelmansa avulla käyttää lukupäätä muistinauhan lukemisen ja kirjoittamiseen, sekä mekanismin, jonka avulla se voi pitää kirjaa tilastaan, ja muuttaa sitä tarvittaessa. Logiikkayksikön tilat voidaan nimetä mielivaltaisesti. Ne voivat olla esim. numeroita 0, 1, 2, 3 jne., kirjaimia a, b, c, d jne. tai nimiä, kuten "tila_1", "punainen_tila" tai "raksuttamassa". Alussa logiikkayksikkö on jossakin sovitussa alkutilassa. Käytämme tässä artikkelissa tilaa, jonka nimi on "alku". Kone voi suorituksen edetessä vaihtaa tilakseen minkä nimisen tilan tahansa. Tilan nimi ei siis vaikuta mitenkään mihinkään, vaan koneen täytyy ainoastaan muistaa, minkä nimisessä tilassa se on.

Taiteilijan näkemys Turingin koneesta. (Kuva: Wikipedia)Taiteilijan näkemys Turingin koneesta. (Kuva: Wikipedia)

Tässä oli Turingin koneen rakenne, joka oli varsin yksinkertainen. Nyt tulee Turingin koneen ohjelmointi, joka onkin sitten jo huomattavan paljon hankalampaa ja yksi syy siihen, miksi Turingin koneita ei käytetä oikeina tietokoneina.

Turingin koneen ohjelma

Turingin koneen ohjelma on normaalia tekstiä ja koostuu ohjelmariveistä, joista jokainen koostuu viidestä osasta. Erotettakoon nämä osat selvyyden vuoksi pilkulla toisistaan. Käytetään näistä osista vaikka symboleja A, B, C, D ja E. Kaksi ensimmäistä osaa (A ja B) ovat ehto sille, voidaanko ohjelmarivi suorittaa, ja kolme viimeistä (C, D ja E) ohjelmarivin suorittamat toimenpiteet. Osien merkitys on seuraava:

  • A on sen tilan nimi, jossa koneen pitää olla, jotta ohjelmarivi voidaan suorittaa.
  • B on symboli, jonka täytyy olla muistinauhalla lukupään kohdalla, jotta ohjelmarivi voidaan suorittaa.
  • C on sen tilan nimi, johon kone asettuu ohjelmarivin suorituksen jälkeen.
  • D on symboli, joka kirjoitetaan muistinauhalle lukupään kohdalle ohjelmarivin suorituksessa.
  • E on suunta, johon lukupäätä siirretään yksi pykälä ohjelmarivin suorituksen jälkeen. Tämä voi olla joko L (=yksi pykälä vasemmalle), R (=yksi pykälä oikealle) tai O (=ei siirtoa).

Esim. "tila7, M, tila4, N, L" tarkoittaisi, että ohjelmarivi suoritetaan, jos kone on tilassa nimeltä "tila7" ja muistinauhalla on lukupään kohdalla symboli "M". Kun ohjelmarivi suoritetaan, siirtyy kone tilaan nimeltä "tila4", muistinauhalla ollut symboli "M" korvataan symbolilla "N" ja lukupää siirtyy yhden pykälän vasemmalle.

Kun Turingin kone käynnistetään, se alkaa etsiä ohjelmastaan riviä, jonka ehdot täyttyvät, eli jonka se voi täten suorittaa. Ohjelmat tulisikin laatia niin, että kahdella ohjelmarivillä ei ole samaa (kumpaakin) ehtoa, jotta kerrallaan olisi vain yksi mahdollinen ohjelmarivi suoritettavaksi. Jos kahdella ohjelmarivillä on identtiset ehdot, ei kone tiedä kumpi sen pitäisi suorittaa. Koneen suoritettua kyseisen ohjelmarivin, se alkaa etsiä seuraavaa ehdot täyttävää riviä, joka on mahdollisesti eri rivi kuin äsken, koska äskeisen ohjelmarivin suorituksessa koneen tila saattoi muuttua ja/tai lukupään kohdalla oleva merkki vaihtua (joko kirjoituksen tai siirron seurauksena). Jos kone ei löydä yhtään ohjelmariviä, jonka se voisi suorittaa, on ohjelman suoritus valmis, ja kone pysähtyy.

Otetaan esimerkiksi ohjelma, joka kirjoittaa muistinauhalle sanan "moi". (Laitoin rivien alkuun selvyyden vuoksi rivinumerot.)
[DEFTABLE]
[D]1:
2:
3:
4:[/D][E]alku, _, kirjoitaM, _, O
kirjoitaM, _, kirjoitaO, m, R
kirjoitaO, _, kirjoitaI, o, R
kirjoitaI, _, loppu, i, R[/E][/DEFTABLE]
Alussa kone on sopimuksemme mukaan tilassa nimeltä "alku" ja lukupäänkohdalla on tyhjää (merkki "_"), koska koko ääretön muistinauha on tyhjä. Ainoastaan rivin numero 1 ehdot täsmäävät ja se voidaan suorittaa. Suorituksen seurauksena kone siirtyy tilaan nimeltä "kirjoitaM", muistinauhalle tulostuu sama tyhje, joka siinä jo olikin, ja lukupää ei liiku mihinkään. Koneen ollessa nyt tilassa "kirjoitaM" täsmäävät vain rivin numero 2 ehdot ja se suoritetaan. Näin ollen kone siirtyy tilaan "kirjoitaO", muistinauhalle tulostuu merkki "m" ja lukupää siirtyy yhden pykälän oikealle. Nyt, kun kone on tilassa "kirjoitaO", ja lukupään kohdalla on taas tyhjää, täsmäävät ainoastaan ohjelmarivin numero 3 ehdot ja se suoritetaan. Tämän seurauksena kone siirtyy tilaan "kirjoitaI", muistinauhaan tulostuu merkki "o" ja lukupää siirtyy pykälän oikealle. Nyt, kun kone on tilassa "kirjoitaI", ja lukupään kohdalla on tyhjää, täsmää viimeisen rivin ehto. Siten kone siirtyy tilaan "loppu", muistinauhalle tulostuu merkki "i" ja lukupää siirtyy yhden pykälän oikealle (ei tosin ole enää mitään väliä mihin se siirtyy). Kun kone on tilassa "loppu", ei yksikään ehto enää täsmää ja kone pysähtyy urakkansa suorittaneena. Kone siis käyttää tilaansa muistaakseen, missä vaiheessa urakkaansa se on menossa.

Jos äskeisen ohjelman haluaisi muuttaa sellaiseksi, että se tulostaa loputtomiin perätysten sanoja "moi", tarvitsee vain vaihtaa rivin numero 4 tilan "loppu" paikalle "kirjoitaM". Tällöin täsmäävät taas rivin numero 2 ehdot ja "moi"-sanan kirjoitus alkaa aina alusta eikä suoritus pysähdy koskaan. Tällöin koneelle annettu ohjelma ei ole enää algoritmi, sillä algoritmin määritelmän mukaan sen suorituksen täytyy joskus päättyä.

Turingin kone -visualisaattori

Ennen kuin jatkamme, haluan esitellä sinulle pienen apuvälineen, jonka avulla voit kokeilla Turingin konetta käytännössä. Jos et halua käyttää tätä apuvälinettä, voit hypätä suoraan tämän lyhyen kappaleen yli seuraavaan.

Kyseessä on Turingin kone -visualisaattori. Sen avulla voit kokeilla Turingin koneen toimintaa käytännössä. Jotta visualisaattori toimisi, sinulla pitää olla koneessasi asennettuna eräs Javaksi kutsuttu asia, josta lisää artikkelisarjan kolmannessa osassa "Kohti korkeampaa abstraktiotasoa". On todennäköistä, että Java on koneessasi jo valmiina, mutta jos ei, niin hae omasi täältä: http://www.java.com. Jos käytössäsi on Linux-käyttöjärjestelmä, voit asentaa Javan todennäköisesti myös suoraan pakettienhallinnasta. Jos Java on asennettuna, visualisaattori käynnistyy kun klikkaat allaolevaa linkkiä.

http://www.suomipelit.com/files/artikkel...

Visualisaattorin käyttöliittymä saattaa näyttää hieman erilaiselta riippuen siitä, millä koneella käytät sitä, mutta seuraavien käyttöohjeiden pistäisi toimia alustalla kuin alustalla.

Ohjelma kirjoitetaan vasemmassa reunassa olevaan suureen mustareunaiseen laatikkoon. Muistinauha näkyy alareunassa, ja voit editoida vapaasti sen sisältöä. Pieni musta nuoli keskellä sitä edustaa lukupäätä. Koska koko (ääretön) muistinauha ei luonnollisestikaan sovi kerralla ruudulle voit vierittää sitä sen alapuolella reunoissa olevista painikkeista. Painike "1" vierittää yhden pykälän ja painike "5" viisi pykälää. Käytännöllisistä syistä lukupää ei vieri nauhan mukana vaan pysyy aina keskellä näyttöä, joten ennen kuin käynnistät koneen, vieritä nauhaa niin, että lukupää on haluamasi ruudun kohdalla.

Koneen tilan nimi näkyy näytön keskellä olevassa kentässä, ja voit editoida sitäkin vapaasti (se on siis ulkonäöstään huolimatta täysin tavallinen editoitava tekstikenttä). Oletuksena alussa tilana on tila nimeltä "alku". "Alusta"-painike tyhjentää koko muistin ja asettaa tilaksi "alku". Kun olet kirjoittanut ohjelman, voit käynnistää koneen isosta painikkeesta, jossa lukee "Käynnistä" ja sammuttaa "Sammuta"-painikkeesta. Kun koneelta loppuvat suoritettavat käskyt, se sammuu itsekseenkin. Kun kone on käynnissä, voit keskeyttää sen toiminnan väliaikaisesti "Keskeytä" painikkeesta. Koneen ollessa keskeytyneenä paina "yksi askel"-painiketta suorittaaksesi ohjelmaa yksi käsky kerrallaan.

Liukusäädin oikeassa yläkulmassa säätää koneen nopeuden. Se toimii hieman käänteisesti, sillä numero edustaa viivettä käskyjen suoritusten välillä millisekunteina. Näin ollen säätimen ollessa ylhäällä on kone hitaimmillaan ja alhaalla on kone nopeimmillaan.

Kokeile esimerkiksi kopioida "moi"-sanan kirjoittava ohjelma visualisaattorin ohjelma-tekstikenttään ja paina "käynnistä". Kopioiminen ja liittäminen pitäisi toimia pikanäppäimillä control+c (kopioi) ja control+v (liitä). Kaikissa selaimissa tämä ei kuitenkaan saata toimia, mutta ainakin Firefox-selaimella homma on testattu toimivaksi. Saat Firefox-selaimen tarvittaessa täältä: http://www.mozilla.com/firefox/ .

Laskeminen Turingin koneen avulla

"moi"-sanan tulostava ohjelma oli sangen yksinkertainen, mutta tämänhän piti olla laskentaa suorittava kone eikä tulostin. Laskenta (sanan varsinaisessa merkityksessä) on kuitenkin täysin mahdollista!

Tehdään seuraavaksi ohjelma, joka laskee yhteen kaksi lukua. Jotta esimerkki olisi yksinkertaisempi, käytetään numeroina tukkimiehen kirjanpitoa eli esitetään numerot sarjana pystyviivoja. Käytetään pystyviivana merkkiä "1" (numero yksi). Numeroa kolme merkittäisiin siis "111" ja numeroa kahdeksan "11111111". Oletetaan, että yhteenlaskettavat numerot on kirjoitettu valmiiksi Turingin koneen muistinauhalle ja että ne on erotettu "+"-merkillä ja niiden perässä on "="-merkki. Jos siis haluamme laskea laskun 2+3, niin muistinauhalla lukisi valmiina "11+111=". Ohjelman suorituksen jälkeen nauhalla pitäisi lukea "11+111=11111". Alussa lukupään oletetaan olevan nauhalla vasemmanpuoleisimman pystyviivan kohdalla.

Jos ajattelet järjellä, kuinka kyseisen urakan voisi helpoiten suorittaa, huomaat, että kaikki mitä koneen tarvitsee tehdä, on kirjoittaa "="-merkin oikealle puolelle yhtä monta pystyviivaa kuin on sen vasemmalla puolella. Niinpä idea voisi olla seuraavanlainen.

Koneen tarvitsee etsiä "="-merkin vasemmalta puolelta pystyviiva (merkki "1"), jota se ei ole vielä kopioinut "="-merkin oikealle puolelle. Sitten pitää merkitä tämä pystyviiva kopioiduksi, eli korvata se toisella merkillä, esim. merkillä "x", ja siirtää lukupäätä oikealle, kunnes vastaan tulee tyhjää nauhaa. Tähän tyhjään voi nyt kirjoittaa äskeisen merkin kopion eli merkin "1". Nyt kone palauttaa lukupään vasempaan reunaan etsiäkseen uuden merkin, jota se ei ole vielä kopioinut ja homma toistuu. Kun kaikki merkit on kopioitu, pitää tilanne vielä siivota alkuperäiseen ulkoasuun eli korvata kaikki "x"-merkit "1"-merkeillä.

Nyt tämä idea pitäisi vielä kirjoittaa Turingin koneen ohjelmaksi. Se on yhtä monimutkaista, miltä se aluksi tuntuukin. Jos lähtee miettimään, monessako eri tilassa koneen tarvitsee olla, niin niitä löytyy ainakin neljä. Yhdessä tilassa kone vain merkitsee pystyviivan rastiksi (annetaan tilalle nimeksi "merkkaa"). Yhdessä se liikuttaa lukupäätä oikealle päin kopioidakseen merkin ensimmäiseen vastaan tulevaan tyhjään paikkaan (annetaan tilalle nimeksi "oikealle"). Yhdessä se palauttaa lukupäätä vasemmalle, kunnes törmää seuraavaan kopiomattomaan merkkiin (annetaan tilalle nimeksi "vasemmalle"). Viimeisessä se korvaa rastit pystyviivoilla (annetaan nimeksi "siisti").

Yksi vaihtoehto ohjelmaksi olisi seuraavanlainen. Ohjelma on pitkä ja monimutkaisen näköinen, ja sen tarkoitus onkin vain demonstroida, että yhteenlasku on mahdollinen, mutta työläs toteuttaa.
[DEFTABLE][D]1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
[/D][E]alku, 1, merkkaa, 1, O
merkkaa, 1, oikealle, x, R
merkkaa, +, merkkaa, +, R
merkkaa, =, siisti, =, L
oikealle, 1, oikealle, 1, R
oikealle, +, oikealle, +, R
oikealle, =, oikealle, =, R
oikealle, _, vasemmalle, 1, L
vasemmalle, 1, vasemmalle, 1, L
vasemmalle, +, vasemmalle, +, L
vasemmalle, =, vasemmalle, =, L
vasemmalle, x, merkkaa, x, R
siisti, x, siisti, 1, L
siisti, +, siisti, +, L
siisti, _, loppu, _, R[/E][/DEFTABLE]
Sopimuksemme mukaan alussa kone on tilassa "alku" ja nauhalla on merkki "1", joten ensimmäisen rivin ehdot täsmäävät ja kone suorittaa sen. Kone ei tee muuta kuin muuttaa tilakseen tilan "merkkaa". Nyt kone on tilassa "merkkaa", ja nauhalla sama "1", koska lukupää ei liikkunut mihinkään. Rivin numero 2 ehdot täsmäävät. Kone asettuu tilaan "oikealle" ja korvaa merkin "1" merkillä "x" ja siirtää lukupäätä oikealle äsken kirjoitetun "x"-merkin viereen. Tilassa "oikealle" kone vain siirtää lukupäätä oikealle, oli sitten lukupään kohdalla mikä merkki tahansa, kunnes törmää tyhjään ruutuun. Kun näin käy, täsmäävät rivin numero 8 ehdot, joten kone asettuu tilaan "vasemmalle" ja korvaa tyhjeen merkillä "1". Tilassa "vasemmalle" kone vain siirtyy vasemmalle, kunnes törmää merkkiin "x". Tämän merkin oikealle puolella on pakko olla kopioimaton merkki, joten kone siirtää lukupään sen kohdalle ja siirtyy tilaan "merkkaa". Näin kaikki alkaa alusta. Kun kaikki merkit on kopioitu (korvattu merkillä "x"), sattuu lukupää merkin "=" kohdalle koneen siirtyessä "merkkaa" tilaan, näin rivin 4 ehdot täyttävät. Tällöin kone siirtyy "siisti" tilaan. Tässä tilassa kone liikuttaa lukupäätä vasemmalle korvaten kaikki vastaan tulevat "x"-merkit "1"-merkeillä, kunnes kohdataan tyhjää, jonka seurauksena rivin 15 ehdot täyttyvät ja kone siirtyy tilaan loppu. Yksikään rivi ei sisällä ehtona tilaa "loppu", joten kone pysähtyy.

Koneen suorittama toimenpide ei saata vaikuttaa laskemiselta sanan varsinaisessa mielessä, vaan mekaaniselta toimenpiteeltä, mutta tyylipisteitä ei jaella. Sitä paitsi se toimii! Kirjoita mitkä tahansa kaksi lukua tukkimiehen kirjanpidolla nauhalle ("+"-merkillä erotettuna ja perään vielä "="-merkki) ja aseta lukupää vasemmanpuoleisimman "1"-merkin kohdalle. Seuraa ohjelman etenemistä esim. aikaisemmin esitellyn Turingin kone -visualisaatorin tai kynän ja paperin avulla ja huomaat, että kun ohjelman suoritus on valmis (pitkän lukupään edes takaisin sahauksen jälkeen) saatu vastaus on ihan oikein. Laskutoimitus olisi tietenkin ollut mahdollinen myös oikeilla numeroilla, mutta tarvittavasta ohjelmasta olisi tullut huomattavasti pidempi.

Katsotaan vielä lopuksi kertolasku, jotta uskoisit senkin olevan mahdollinen laskettava Turingin koneella. Käytetään jälleen kerran tukkimiehen kirjanpitoa. Kerrottavat luvut ovat valmiiksi nauhalla erotettuna "*"-merkillä ja niiden perässä on "=" merkki. Lukupää on vasemman puoleisimman merkin kohdalla. Jos siis halutaan laskea 4*3, niin nauhalla lukisi "1111*111=".

Kertolaskussa koneen tarvitsee vain kopioida "*"-merkin ja "="-merkin välissä olevat pystyviivat "="-merkin oikealle puolelle yhtä monta kertaa kuin on pystyviivoja *-merkin vasemmalla puolella. Tämä vaatii samantapaista merkkailua ja edestakaisin sahausta kuin yhteenlaskukin. Yllätykseksi ohjelmasta ei tule kuin vähän pidempi verrattuna yhteenlaskuun.
[DEFTABLE][D]1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
[/D][E]alku, 1, merkkaaEka, 1, O
merkkaaEka, 1, etsiToka, y, R
etsiToka, 1, etsiToka, 1, R
etsiToka, *, merkkaaToka, *, R
merkkaaToka, 1, kopioi, x, R
kopioi, 1, kopioi, 1, R
kopioi, =, kopioi, =, R
kopioi, _, seuraava, 1, L
seuraava, =, seuraava, =, L
seuraava, 1, seuraava, 1, L
seuraava, x, merkkaaToka, x, R
merkkaaToka, =, takaisin, =, L
takaisin, x, takaisin, 1, L
takaisin, *, takaisin, *, L
takaisin, 1, takaisin, 1, L
takaisin, y, merkkaaEka, y, R
merkkaaEka, *, siisti,*, L
siisti, y, siisti, 1, L
siisti, _, loppu, _, R[/E][/DEFTABLE]
Ohjelma alkaa jo olla niin monimutkainen, että sen selittäminen sanoin on hankalaa. Sen sijaan kokeile ohjelman toimintaa Turingin kone -visualisaattorilla. Kopioi ohjelma visualisaattorin ohjelmatekstikenttään. Kirjoita nauhalle jokin lasku. Vaikka "111*11111=". Siirrä lukupää ensimmäisen "1"-merkin kohdalle ja paina "Käynnistä". Haluat ehkä asettaa koneen toimintanopeuden hieman korkeammaksi, sillä pienen laskun laskeminen kestää koneelta aika kauan.

Churchin-Turingin teesi #

Turingin kone ei siis (onneksi) ole malli, jonka mukaan oikeat tietokoneet toimivat, mutta se voisi yhtä hyvin olla, sillä Alonzo Church ja Alan Turing esittivät vuonna 1936 Churchin-Turingin teesin, joka väittää, että millä tahansa koneella, joka sisältää tietyt perusominaisuudet, voi tehdä kaiken sen, minkä millä tahansa muulla tietokoneella ja että Turingin kone on tällainen perusominaisuudet omaava kone. Toisin sanoen Turingin koneella voi tehdä kaiken mitä millä tahansa muulla tietokoneella! Ja toisinpäin: ei ole mahdollista rakentaa sellaista tietokonetta, jolla voisi tehdä jotain sellaista, mitä Turingin koneella ei voisi tehdä. Tämä on koko tämän ensimmäisen artikkelin ydin. Näin Turingin koneesta saadaan parempi määritelmä tietokoneelle: tietokone – mikä tahansa laite, jolla voi tehdä kaiken sen mitä Turingin koneella.

Syitä siihen, miksi Turingin kone ei ole nykyisten tietokoneiden toimintaperiaate, on monia, kuten se, että niinkin yksinkertainen operaatio kuin yhteenlasku vei todella paljon aikaa ja vaivaa. Toisekseen ääretöntä muistinauhaa ei ole olemassa. Myös ohjelmien laatiminen Turingin koneelle on hankalaa. Kokeile vaikka toteuttaa potenssilasku. Voisin melkein lyödä vetoa, että et onnistu siinä.

Churchin-Turingin teesillä on monia käytännön sovelluksia. Koska mikä tahansa tietokone voi tehdä kaiken sen, minkä mikä tahansa muu tietokone, ei jollekin tietyn tyyppiselle tietokoneelle kirjoitettu ohjelma ole sidoksissa tähän tietokoneeseen, vaan se voidaan suorittaa minkälaisella tietokoneella hyvänsä. Tarvitaan vain väliin sovitinohjelma eli emulaattori. Vieraan tietokoneen ohjelma kirjoitetaan sen tietokoneen muistiin, jolla ohjelma halutaan suorittaa, ja sitten tehdään emulaattori, joka lukee tätä muistissa olevaa ohjelmaa ja sitä tulkiten toteuttaa sen toiminnot kyseisellä tietokoneella. Aikaisemmin esittelemä Turingin kone -visualisaattori oli tällainen emulaattori. Sen avulla saatoit ajaa Turingin koneelle tarkoitetun ohjelman omassa tietokoneessasi(, joka ei siis perustunut Turingin koneeseen).

Nintendon 'Nintendo 64' -konsolille tarkoitettu 'Super Mario 64' -peli toimii moitteettomasti PC -tietokoneessa 'Project 64' -emulaattorin avustuksella. Elävä esimerkki Churchin-Turingin teesistä. (Kuva pelistä Mario 64 ja ohjelmasta Project 64)Nintendon 'Nintendo 64' -konsolille tarkoitettu 'Super Mario 64' -peli toimii moitteettomasti PC -tietokoneessa 'Project 64' -emulaattorin avustuksella. Elävä esimerkki Churchin-Turingin teesistä. (Kuva pelistä Mario 64 ja ohjelmasta Project 64)

Mainittakoon tämän kappaleen lopuksi, että Turingin koneesta on kehitetty lukuisia eri variaatioita. On esim. koneita, joissa on useita muistinauhoja, koneita joiden muistinauha onkin kaksiulotteinen muistitaso ja koneita joiden pitää siirtyä tiettyyn lopputilaan ja lukupään tiettyyn loppupaikkaan ennen kuin kone osaa pysähtyä jne. Churchin-Turingin teesin mukaan yksikään näistä koneista ei kuitenkaan pysty tekemään mitään sellaista, mitä tavallinen Turingin kone ei pystyisi tekemään.

Hajasaantikone #

Kaikki nykyiset tietokoneet perustuvat ns. hajasaantikoneen malliin. Mainittakoon taas ihan aluksi, että vaikka hajasaantikoneen ohjelmoiminen on helpompaa kuin Turingin koneen, ei sekään mitään helppoa ole. Tämän takia on tietotekniikan lyhyen historian aikana on kehitetty erinäisiä keinoja, joilla ohjelmien kirjoittamista tietokoneelle saadaan helpotettua huomattavasti. Näistä keinoista puhumme artikkelisarjan kolmannessa osassa "Kohti korkeampaa abstraktiotasoa". Oikeita pelejä EI siis (luojan kiitos) tarvitse väkertää seuraavassa esitetyillä keinoilla. Kuten Turingin koneestakin, myös hajasaantikoneesta on lukemattomia muunnelmia, joista esitän tässä yhden.

Hajasaantikoneen rakenne

Hajasaantikone on seuraavanlainen. Se koostuu muistista ja logiikkayksiköstä, kuten Turingin konekin. Muisti vastaa Turingin koneen muistinauhaa, mutta siinä on yksi merkittävä ero. Siinä missä Turingin koneessa lukupää pystyi liikkumaan vain yhden pykälän kerrallaan, hajasaantikoneessa lukupää voi hypätä mihin tahansa kohtaan muistia haluaa. Tätä varten hajasaantikoneen muisti jaetaan muistipaikkoihin ja nämä muistipaikat on numeroitu nollasta alkaen. Ensimmäisen muistipaikan numero on 0, seuraavan 1 jne. Jokainen muistipaikka voi sisältää yhden minkä tahansa luvun, esim. 0, 1, 2, 13, 42 tai 2079460347. Varsinaisen muistin lisäksi on vielä jotain, mitä Turingin koneessa ei ollut: yksi ylimääräinen muistipaikka, joka kutsutaan akuksi tai rekisteriksi. Käytän tässä termiä "akku", koska se on lyhempi kirjoittaa. Tällä akulla ei siis ole mitään tekemistä auton akun tai minkään muun sähköä tuottavan / varastoivan laitteen kanssa.

Logiikkayksikön tarvitsee osata lukea ja kirjoittaa muistipaikkoihin sekä akkuun ja lisäksi suorittaa yhteen, vähennys, kerto ja jakolakuja. Toisin kuin Turingin koneen hajasaantikoneen tarvitsee siis osata jo valmiiksi laskea! (Jos et sulata ajatusta koneesta joka yksinkertaisesti vain osaa laskea, niin voit ajatella, että hajasaantikoneen sisällä on pieni Turingin kone, joka suorittaa laskut sen puolesta.)

Hajasaantikoneen ohjelma

Hajasaantikoneen ohjelma on normaalia tekstiä ja koostuu ohjelmariveistä, jotka ovat muotoa "käsky parametri". Käsky on jokin sana esim. "LOAD" ja parametri jokin numero esim. "132". Parametri voi tarkoittaa jotain paljasta lukua tai jonkin muistipaikan numeroa. Jotta voitaisiin erottaa mikä parametri tarkoittaa mitäkin, laitetaan parametrin eteen merkki ilmaisemaan kummasta on kyse. Käytän tässä merkkejä "=" ja "&". "=1234" tarkoittaa siis lukua tuhatkaksisataakolmekymmentäneljä ja "&1234" tarkoittaa muistipaikkaa numero 1234. Kutsutaan paljasta lukua välittömäksi osoitukseksi ja muistipaikan numeroa suoraksi osoitukseksi.

Käsky on jokin seuraavista:


  • LOAD Kopioi parametrina saamansa luvun tai muistipaikan sisällön akun sisällöksi.
  • STORE Kopioi akun sisällön parametrina saamansa muistipaikan sisällöksi. Tämä komento voi siis saada parametrinaan vain ja ainoastaan muistipaikan numeron, ei paljasta lukua.
  • ADD Laskee yhteen akun sisällön ja parametrina saamansa luvun tai muistipaikan sisällön ja sijoittaa tuloksen akkuun.
  • SUBS Vähentää akun sisällöstä parametrina saamansa luvun tai muistipaikan sisällön ja sijoittaa tuloksen akkuun.
  • MULT Kertoo keskenään akun sisällön ja parametrina saamansa luvun tai muistipaikan sisällön ja sijoittaa tuloksen akkuun.
  • DIV Jakaa akun sisällön parametrina saamallaan luvulla tai muistipaikan sisällöllä ja sijoittaa tuloksen akkuun.
  • JUMP Hyppää ohjelman suorituksessa riville, jonka numeron se saa parametrinaan.
  • JZERO Hyppää ohjelman suorituksessa riville, jonka numeron se saa parametrinaan, mutta tekee tämän vain ja ainoastaan jos akun sisältönä on luku nolla.
  • HALT Pysäyttää koneen toiminnan. Ei välitä mitään parametristaan.

Esimerkkejä:

"LOAD =1" Asettaa akun sisällöksi luvun 1.

"ADD =3" Lisää akun sisältöön luvun 3 ja tallentaa tuloksen akkuun. Jos siis akussa oli alun perin luku 2 on siinä tämän käskyn jälkeen luku 5.

"MULT &4" Kertoo akun sisällön muistipaikasta numero 4 löytyvällä luvulla ja tallentaa tuloksen akkuun. Jos akussa oli luku 5 ja muistipaikassa numero 4 luku 6 tulee akun sisällöksi luku 30.

"STORE &2" Kopioi akun sisällön muistipaikkaan numero 2.

Tarvitaan kuitenkin vielä yksi yksi parametrityyppi, jota kutsutaan epäsuoraksi osoitukseksi. Merkitään tätä tyyppiä merkillä "*". Epäsuoran osoituksen idea on, että se on muistipaikan numero, mutta lukua ei lueta tästä muistipaikasta, vaan siitä muistipaikasta, jonka numero tässä muistipaikassa on. Hieman monimutkainen siis, mutta tarpeellinen.

Esim. "LOAD *1" kopioi akun sisällöksi luvun siitä muistipaikasta, jonka numero löytyy muistipaikasta numero 1.

Joidenkin käskyjen parametrityypeille joudutaan asettamaan joitakin rajoituksia. JUMP ja JZERO kelpuuttavat vain välittömän osoituksen (josta käytimme merkkiä "="). Rivi, jolle hypätään, pitää siis tietää aina suoraan. Sitä ei voida lukea mistään muistipaikasta. Toinen rajoitus on se, että STORE käsky ei hyväksy välitöntä osoitusta. Koska kyseinen käsky tallentaa akun sisällön muistipaikkaan, on sen pakko saada parametrinaan muistipaikan numero (joko suora tai epäsuora).

Ohjelman suoritus

Hajasaantikoneen tekemä ohjelman suoritus on erilainen kuin Turingin koneen. Hajasaantikone aloittaa ohjelman suorittamisen ensimmäisestä rivistä. Kun kone on suorittanut sen, se siirtyy seuraavaan jne. Kun viimeinen rivi on suoritettu kone pysähtyy. Hajasaantikone ei siis tarkista mitään ehtoja ennen ohjelmarivin suorittamista vaan se suorittaa niitä järjestyksessä ylhäältä alas päin. Suoritusjärjestykseen saadaan muutosia ainoastaan JUMP- tai JZERO-käskyllä.

Otetaan esimerkiksi ohjelma joka laskee yhteen muistipaikkojen 0 ja 1 sisällöt ja tallentaa tuloksen muistipaikkaan numero 2.
[DEFTABLE][D]1:
2:
3:[/D][E]LOAD &0
ADD &1
STORE &2[/E][/DEFTABLE]
Oletetaan, että muistipaikassa 0 on luku 132 ja muistipaikassa 1 luku 83 ja katsotaan mitä ohjelma tekee. Kone aloittaa ohjelman suorittamisen ohjelmariviltä numero 1. Eli se kopioi akun sisällöksi muistipaikan numero 0 sisällön eli luvun 132. Nyt akun sisältönä on luku 132. Sitten ensimmäinen ohjelmarivi on suoritettu ja kone siirtyy riviin numero 2. Tässä kone laskee yhteen akun sisällön eli luvun 132 ja ADD-komennon parametrin eli muistipaikassa 1 olevan luvun 83 saa tulokseksi 215 ja sijoittaa tämän luvun akun sisällöksi. Akun sisältö on nyt 215. Nyt rivi numero 2 on suoritettu ja kone siirtyy riviin numero 3. Tässä STORE käsky kopioi akun sisällön muistipaikkaan numero 2. Akun sisältö on edelleen 215 ja muistipaikan numero 2 sisältö on myös 215.

Hajasaantikonevisualisaattori

Esittelen vielä toisen havainnollistamisen apuvälineen. Kyseessä on hajasaantikonevisualisaattori ja se aukeaa allaolevasta linkistä.

http://www.suomipelit.com/files/artikkel...

Sitä käytetään lähes samoin kuin Turingin kone -visualisaattoriakin. Vasemman reunan laatikkoon kirjoitetaan ohjelma. Muistin sisältö näkyy alareunassa (muistipaikan numero näkyy muistipaikan alla) ja akun sisältö keskellä alhaalla. Koska muisti ei tietenkään mahdu kerralla ruudulle voit vierittää sitä alareunan painikkeista 1, 10 tai 100 paikkaa kerrallaan.

Keskellä näyttöä on kaksi asiaa joita emme vielä tarvitse. Ensimmäinen on valkea neliö ja toinen neljän tekstikentän ryhmä, joiden yllä kirjaimet V, Y, A ja O. Näiden komponenttien tarkoitus selviää seuraavassa kappaleessa. Jätä ne siihen asti huomiotta.

Hieman monimutkaisempi esimerkki

Otetaan hieman hankalampi esimerkki tekemällä ohjelma, joka laskee luvun kertoman. Luvun kertomahan lasketaan kertomalla keskenään luku itse ja kaikki sitä pienemmät luvut ykköseen asti. Luvun 6 kertoma on siis 6*5*4*3*2*1 = 720. Oletetaan, että luku jonka kertoma halutaan laskea on muistipaikassa numero 0 ja kertoma halutaan laskea muistipaikkaan numero 1.
[DEFTABLE][D]1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11: [/D][E]LOAD =1
STORE &1
LOAD &0
MULT &1
STORE &1
LOAD &0
SUBS =1
STORE &0
JZERO =11
JUMP =4
HALT[/E][/DEFTABLE]
Rivit 1, 2, ja 3 eivät tee muuta, kuin asettavat alkutilanteen. Ne asettavat muistipaikan 1 arvoksi luvun 1 ja akun arvoksi muistipaikassa 0 olevan luvun eli sen luvun, jonka kertoma halutaan laskea. Rivit 4 ja 5 kertovat keskenään akun ja muistipaikan 1 ja tallentavat tuloksen takaisin muistipaikkaan 1. Rivit 6, 7 ja 8 vähentävät muistipaikan 0 arvoa yhdellä. Rivi 9 testaa onko akun sisältö nolla ja jos on niin se sammuttaa ohjelman hyppäämällä suoraan HALT käskyyn. Jos hyppyä ei tapahtunut rivin 10 JUMP-käsky aloittaa kaiken taas alusta pisteestä, jossa akun sisältö kerrottiin muistipaikan 1 sisällöllä. Ohjelma siis toistaa rivejä 4-10. Jokaisella kierroksella suoritettaessa rivi 4 on akun sisältönä aina yhtä pienempi luku kuin edellisellä kierroksella. Kun tämä luku kerrotaan muistipaikan 1 sisällöllä ja tulos laitetaan tallennetaan samaan muistipaikkaan, tulevat kaikki luvut alkuperäisestä luvusta aina ykköseen asti kerrottua keskenään. Lopulta, kun akun sisältö laskee nollaan, ohjelma hyppää HALT-käskyyn ja sammuu.

Kokeile kertoman laskevaa ohjelmaa aiemmin esitellyllä visualisaattorilla. Kopioi ohjelma ohjelmakenttään ja kirjoita se luku, jonka kertoman haluat laskea (esim. luku 7) muistipaikkaan 0 ja paina käynnistä.

IO-laitteet #

Tässä vaiheessa saattaa askarruttaa yksi asia. Kuinka hajasaantikoneesta saa ulos kuvaa ja ääntä ja kuinka sen saa reagoimaan käyttäjän antamiin komentoihin.

Vastaus on: "ei yksin mitenkään". Tätä varten hajasaantikone tarvitsee lisälaitteita kuten näytön, näppäimistön ja hiiren. Ne ovat kaikki ns. syöttö- ja tulostuslaitteita eli IO-laitteita (lyhenne englannin kielen sanoista Input Output).

Ota huomioon, että tässä esittämäni toimintaperiaatteet ovat hieman ideaalistettuja versioita.

Tulostuslaitteet

Tulostuslaite on laite, joka välittää informaatiota koneesta käyttäjälle päin. Tulostuslaitteita ovat siis esim. monitori, kaiuttimet ja tietenkin tulostin. Huolimatta eroavaisuuksistaan kaikki tulostuslaitteet tekevät yhtä ja samaa: ne tulkitsevat käyttäjälle koneen muistin sisältöä. Käytännössä tämä tarkoittaa sitä, että laitteelle on määrätty koneen muistista tietty määrä muistipaikkoja, joiden sisältöä se tarkkailee ja esittää näissä muistipaikoissa olevien lukujen arvot käyttäjälle jollain tavalla.

Otetaan esimerkkinä monitori, koska se on yksinkertaisin. Monitori yksinkertaisesti tulkitsee muistipaikkojen sisältöä väreinä. Monitorin kuva koostuu pienen pienistä kuvapisteistä eli pikseleistä. Keskiverron monitorin kuva on yleensä kooltaan 1024 pikseliä vaakasuuntaan ja 768 pikseliä pystysuuntaan eli yhteensä 1024x768 = 768432 pikseliä. Jokaiselle pikselille on määrätty koneen muistista yksi muistipaikka, jonka sisältöä se tarkkailee ja määrää oman värinsä tässä muistipaikassa olevan lukuarvon mukaan jonkin tietyn sopimuksen mukaisesti. Esim. numero 0 voisi tarkoittaa mustaa ja numero 16777215 valkoista. Värien ja numeroiden vastaavuus on vain sopimuskysymys.

Monitorin käyttämien muistipaikkojen sijainti muistissa on myös sopimuskysymys. Käytännöllisistä syistä ne eivät ole hajallaan muistissa vain alkavat tietystä kohdasta ja ovat sitten järjestyksessä siitä eteenpäin yhtenä könttinä. Historiallisista syistä oikeissa tietokoneissa monitorin ensimmäisen pikselin (eli ylimmän rivin vasemmanpuoleisimman pikselin) käyttämän muistipaikan numero on 40960. Seuraavan pikselin (eli ylimmän rivin toinen pikseli vasemmalta) muistipaikan numero on 40961 ja sitä seuraavan 40962 jne... pikseli pikseliltä, rivi riviltä. Viimeisen pikselin (eli alarivin oikeanreunimmaisen pikselin) muistipaikan numero on "40962 + pikselien kokonaismäärä - 1". Jossakin vanhassa tietokoneessa näkyvän kuvan koko saattoi olla vain 320x200 = 64000 pikseliä. Tällöin viimeisen pikselin muistipaikan numero olisi 40962+64000-1=104961.

Ohjelman laatijan täytyy tietenkin tietää mitä muistipaikkoja monitori käyttää ja miten se minkäkin luvun väriksi tulkitsee, jotta osaisi sitä käyttävän ohjelman laatia.

Voit kokeilla monitorin toimintaa käytännössä aikaisemmin esitellyllä hajasaantikonevisualisaattorilla. Mustareunainen neliö sen keskellä nimittäin on yksinkertainen monitori. Tämän monitorin kuvan koko on 16x16=256 pikseliä. Sen pikselit edustavat koneen muistipaikkoja 1000-1255. Ylärivin vasemman puoleisin pikseli on muistipaikka 1000. Seuraava pikseli muistipaikka 1001 jne. Viimeisen pikselin muistipaikan numero on 1255. Monitori osaa näyttää vain kaksi väriä: valkoisen ja mustan. Se tulkitsee arvon 0 valkeaksi ja minkä tahansa muun arvon mustaksi. Koska kaikkien muistipaikkojen arvo on alussa 0 on tämä monitorikin alussa kokonaan valkea.

Otetaan seuraava esimerkkiohjelma. Se piirtää viiston mustan viivan monitorin vasemmasta ylänurkasta (muistipaikasta 1000) sen oikeaan alanurkkaan (muistipaikkaan 1255).
[DEFTABLE][D]1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:[/D][E]LOAD =1000
STORE &0
LOAD =1
STORE *0
LOAD &0
ADD =17
STORE &0
SUBS =1272
JZERO =11
JUMP =3
HALT[/E][/DEFTABLE]
Rivit 1 ja 2 asettavat muistipaikan 0 arvoksi luvun 1000 (Luku 1000:han on monitorin ensimmäisen pikselin muistipaikan numero.) Rivit 3 ja 4 asettavat sen muistipaikan arvoksi luvun 1, jonka numero löytyy muistipaikasta 0. (Monitori tulkitsee minkä tahansa nollasta poikkeavan arvon mustaksi eli esim. luku 1 kelpaa mustaksi.) Rivit 5, 6 ja 7 kasvattavat muistipaikan 0 arvoa luvulla 17. (Koska monitori oli 16 pikseliä leveä, on mitä tahansa pikseliä oikealla alaviistossa olevan pikselin muistipaikan numero 17 paikan päässä sen omasta.) Rivit 8 ja 9 testaavat onko akun arvo numero 1272 ja jos se on, niin suorituksessa hypätään riville 11 käskyyn HALT, joka pysäyttää ohjelman. (Viimeisen pikselin muistipaikan numero on 1255, joten sitä seuraavan oikealla alaviistossa olevan pikselin eli ensimmäisen sellaisen pikselin, jota ei tarvitse piirtää, muistipaikan numero on 1255+17=1272.) Rivi numero 10 ei tee muuta kuin hyppää takaisin riville 3, eli kaikki alkaa alusta kohdasta, jossa seuraavan pikseli arvoksi asetetaan 1. Ohjelma siis kiertää kokoajan silmukkaa. Se pitää seuraavaksi "mustattavan" pikselin muistipaikan numeroa tallessa muistipaikassa numero 0. Jokaisella kierroksella se mustaa tämän pikselin (asettaa arvoon 1) ja asettaa muistipaikkaan numero 0 seuraavaksi mustattavan pikselin muistipaikan numeron. Vasta, kun se kohtaa ensimmäisen muistipaikan, jota ei tarvitse mustata, ohjelma sammuu.

IO-laitteet voisi kytkeä ihan yhtä hyvin Turingin koneeseen kuin hajasaantikoneeseenkin. Esim. monitorille vain määräisiin tietyt ruudut muistinauhasta, joiden sisällön se näyttäisi graafisesti. Esim. jos ruutu olisi tyhjä, olisi sitä vastaava pikseli näytöllä valkoinen ja jos ei niin musta.

Syöttölaitteet

Syöttölaite toimii juuri päinvastoin kuin tulostuslaite. Se välittää informaatiota käyttäjältä koneelle päin. Se tekee tämän muuttamalla koneen muistipaikkojen sisältöä kesken ohjelman suorituksen aina, kun käyttäjä painaa jotain syöttölaitteessa olevaa painiketta. Syöttölaitteita ovat esim. näppäimistö, hiiri ja mikrofoni.

Otetaan esimerkiksi näppäimistö tai oikeastaan sen ideaalistettu versio. Oikea näppäimistö toimii eri tavalla kuin tässä on esitetty. Jokaiselle näppäimistön näppäimelle on määrätty tietokoneen muistista jokin muistipaikka. Mutta sen sijaan, että näppäin näyttäisi muistipaikan sisällön, sen tehtävä on pitää huolta, että muistipaikan sisältö edustaa näppäimen tilaa. Näppäimellä on vain kaksi mahdollista tilaa: "alas painettuna" ja "ylhäällä". Kumpaakin tilaa on sovittu edustamaan jokin numero. Esim. "alas painettuna" voisi olla numero 1 ja "ylhäällä" numero 0. Näin, aina kun käyttäjä painaa jotain näppäimistön painiketta, asettaa näppäimistö tätä painiketta vastaavan muistipaikan arvoksi luvun 1 ja kun käyttäjä vapauttaa painikkeen asetetaan muistipaikan arvoksi luku 0. Tällöin muistipaikan tila edustaa koko ajan painikkeen tilaa. Ohjelma voi reagoida näppäinten painalluksiin tutkimalla näppäimistölle varattujen muistipaikkojen sisältöä.

Esittämäni monitorin toimintaperiaate oli hyvin lähellä todellista. Sen sijaan näppäimistön ja vastaavien laitteiden osalta todelliset laitteet käyttävät hieman erilaista tekniikkaa. On nimittäin epäkäytännöllistä määrätä laitteen jokaiselle mahdolliselle nippelille ja nappelille omaa muistipaikkaa. Sen sijaan laite kuin laite tarvitsee periaatteessa vain vain kaksi muistipaikkaa. Käytetään näistä muistipaikoista nimiä "data" ja "lippu".

Kun käyttäjä painaa jotain näppäimistön (tai minkä tahansa muun syöttölaitteen) painiketta asettaa se lipun arvoksi numeron 1 merkiksi siitä, että tässä laitteessa on tapahtunut tapahtuma ja datan arvoksi sen painikkeen numeron, jota painettiin. Sen jälkeen syöttölaite jää odottamaan tapahtuman käsittelyä tarkkailemalla lipun sisältöä. Reagoidakseen tapahtumaan ohjelman ei nyt tarvitse tutkia laitteen mahdollisesti satoja muistipaikkoja, vaan vain ja ainoastaan lippu. Jos lippu on arvoltaan 0 voi ohjelma hypätä suoraan tapahtuman käsittelyn yli (JZERO käsky). Jos taas lippu on 1 ei ohjelma hyppää käsittelyn yli vaan lukee datan arvon ja reagoi siihen. Tehtyään haluamansa asiat ohjelma kirjoittaa lipun arvoksi taas luvun 0. Lipun arvoa tarkkailevalle syöttölaitteelle tämä on merkki siitä, että ohjelma on käsitellyt tapahtuman ja se voi kirjoittaa dataan ja lippuun seuraavan painalluksen.

Voit kokeilla myös näppäimistön toimintaa käytännössä jo tutulla hajasaantikonevisualisaattorilla. Neljän kentän ryhmä keskellä edustaa 4 painikkeista näppäimistöä. Painikkeet vastaavat näppäimistön nuolinäppäimiä vasen (V), ylös (Y), alas (A) ja oikea (O). Näille näppäimille on varattu samassa järjestyksessä muistipaikat 2000, 2001, 2002 ja 2003. Kenttiä ei voi editoida. Ne vain näyttävät kyseisten muistipaikkojen sisällöt, jotta sinun ei tarvitsisi kelata ruudun alareunassa olevaa muistin sisältöä muistipaikkaan 2000 asti. Kun painat omasta näppäimistöstäsi jotain näistä painikkeista asettuu vastaavan muistipaikan arvoksi luku 1 ja kun vapautat painikkeen tulee arvoksi 0.

Päätämmekin tämän ensimmäisen osan eräänlaisella matopelin alkeisversiolla. Teemme hajasaantikonevisualisaattorille ohjelman, jossa ruudulla sijaitsee musta piste, jota voi liikuttaa eteenpäin näppäimistön oikealla nuolinäppäimellä. Pelin tarkoituksena on viedä piste ruudun alareunan oikeaan nurkkaan asti. Kun piste on perillä on peli ohi ja ohjelma sammuu.

Ohjelmaa varten täytyy pitää kirjaa siitä missä kohdassa piste on menossa, joten tallennetaan pisteen muistipaikan numero muistipaikkaan 0. Piste lähtee monitorin vasemmasta ylänurkasta eli muistipaikasta 1000.
[DEFTABLE][D]1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:[/D][E]LOAD =1000
STORE &0
LOAD =1
STORE &1000
LOAD &2003
JZERO =5
LOAD =0
STORE *0
LOAD &0
ADD =1
STORE &0
LOAD =1
STORE *0
LOAD &0
SUBS =1255
JZERO =18
JUMP =5
HALT[/E][/DEFTABLE]
Rivit 1 ja 2 asettavat muistipaikkaan 0 pisteen alkusijainnin eli numeron 1000. Rivit 3 ja 4 piirtävät pisteen sen alkupaikkaan. Rivit 5 ja 6 tarkistavat onko oikea nuolipainike pohjassa eli onko muistipaikan 2003 arvo eri suuri kuin nolla. Jos ei ole hypätään takaisin alkuun. Jos on, niin pitää siirtää pistettä yksi pykälä eteenpäin. Ensin on kuitenkin pyyhittävä vanha piste. Tämän tekevät rivit 7 ja 8. Ne lukevat pisteen sijainnin muistipaikasta 0 ja "valkaisevat" pikselin kirjoittamalla sen sijaintiin arvon 0. Varsinaisen siirron tekevät rivit 9, 10 ja 11. Ne kasvattavat muistipaikan 0 sisällön arvoa yhdellä. Piste pitää kuitenkin vielä piirtää uuteen sijaintiinsa. Tähän tarvitaan rivit 12 ja 13. Siinä pikselin uuteen sijaintiin (joka löytyy muistipaikasta 0) kirjoitetaan arvo 1 eli musta. Lopuksi vielä tarkistetaan on piste perillä alanurkassa eli voiko pelin jo lopettaa. Tästä huolehtivat rivit 14, 15 ja 16. Jos piste sijaitsee monitorin viimeisessä muistipaikassa eli muistipaikassa 1255 on "pisteen sijainti - 1255" arvoltaan 0 ja JZERO hyppää käskyyn HALT pysäyttäen ohjelman. Jos näin ei ollut ohjelma saavuttaa rivin 17 ja hyppää takaisin alkuun uudelle kierrokselle.

Kopioi ohjelman sisältö hajasaantikonevisualisaattoriin, laita nopeus maksimiin (säädin arvoon 0) ja paina käynnistä. Monitorin ylänurkassa pitäisi näkyä musta piste. Paina näppäimistösi oikea nuolinäppäin pohjaan ja pisteen pitäisi lähteä liikkumaan. Kun vapautat painikkeen piste pysähtyy. Kun piste saavuttaa alanurkan ohjelma sammuu.

Tästä on vielä pitkä matka oikeasti mielekkääseen peliin, mutta onpahan alku. Itse asiassa oikean pelin vääntäminen tässä esitetyllä tavalla olisi aivan liian monimutkainen urakka. Tätä varten tarvitaan helpotusta ohjelmointiin, josta puhumme vasta artikkelisarjan kolmannessa osassa. Seuraavassa osassa hylkäämme tietokoneen teoreettiset mallit ja siirrymme oikeisiin tietokoneisiin.