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 2: Fyysistä tietokonetta rakentamassa

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.

25.10.2006 julkaistun artikkelin on kirjoittanut Markus.

  1. Hajasaantikonetta rakentamassa
  2. Numeron esittäminen sähkövirran avulla
  3. Laskeminen sähköisesti
  4. Tiedon tallentaminen sähköisesti
  5. Konekieli

Hajasaantikonetta rakentamassa #

Hajasaantikone on vain teoreettinen malli. Ennen kuin sitä voidaan hyödyntää, pitää sellainen oikeasti rakentaa. Kaikki oikeat tietokoneet ovat vain hajasaantikoneen fyysisiä toteutuksia.

Karikatyyri tyypillisestä hajasaantikoneestaKarikatyyri tyypillisestä hajasaantikoneesta

Vaikka hajasaantikoneen käyttäjän ja/tai ohjelman laatijan ei periaatteessa tarvitse välittää tuon taivaallista siitä, miten hajasaantikone on fyysisesti rakennettu, on koneen fyysinen rakenne hyvä ymmärtää, sillä kaikki käytännön toteutukset asettavat joitakin mielenkiintoisia rajoituksia koneen toiminnalle. Näistä rajoituksista ilmeisimpänä se valitettava tosiasia, että oikealle koneelle ei voida antaa äärettömän isoa muistia.

Oikeat tietokoneet eivät ole mekaanisia koneita, vaan niiden toiminta perustuu sähköön. Tämä varten tutkimme tässä osassa hajasaantikonetta komponentti kerrallaan ja esitämme, kuinka ne voidaan toteuttaa sähkön avulla.

Koska hajasaantikoneen täytyi pystyä esittämään numeroita, aloitamme tutkimalla, kuinka sähkövirtaa voi käyttää esittämään numeroa.

Numeron esittäminen sähkövirran avulla #

Ensimmäinen mieleen tuleva tapa lienee esittää numeroa sähkövirran voimakkuutena. Mitä suurempi virta, sitä suurempi numero. Tämä idea on kuitenkin kuollut jo syntyessään. Tarpeeksi suuri numero voisi synnyttää virran, joka polttaisi laitteen kuin laiteen, eikä olisi kiva sähkölaskun kannaltakaan.

Toinen hankala asia on mitata virta niin tarkasti, että sen esittämä numero voitaisiin 100% varmasti tulkita oikein. Pienikin (esim. kaukaisen salaman aiheuttama) virtapiikki saattaisi muuttaa tuloksen. Ainoat virrat, joiden välille voidaan tehdä varma ero, ovat nolla virta (tai jokin hyvin matala virta) ja ei nolla virta. Tämä onkin tietokoneiden ottama lähestymistapa. Tällä tavalla voidaan esittää kuitenkin vain kaksi numeroa: 0 (virta ei kulje) ja 1 (virta kulkee).

Binäärijärjestelmä

Koska elektroniikka, jolla hajasaantikone toteutetaan, ei osaa esittää kuin kaksi numeroa: 0 (sähkövirta ei kulje) ja 1 (sähkövirta kulkee), tulee eteen ongelma hajasaantikoneen vaatimukselle esittää mielivaltaisia numeroita. Ratkaisu on esittää mielivaltaista numeroa sarjana nollia ja ykkösiä.

Numeron esittäminen sarjana muita numeroita ei ole vieras, sillä niinhän me numerot arkipäivässäkin esitämme. Käytämme vain kymmentä eri numeromerkkiä: 0, 1, 2, 3, 4, 5, 6, 7, 8 ja 9. Jos halutaan esittää numero, joka on suurempi kuin 9, laitetaan vain kaksi tai useampi numeromerkki peräkkäin. Ensimmäinen numeromerkki esittää ykkösiä (10^0=1). Toinen esittää kymmeniä (10^1=10), kolmas satoja (10^2=100), neljäs tuhansia (10^3=1000), jne. Paikalla i oleva merkki esittää aina lukua 10^(i-1). Esimerkiksi merkkijono ”5823” tarkoittaa viisituhattakahdeksansataakaksikymmentäkolme (kertolaskuna ilmaistuna 5*1000+8*100+2*10+3*1).

Käyttämäämme numerojärjestelmää kutsutaan kymmenjärjestelmäksi, koska siinä on kymmenen erilaista numeromerkkiä. Käytössä olevien numeromerkkien määrää kutsutaan numerojärjestelmän kantaluvuksi, eli kymmenjärjestelmän kantaluku on 10.

Saman periaatteen mukaan numeroita voidaan esittää käyttäen vain kahta numeromerkkiä (0 ja 1). Tällaista järjestelmää kutsutaan binäärijärjestelmäksi ja sen kantaluku on 2. Jos binäärijärjestelmässä halutaan esittää luku, joka on suurempi kuin 1, pitää laittaa kaksi tai useampi merkki peräkkäin. Saadussa luvussa ensimmäinen merkki esittää ykkösiä (2^0=1), toinen esittää kakkosia (2^1=2), kolmas esittää nelosia (2^2=4), neljäs esittää kahdeksikkoja (2^3=8), jne. Paikalla i oleva merkki esittää aina lukua 2^(i-1). Esimerkiksi merkkijono ”1101” tarkoittaa yksikahdeksaayksineljäänollakahtayksi. Ei oikein kuulosta selvälle, varsinkin, kun se kirjoitetaan yhteen. Ymmärtämistä helpottaa, kun ajattelet asian kertolaskuna 1*8+1*4+0*2+1. Jos lasket kertolaskun, saat selville, että binäärijärjestelmän luku ”1101” olisi kymmenjärjestelmässä luku 13.

Seuraavassa 16 ensimmäisen luvun (luvut 0-15) vastineet binäärijärjestelmässä.
[DEFTABLE][D]Kymmenjärjestelmä
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[/D][E]Binäärijärjestelmä
0
1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
1111[/E][/DEFTABLE]
Huomaat varmaan, että binäärijärjestelmässä numeromerkkejä tarvitaan enemmän kuin kymmenjärjestelmässä.

Väylät

Yhtä binäärijärjestelmän numeromerkkiä (0 tai 1) kutsutaan bitiksi. Bittien määrää binääriluvussa kutsutaan luvun bittisyydeksi. Esim. binääriluku ”10011101” (joka vastaa kymmenjärjestelmän lukua 157) on 8-bittinen.

Kun binäärijärjestelmän luku esitetään sähkövirran avulla, tarvitaan useita rinnakkaisia johtimia. Yksi luvun jokaista bittiä kohden. Jos tässä johtimessa kulkee virta, tulkitaan sitä vastaava bitti ykköseksi, ja jos ei, niin nollaksi. Johtimet muodostavat väylän. Johtimia ei voi kuitenkaan olla äärettömän paljon, joten täytyy vetää jokin raja sille, kuinka monta johdinta väylässä on, eli kuinka leveä se on. Väylän leveys asettaa ylärajan sille, kuinka suuria numeroita tietokoneella voi esittää. Jos väylässä on esim. 8 johdinta, eli se on 8-bittinen, on suurin sillä esitettävä luku ”11111111” eli kymmenjärjestelmän luku 255.

Tätä väylän leveyttä kutsutaan tietokoneen bittisyydeksi ja se on oikeissa tietokoneissa yleensä 32. Suurin 32 bitillä esitettävä luku on ”11111111111111111111111111111111” eli kymmenjärjestelmän luku 4294967295. Myös ensimmäiset 64-bittiset tietokoneet ovat alkaneet ilmaantua. Suurin 64 bitillä esitettävä luku on kymmenjärjestelmässä ilmaistuna 18446744073709551615.

Laskeminen sähköisesti #

Hajasaantikoneen logiikkayksikköä vastaa oikeassa tietokoneessa prosessori. Sen tehtävänä on mm. suorittaa laskutoimituksia. Numeroiden esittäminen binäärijärjestelmässä kymmenjärjestelmän sijaan ei yllättäen tee laskutoimituksia vaikeammiksi vaan huomattavasti helpommiksi.

On olemassa puolijohteiksi kutsuttuja materiaaleja, joista sopivasti seostamalla saadaan rakennettua johdin, jossa virta voi kulkea vain yhteen suuntaan. Tällaista johdinta kutsutaan diodiksi. Yleisin tietokoneissa käytetty puolijohdemateriaali on pii, jonka takia niiden prosessoreita kutsutaan joskus piisiruiksi.

Diodeista voidaan kasata ns. loogisia portteja. Ne ovat johtimien välisiä liittimiä, joissa on yksi ulostulo, ja yksi tai useampi sisäänmeno. Se tuleeko portista ulos virtaa, vai ei, riippuu jonkin logiikan mukaan siitä, kuinka moneen sen sisäänmenoon menee virta. Tämä logiikka riippuu portin sisäisestä rakenteesta ja toteutetaan diodien avulla. En ota tässä sen kummemmin kantaa porttien sisäiseen rakenteeseen. Itse asiassa diodit ovat vain yksi tapa toteuttaa loogiset portit. Portit voisi yhtä hyvin toteuttaa vaikka optisesti tai mekaanisesti.

Erilaisia loogisia portteja voi tietenkin olla äärettömän monta, mutta niistä tarvitaan vain muutamaa erilaista. Esittelen tässä yleisimmät portit eli JA-, TAI-, XTAI- ja EI-portit

JA-portti

JA-portissa on kaksi sisäänmenoa ja sen piirrossymboli näyttää seuraavanlaiselle (, jossa a ja b ovat sisäänmenot).


JA-portti päästää virtaa ulos vain, jos se saa virtaa sisään kummastakin sisäänmenostaan. Muuten virtaa ei tule ulos ollenkaan. Portin toiminta on täten seuraavan taulukon mukainen. 0 tarkoittaa, että virta ei kulje, ja 1 tarkoittaa, että virta kulkee.

Ulos tulee siis virtaa vain, jos sitä menee sisään sisäänmenosta a ja sisäänmenosta b. Tästä nimi JA-portti.

TAI-portti

TAI-portissa on kaksi sisäänmenoa ja sen piirrossymboli on seuraavan näköinen.

TAI-portti päästää ulos virtaa aina, jos se saa virtaa ainakin toisesta sisäänmenostaan eli sen toiminta on seuraavan taulukon mukainen.

Ulos tulee siis virtaa jos sitä menee sisään sisäänmenosta a tai sisäänmenosta b.

XTAI-portti

XTAI-porttia kutsutaan joskus myös JOKO-TAI-portiksi. Portissa on kaksi sisäänmenoa ja sen piirrossymboli on seuraavan näköinen.

Se päästää ulos virtaa vain, jos se saa sitä jommasta kummasta sisäänmenostaan, mutta ei, kun se saa sitä molemmista. Toiminta on täten seuraavan taulukon mukainen.

Virtaa tulee ulos siis silloin, kun sitä menee sisään joko sisäänmenosta a tai sisäänmenosta b (, mutta ei silloin kun molemmista).

EI-portti

Viimeisenä esittelen EI-portin. Toisin kuin aikaisemmissa porteissa EI-portissa on vain yksi sisäänmeno. Portin piirrossymboli näyttää seuraavalta.

EI-portti päästää ulos virtaa vain, jos sitä ei sisään mene. Sen toiminta on täten seuraavan taulukon mukainen.

Ennen kuin alat pitää EI-porttia ratkaisuna maailman energiapulaan, eli laitteena, joka tuottaa sähköä tyhjästä silloin, kun sitä ei siihen syötetä, niin mainittakoon, että näin ei ole. EI-porttiin pitää viedä ylimääräinen piilotettu sisäänmeno, josta virta syötetään ulos silloin, kun sitä ei siihen varsinaisesta sisääntulosta mene. Itse asiassa kaikkiin portteihin täytyy viedä paitsi piilotettu sisäänmeno, myös piilotettu ulostulo, johon virta viedään silloin, kun sitä ei saa tuoda ulos ulostulosta. Tämä ei kuitenkaan ole olennaista.

Laittamalla EI-portti minkä tahansa muun portin perään, saadaan rakennettua kyseisen portin vastakohta. Esim. JA-portin vastakohta JA-EI-portti saadaan laittamalla EI-portti JA-portin perään. JA-EI-portin piirrossymboli on seuraavanlainen.

Ainoana erona JA-portin symboliin pieni ympyrä ulostulon kohdalla.

Toiminta on JA-portin vastakohta eli seuraavanlainen.

Muiden porttien vastakohdat TAI-EI ja XTAI-EI vastaavasti. Piirrossymboleissa ainoana erona pieni ympyrä ulostulon edessä.

Summain

Loogisten porttien avulla on mahdollista toteuttaa sähkövirralla kaikki laskutoimitukset, kun sovitaan, että ”virta ei kulje” tarkoittaa numeroa 0 ja ”virta kulkee” tarkoittaa numeroa 1. Otetaan esimerkkinä ainoastaan yhteenlasku, koska se on yksinkertaisin.

Aloitetaan yksibittisten lukujen yhteenlaskusta. Jos (ja totta kai kun) tarvitsee laskea yhteen lukuja, jotka ovat suurempia kuin yksi bitti, voidaan soveltaa ”allekkain lasku”-periaatetta. Tämä periaatehan opetetaan meille ala-asteella. Jos tarvitsee laskea yhteen kaksi isoa lukua, kirjoitetaan ne paperille allekkain. Nyt jokainen numero lasketaan vain yhteen sen numeron kanssa, joka on samalla kohti pystysuunnassa. Näin ei tarvitse osata laskea päässä kuin yksi numeroisilla luvuilla.

Seuraava taulukko esittää kaikki neljä mahdollista vaihtoehtoa yksibittisten lukujen a ja b yhteenlaskussa (käyttäessä binäärijärjestelmää).

Vastaus on myös yksibittinen, paitsi viimeisessä tapauksessa, jossa vastaus on kaksibittinen. Ongelma on sama kuin allekkain laskussa, kun numeroiden summa on kymmenen tai enemmän. Ongelma ratkaistaan ottamalla numeroista takimmainen vastaukseksi ja jättämällä etummainen numero muistinumeroksi seuraavaa laskutoimitusta varten.


Seuraavassa sama taulukko uudelleen, mutta siihen on erotettu tulos (takimmainen numero) ja muistinumero (etummainen numero).

Jos vertaan tulos-saraketta XTAI-portin taulukkoon ja muistinumero-saraketta JA-portin taulukkoon, huomaat yhtäläisyyden. Kahden bitin yhteenlaskussa tulos saadaan XTAI-portilla ja muistinumero JA-portilla. Kytkentä, joka laskee yhteen bitit a ja b, voisi olla seuraavan näköinen. Kyseistä kytkentää kutsutaan puolisummaimeksi.

Entäpä jos laskussa tarvitsee ottaa huomioon edellisestä laskusta saatu muistinumero? Tällöin tarvitsee itseasiassa laskea yhteen kolme yksibittistä lukua a, b ja muistinumero. Seuraava taulukko esittää kaikki 8 mahdollista vaihtoehtoa tuloksineen.

Laskutoimitus tehdään laittamalla peräkkäin kaksi puolisummainta. Ensimmäinen laskee yhteen varsinaiset luvut a ja b. Toinen laskee yhteen äsken saadun vastauksen ja edellisen muistinumeron. Kytkentää kutsutaan (koko)summaimeksi ja se on seuraavan näköinen.

Vasemmanpuoleisin XTAI-portti ja alin JA-portti muodostavat ensimmäisen puolisummaimen ja keskimmäiset XTAI- ja JA-portti toisen puolisummaimen. Kummastakin laskusta voi jäädä muistinumero (mutta ei yhtä aikaa molemmista). Täten koko laskusta jää muistinumero jos se jää ensimmäisestä tai toisesta. Tätä varten vielä yksi TAI-portti.

Kun tarvitsee laskea yhteen kaksi N-bittistä lukua, laitetaan rinnakkain N-kappaletta summaimia. Kytketään jokaisen ulostuleva muistinumerojohdin seuraavan sisään menevään muistinumerojohtimeen. Seuraava kuva näyttää kytkennän kahden 4-bittisen luvun yhteenlaskua varten.

Kuvassa on kaksi huomioitavaa asiaa. Ensimmäisen summaimen sisäänmenevä muistinumero on aina nolla. Toinen on se, että jos viimeisestä laskusta jää muistinumero, ei se enää mahdu ulostuloväylään, vaan menee ”harakoille”. Puhutaan, että laskutoimitus vuotaa yli ja tulos on näin väärä. Ainut ratkaisu on olla laskematta liian isoilla numeroilla.

Summaimia täytyy olla rinnakkain yhtä monta kuin on tietokoneen väylän leveys eli bittisyys. Tavallisessa tietokoneessa on siis 32 summainta rinnakkain. Yhteenlaskun lisäksi myös kaikille muille laskutoimituksille on mahdollista rakentaa ne laskeva piirisarja, mutta en käsittele niitä tässä, kuten en myöskään desimaalilukuja. Sitä osaa prosessorista, jossa laskutoimitukset laskevat piirisarjat sijaitsevat, kutsutaan aritmeettisloogiseksi yksiköksi, ja siitä käytetään yleensä lyhennettä ALU.

Tiedon tallentaminen sähköisesti #

Tähän mennessä on käyty läpi hajasaantikoneen toteutus laskennan osalta. Seuraavaksi tutustutaan kuinka sen muisti toteutetaan sähkön avulla.

Koska oikeat tietokoneet esittävät numerot binäärijärjestelmässä eli sarjana ykkösiä ja nollia, helpottuu myös muistin toteutus huomattavasti. Muistin tarvitsee vain pystyä tallentamaan kaksi eri merkkiä ”0” ja ”1”. Jälleen kerran binäärijärjestelmä tekee asiat helpoksi.

Kiikku

Yksinkertaisin mahdollinen laite, joka pystyy tallentamaan yhden bitin, on nimeltään kiikku. Se rakennetaan loogisista porteista summaimen tapaan ja kytkentä näyttää seuraavalta.


Kiikussa on kaksi sisäänmenoa D ja C, sekä yksi ulostulo Q. Kiikku eroaa oleellisesti summaimesta siinä, että siinä on takaisinkytkentä ulostulosta Q aikaisempaan kohtaan kiikkua. Ulostulon Q arvo riippuu siis paitsi sisäänmenoista D ja C niin myös Q:n aikaisemmasta arvosta! Seuraava taulukko esittää kaikki kahdeksan mahdollista tapausta.

Huomataan, että aina, kun C on nolla, ovat uusi ja vanha Q samat (riippumatta D:n arvosta). Lisäksi aina, kun C on ykkönen, on uusi Q sama kuin D (riippumatta edellisestä Q:n arvosta). Kiikku siis muistaa arvonsa niin kauan, kuin vain C:n arvo on nolla. Kun C saa arvon yksi, kiikku vaihtaa arvokseen D:n, jonka se taas muistaa, kunhan C:n arvoksi vaihdetaan nolla. Sisäänmeno C on kontrollilinja. Se kertoo kiikulle luetaanko kiikun arvo vai tallennetaanko kiikkuun arvo.

Yksi kiikku tallentaa yhden bitin. Koko väylän esittämän numeron tallentamiseksi pitää olla jokaiselle johtimelle oma kiikku. Monta rinnakkaista kiikkua muodostaa tietokoneen yhden muistipaikan. Kuvassa esimerkkinä 4-bittinen muistipaikka.

Kontrollilinja C on kaikille yhteinen. Jos sen arvo on 0, luetaan muistin sisältö ulostulevaan väylään. Jos sen arvo taas on 1, kirjoitetaan sisään menevän väylän arvo muistin sisällöksi.

Muistipaikat

Se kuinka monta kiikkua yhteen muistipaikkaan sijoitetaan, määrää kuinka suuren luvun siihen voi tallentaa. Looginen valinta olisi laittaa yhteen muistipaikkaan yhtä monta kiikkua, kuin on tietokoneen bittisyys. Näin yhteen muistipaikkaan sopisi täsmälleen se suurin mahdollinen luku, joka tietokoneella on mahdollista esittää.

Jostain syystä näin ei ole menetelty. Sen sijaan on sovittu, että yksi muistipaikka voi tallentaa aina tasan kahdeksan bittiä. Tätä määrää ”8 bittiä” kutsutaan tavuksi. Yksi muistipaikka sisältää täten aina yhden tavun.

Suurin yhdellä tavulla esitettävä luku on ”11111111” eli 255. Ei kovin paljoa. Näin suuremmat esim. 32-bittiset luvut pitää jakaa useampaan muistipaikkaan. Ensimmäiset 8 bittiä ensimmäiseen, seuraavat 8 toiseen jne.

Tietokoneen muistin koko ilmoitetaan tavuina (, joka on myös samalla muistipaikkojen määrä). Koska muistin koko on tavallisesti miljoonia ellei miljardeja tavuja, käytetään tavujen kanssa kilometrien ja kiligrammojen tapaan etuliitteitä kilo, mega, giga jne. ilmaisemaan kertaluokkaa. Ainut ero on, että suhdeluku ei ole 1000 vaan 1024. Seuraavassa tavallisimmat.
[DEFTABLE]
[D]Etuliite[/D][E]Merkitys[/E]
[D]kilotavu[/D][E]1024 tavua[/E]
[D]megatavu[/D][E]1024 kilotavua eli noin miljoona tavua[/E]
[D]gigatavu[/D][E]1024 megatavua eli noin miljardi tavua[/E]
[D]teratavu[/D][E]1024 gigatavua eli noin biljoona tavua[/E]
[D]petatavu[/D][E]1024 teratavua eli noin biljardi tavua[/E]
[/DEFTABLE]
Keskiverrossa tietokoneessa on nykyään noin yksi gigatavu muistia. Tietokoneen bittisyys antaa ehdottoman ylärajan sille, kuinka paljon muistia koneessa voi olla. Koska jokaiseen muistipaikkaan pitää voida viitata sen numerolla, ei koneessa voi olla suurinumeroisempaa muistipaikkaa kuin se pystyy esittämään. 32-bittisessä tietokoneessa voi olla täten korkeintaan noin 4 gigatavua muistia.

Massamuistit

Koska tietokoneen muisti perustuu sähköön, häviää sen sisältö, jos tietokoneesta katkaistaan virta. Lisäksi 32-bittisen tietokoneen maksimissaan neljä gigatavua muistia on yllättävän vähän monessa ihan arkipäiväisessäkin tilanteessa. Tätä varten tarvitaan avuksi valtavan suuri kapasiteettisia muisteja, jotka säilyttävät sisältönsä myös sähköjen ollessa poikki. Tällaisia muisteja kutsutaan massamuisteiksi. Sana ”massa” viittaa muistien suureen kapasiteettiin eli massiivisuuteen. Suurimmissa massamuisteissa voi olla jopa biljoona tavun kokoista muistipaikkaa eli teratavun verran muistia.

Massamuistit ovat itse asiassa syöttö-/tulostuslaitteita ja vielä kumpaakin yhtä aikaa. Massamuistiin ”tulostaminen” tallentaa tiedon sinne ja sieltä ”syötteen” lukeminen hakee tiedon muistista. Massamuisteissa on huomattavasti enemmän muistipaikkoja, kuin mitä 32-bitillä voidaan numeroida, siksi niiden on pakko toimia ”lippu ja data” periaatteella. Data-kenttiä tarvitaan kaksi kappaletta (joista kumpikin vie useamman muistipaikan). Toiseen datakenttään laitetaan data, joka muistiin halutaan tallentaa ja toiseen se massamuistin muistipaikan numero, johon se tallennetaan. Tämän jälkeen lippukenttä asetetaan arvoon, joka kertoo sitä tarkkailevalle massamuistille, että data halutaan tallentaa haluttuun osoitteeseen. Vastaavasti tietoa luettaessa asetetaan lippu arvoon, joka tarkoittaa tiedon lukemista. Tällöin massamuisti käy kopioimassa halutusta muistipaikastaan arvon data kenttään. Tarkka toteutus tietenkin vaihtelee massamuisteittain, mutta periaate on sama.

Yleisin käytössä oleva massamuisti on kiintolevy, se tallentaa tiedon magnetismin avulla. Tieto tallennetaan pienten magneettien asentoina levyn pintaan. Muita yleisiä massamuisteja ovat CD- ja DVD-levyt. Ne tallentavat tiedon pieninä kuoppina levyn pintaan.

Konekieli #

Teoreettisessa hajasaantikoneessa ohjelman muodostamat ohjelmarivit sijaitsivat erillisessä varastossa. Näin ei kuitenkaan tehdä oikeassa tietokoneessa, sillä tämä monimutkaistaisi koneen toteutusta. Sen sijaan ohjelmarivit varastoidaan koneen varsinaiseen muistiin aivan tavallisiin muistipaikkoihin.

Tietokoneen muisti pystyi kuitenkin tallentamaan vain ykkösiä ja nollia, kun taas ohjelmarivit koostuivat kahdesta osasta: käskystä ja parametrista. Parametri oli aivan tavallinen numero: joko luku tai muistipaikan numero. Tämä numero voidaan esittää binäärimuodossa ja tallentaa näin muistiin ykkösinä ja nollina.

Käsky sen sijaan oli jokin sana esim. ”LOAD” tai ”STORE”. Koska erilaisia käskyjä on vain äärellinen määrä, voidaan tehdä sopimus siitä, millainen bittijono kutakin käskyä esittää. Voitaisiin sopia, että ”101100” tarkoittaisi käskyä ”STORE” ja ”011011” tarkoittaisi käskyä ”LOAD”. Esittämässäni teoreettisessa hajasaantikoneessa oli vain yhdeksän käskyä. Oikeissa tietokoneissa korkeintaan muutamia satoja. Määrän vähäisyyden takia vain muutamalla bitillä voidaan saada aikaan tarpeeksi yhdistelmiä kaikkien käskyjen esittämiseen. Näin voidaan ottaa käskyä esittävän bittijonon lopusta pari bittiä esittämään parametrin tyyppiä jonkin sopimuksen mukaan. Voitaisiin esim. sopia, että ”11” tarkoittaisi epäsuoraa osoitusta ja ”01” välitöntä osoitusta.

Esim. ”STORE *97” muuttuisi muotoon ”10110011 01100001” ja ”LOAD =2” muuttuisi muotoon ”01101101 00000010”. Koko ohjelmarivi ei tietenkään mahdu yhteen muistipaikkaan, vaan se pitää jakaa pätkiksi useampaan peräkkäiseen muistipaikkaan. Pelkästään parametri vie yleensä 4 muistipaikkaa (4*8 bittiä = 32 bittiä, joka riittää esittämään 32-bittisen tietokoneen minkä tahansa muistipaikan numeron).

Prosessorien tarjoamien käskyjen määrä vaihtelee merkeittäin/tyypeittäin ja tarjolla olevia käskyjä kutsutaan prosessorin käskykannaksi. Käskyjen määrässä on kaksi eri koulukuntaa: RISC (Reduced Instruction Set Computer) ja CISC (Complex Instruction Set Computer). RISC-prosessorit pyrkivät tarjoamaan suppean valikoiman käskyjä, jotta prosessori olisi yksinkertaisuuden vuoksi mahdollisimman tehokas toteuttaa. CISC-prosessorit taas pyrkivät tarjoamaan suuren valikoiman käskyjä silläkin uhalla, että prosessorista tulee monimutkaisuuden takia hitaampi. Suurin osa käytössä olevista prosessoreista on CISC prosessoreita. Churchin-Turingin teesin mukaan kumpikaan prosessori ei tietenkään voi tehdä mitään sellaista mitä toinenkaan ei voi. Itse asiassa ainoat tarvittavat käskyt ovat ”LOAD”, ”STORE”, ”ADD”, ”JUMP” ja ”JZERO”. Kaikki muut käskyt on mahdollista toteuttaa näiden avulla.

Käskyjen laittaminen muistiin muun datan sekaan tuo oikealle tietokoneelle aivan uuden mahdollisuuden, jota teoreettisella hajasaantikoneella ei ollut. Kun käsky on tavallinen numero tavallisessa muistipaikassa, voi kone kirjoittaa sen päälle uuden käskyn (tarkemmin käskyä vastaavan numeron). Toisin sanoen kone voi muuttaa omaa ohjelmaansa! Itseään muuttava kone saattaa kuulostaa todella ihme vehkeeltä, jolla voi tehdä jotain suurta ja hienoa, mutta itse asiassa näin ei ole. Churchin-Turingin teesin mukaan sillä ei nimittäin voi tehdä mitään sellaista, mitä Turingin koneellakaan ei voi tehdä. Tämä uusi ominaisuus on siis täysin turha.

Ohjelman suoritus

Ohjelman suorituksessa on vielä yksi tärkeä asia, johon en ottanut kantaa hajasaantikoneen teoreettisessa mallissa: miten kone pitää kirjaa siitä, mitä ohjelmariviä se parhaillaan suorittaa? Tätä varten koneessa pitää olla akun lisäksi vielä yksi ylimääräinen muistipaikka: ohjelmalaskuri. Tämän muistipaikan tarkoitus on pitää kirjaa siitä, mikä ohjelmarivi on tällä hetkellä suorituksessa. Koska ohjelmarivit ovat oikeassa tietokoneessa tavallisessa muistissa, sisältää ohjelmalaskuri käytännössä sen muistipaikan numeron, jossa oleva ohjelmarivi on tällä hetkellä suorituksessa.

Kun koneen pitää suorittaa ohjelmarivi, se tarkistaa ohjelmalaskurista, mikä ohjelmarivi on tarkoitus suorittaa ja suorittaa sen. Ohjelmarivin suoritettua kone kasvattaa ohjelmalaskurin arvoa yhdellä. Näin suoritukseen tulee seuraavaksi järjestyksessä seuraava ohjelmarivi. Tällöin myös JUMP-käsky on helppo toteuttaa. Kone vain kirjoittaa ohjelmalaskuriin JUMP-käskyn parametrina olevan luvun.

Prosessorin sydämenä tikittää pieni kello ja sen nopeutta mitataan hertseinä. Yksi hertsi vastaa yhtä kellopulssia sekunnissa. Näin esimerkiksi megahertsin prosessorin kello tikittää miljoona pulssia sekunnissa. Kello lähettää prosessorin väyliin jokaisella sykäyksellä sähköpulssin, saaden prosessorin suorittaman näin yhden ohjelmarivin. Ainakin periaatteessa voisi olettaa, että prosessori suorittaa yhden ohjelmarivin per kellopulssi. Näin ollen esim. yhden gigahertsin prosessori suorittaisi miljardi ohjelmariviä sekunnissa. Käytännössä kuitenkin yhden käskyn suorittamiseen menee useita eri vaiheita, jotka yleensä ovat: nouto, purku, suoritus ja kirjoitus.

Noutovaiheessa prosessori tarkistaa ohjelmalaskurista suorittavan käskyn muistipaikan numeron ja hakee sen sisällön suoritukseen.

Purku-vaiheessa prosessori tulkitsee käskystä mitä sen pitäisi tehdä. Käskyn suoritukseen tarvittavat numerot eli operandit haetaan muistista ja/tai akusta.

Suoritusvaiheessa prosessori lähettää operandit oikeisiin väyliin, jotta käskyn tarkoittamat toimenpiteen tulisi suoritettua. Esim. ”ADD”-käskyn tapauksessa operandit ohjataan summaimen sisältävään väylään.

Kirjoitusvaiheessa saadut tulokset lähetetään takaisin muistiin eli ohjataan esim. akkuun tai johonkin muistipaikkaan johtavaan väylään. Tässä kohden myös ohjelmalaskurin arvoa kasvatetaan yhdellä, jolloin seuraavalla kellopulssilla suoritukseen tulee järjestyksessä seuraava ohjelmarivi.

Bugit

Tietokoneen tuottaman lämmön houkuttelemana 9. Syyskuuta 1945 pieni koiperhonen lensi Harvardin yliopistossa testauksessa olleen Mark II -tietokoneen sisään ja aiheutti oikosulun ja näin tietokoneen toimintavirheen. Tietokoneen ylläpitäjät löysivät tämän ötökän ja teippasivat sen raporttiinsa. Tästä sai alkunsa termi bugi, jolla tarkoitetaan tietokoneen toimintavirhettä, englannin kielen ötökkää tarkoittavan sanan ”bug” mukaan.

Maailman ensimmäinen tietokonebugi.Maailman ensimmäinen tietokonebugi.

Vaikka ensimmäinen bugi olikin oli ihan oikea (perhosen aiheuttama) laitevika, niin nykyään tietokoneet ovat laitteistojensa osalta erittäin toimintavarmoja ja luotettavia. Sen sijaan toimintavirheet ovat ohjelman tehneen ihmisen syytä. Tietokone ei suorita ohjelmaa väärin, vaan sen tehnyt ihminen on laatinut ohjelman niin, että se ei tee haluttua asiaa.

Käytännön ongelmat

Jos hajasaantikoneen ohjelmoiminen oli hankalaa, niin siihen perustuvan fyysisen tietokoneen ohjelmoiminen on vieläkin hankalampaa. Tutut kymmenjärjestelmän luvut vaihtuivat binäärijärjestelmän luvuiksi ja mikä pahinta selkokieliset käskyt myös sarjaksi ykkösiä ja nollia.

Tämän seurauksena vähänkään monimutkaisemman ohjelman tekeminen ei ole enää inhimillinen urakka. On tehtävä jotain asioiden helpottamiseksi. Ratkaisuna on ottaa ihmisläheisempi eli abstraktimpi näkökulma koneen ohjelmointiin. Tästä puhumme seuraavassa osassa eli katsomme kuinka oikeita ohjelmia tehdään.

Lähetäthän kaikki tästä artikkelista löytämäsi virheet osoitteeseen markus.ilmola@pp.inet.fi, niin korjaan ne mahdollisimman pian. Kaikki muukin palaute on tervetulletta.