4 Ohjelmointi konekielell TTK91 ja Titokone 4 1




























![I For-lause for (int i=20; i < 50; ++i) T[i] = 0; DC 0 I For-lause for (int i=20; i < 50; ++i) T[i] = 0; DC 0](https://slidetodoc.com/presentation_image_h2/46900bb5b9b458cad5d2ba678e463436/image-29.jpg)






![for (int i=20; i < 50; ++i) T[i] = 0; Optimointia: for-silmukka I DC for (int i=20; i < 50; ++i) T[i] = 0; Optimointia: for-silmukka I DC](https://slidetodoc.com/presentation_image_h2/46900bb5b9b458cad5d2ba678e463436/image-36.jpg)





![Taulukon indeksitarkistus for (int i=20; i < 50; ++i) T[i] = 0; Optimoiva kääntäjä Taulukon indeksitarkistus for (int i=20; i < 50; ++i) T[i] = 0; Optimoiva kääntäjä](https://slidetodoc.com/presentation_image_h2/46900bb5b9b458cad5d2ba678e463436/image-42.jpg)



![LOAD R 1, 100: 510 R 1<= MEM[100] = 510 R 2= 0 ADD LOAD R 1, 100: 510 R 1<= MEM[100] = 510 R 2= 0 ADD](https://slidetodoc.com/presentation_image_h2/46900bb5b9b458cad5d2ba678e463436/image-46.jpg)




- Slides: 50
4. Ohjelmointi konekielellä (TTK-91 ja Titokone) 4. 1 Tiedon sijainti ja viittaaminen suoritusaikana n n muuttujat, tietorakenteet, symbolit, muistitilan käyttö 4. 2 Ohjelmoinnin peruskäsitteiden toteutus konekielessä n ohjelman kontrolli 4. 3 Koodin optimointi ja tarkistukset 5/22/2021 Liisa Marttinen kevät 2005 1
4. 1 Tiedon sijainti ja viittaaminen suoritusaikana n Suoritusaikana tiedon on sijaittava joko keskusmuistissa tai rekisterissä n n muisti n n n iso (256 MB -1 GB 32 bitin sanaa), mutta suhteellisen hidas (hakuaika 10 ns) ei oikeastaan kovin hidas, mutta prosessori on niin paljon nopeampi rekisteri n n levy yms on aivan liian hidas! nopea (1 ns), mutta pieni (256 32 bitin sanaa) välimuisti (prosessorin sisällä oleva 1. tason välimuisti) n lähes yhtä nopea kuin rekisteri (1 -2 ns), kooltaan suurempi (864 KB) 5/22/2021 Liisa Marttinen kevät 2005 2
Miten tietoon viitataan ? n Tieto on muistissa n n heksadesimaaliluku suoraan muistiosoitteella (0 x. A 49 F 37, 9832456) symbolista konekieltä käytettäessä symbolilla (Taulu, luku, Y) n n n osoite voidaan välittää rekisterissä tai ’epäsuorasti’ jossain muistipaikassa n n symbolin arvo on muistiosoite LOAD R 1, Taulu ADD R 2, @-3(FP), LOAD R 3, @osoite suoritusaikana laskettavan osoitteen avulla 5/22/2021 Liisa Marttinen kevät 2005 3
Miten tietoon viitataan? (2) n Tieto välimuistissa n samalla tavalla kuin muistissa olevaan tietoon n ei siis suoraa viittausta välimuistiin mutta tieto saattaakin löytyä nopeammin välimuistista viittaushetkellä ei tiedetä, saadaanko tieto välimuistista vai joudutaanko se hakemaan keskusmuistista 5/22/2021 Liisa Marttinen kevät 2005 4
Miten tietoon viitataan? (3) n Tieto on rekisterissä n n n konekielessä rekisterin osoitteen avulla (3 tai 7) symbolisessa konekielessä rekisterin nimen avulla (R 2, SP, FP) Tieto on konekäskyssä n yleensä konekäskyssä on vain yksi paikka tiedolle 5/22/2021 Liisa Marttinen kevät 2005 5
Tieto ja sen osoite n Muistissa olevaan tietoon liittyy sekä arvo että osoite n osoite = muuttujan sijaintipaikka muistissa osoite = 125 ja arvo =10 n 5/22/2021 LOAD R 1, =10 STORE R 1, 125: Liisa Marttinen kevät 2005 10 6
Symbolit ja muuttujat n Symbolisen konekielen kääntäjä pitää viitteitä ja muuttujia vastaavia tunnuksia symboleina. Symbolin arvoksi tulee n sen käskyn sijaintiosoite, jonka viitteenä se on n n Taas= 1134: ’ADD’ 2 1 1 100 muuttujalle varatun muistipaikan osoite n n n Taas ADD R 2, 100(R 1) Y DC 12 ; Y: lle tilaa yksi muistipaikka ja Y: n arvoksi 12 Taulu DS 100 ; varataan 100 muistipaikkaa symbolit yleensä olemassa vain käännösaikana n virheilmoituksia varten voidaan symbolitaulu tallettaa 5/22/2021 Liisa Marttinen kevät 2005 7
Muuttujien arvot ja osoitteet Ohjelman osoiteavaruus valekäsky DC 0 X DC 200 ohjelman konekielliset käskyt LOAD R 2, =X LOAD R 2, X . . . olkoon ohjelman koko 23 käskyä . …. X 200 23 X: lle varataan tilaa ohjelman käskyjen jälkeen LOAD R 2, =X => R 2 = 23 eli muuttujan X: n osoite = symbolin X arvo LOAD R 2, X => R 2 = 200 eli muuttujan X arvo 5/22/2021 Liisa Marttinen kevät 2005 8
Osoitimuuttujat n Samanlaisia muuttujia kuin muutkin muuttujat n n on osoite ja arvo Arvo on nyt jonkin tiedon osoite muistissa n n globaalin muuttuja, taulukko, tietue, olio dataosoite pinosta tai keosta tiedolle dynaamisesti (suoritusaikana) dataosoite varatun alueen osoite n n Javan ’new’-operaatio palauttaa muistialueen osoitteen (tai virhekoodin, jos varaus ei onnisti) käskyn aliohjelman tai metodin osoite ohjelmakoodiin 5/22/2021 koodiosoite Liisa Marttinen kevät 2005 9
Osoitinmuuttujat Xptr DC 0 tbl DS 4 X DC 200 LOAD R 1, =X STORE R 1, Xptr LOAD R 2, X LOAD R 3, @Xptr Oletus: ohjelman koko on 123 konekäskyä! Muuttujan X osoite on 128. Muuttujan X arvo on 200. Osoitinmuuttujan Xptr osoite on 123. Osoitinmuuttujan Xptr arvo on 128 (eli toisen muuttujan, nyt X: n, osoite). Ohjelman muistiavaruus … 123 1280 124 0 125 0 126 0 127 0 128 200 129 1000 130 4500 … LOAD R 2, X ; R 2<- 200 LOAD R 3, @Xptr ; R 3 <-200 5/22/2021 Liisa Marttinen kevät 2005 10
Yhden ohjelman muistitilan käyttö TTK 91: ssä ohjelmakoodi globaalit muuttujat ja tietorakenteet BASE ohjelman LIMIT P muistitila SP pino aliohjelmien toteuttamista varten sekä tilat paikallisille muuttujille vapaa alue HP Keskusmuisti 5/22/2021 Keko dynaamisesti varattavia muistialueita varten (esim. Java ’new’). TTK 91: ssä ei ole toteutettu kekoa! Liisa Marttinen kevät 2005 11
Globaali data TTK-91: ssä n n n Globaaleille muuttujille ja muille globaaleille tietorakenteille varataan tilaa heti ohjelman käskyjen jälkeen muuttujat int K=1; boolean B; tilan varaus int Tau[8] ; char C short X; char mjono[] =’TTK-91’ K DC 1 ; alkuarvo 1 Tau DS 8 ; 8 sanaa B n viittaaminen 5/22/2021 DC 0 ; 1=true, 0 = false Alku LOAD R 1, K STORE R 2, TAU(R 1) Liisa Marttinen kevät 2005 12
0 Ohjelman osoiteavaruuden käyttö aliohjelmaa Alioh 1 suoritettaessa: Paaohj. . . Alioh 1. . . Alioh 2. . . Pääohjelman ja aliohjelmien koodit . . . . Aliohn. . . 214 316 516 Apu, Bee, K X, Y, P 1, P 2 Aliohjelman omat paikalliset muuttujat X ja Y sekä parametrit P 1 ja P 2 vapaa muistitila SP 20999 HP globaalit, kaikkialle näkyvät muuttujat Bee ja K sekä taulukko Apu Isotaulu Aliohjelman suoritusaikana varaama suuri taulukko Isotaulu[0: 9999]. Käytössä myös aliohjelman suorituksen jälkeen, kunnes erikseen vapautetaan (’free’). (Ei ole toteutettu TTK-91: een!) 21999 5/22/2021 Liisa Marttinen kevät 2005 13
Datan tilavaraukset muistista n Globaalille datalle n n n varataan ohjelman latauksen yhteydessä kaikkialla viitattavissa nimen (osoitteen) avulla Dynaamiselle datalle n int I; function Check(); Struct n = new Struct(); varataan keosta suorituksen aikana vapautetaan kun ei enää tarviat viittaus varauksen jälkeen osoitteen avulla Aliohjelmien paikalliselle datalle n n n parametrit, paikalliset muuttujat varataan pinosta kutsuhetkellä vapautetaan aliohjelmasta poistuttaessa viittaus aliohjelman sisällä suhteellisen osoitteen avulla 5/22/2021 Liisa Marttinen kevät 2005 14
Tiedon sijainti suoritusaikana n Rekisterissä (nopein) n n n kääntäjä päättää milloin ja minkä muuttujien arvot pidetään rekisterissä konekäskyssä oleva tieto on myös (käsky) rekisterissä Välimuistissa (nopea) n n laitteisto hoitaa automaattisesti jollekin muistialueelle käyttäjä ei tiedä, milloin on muistissa, milloin välimuistissa (muistista haku on paljon hitaampaa!) 5/22/2021 Liisa Marttinen kevät 2005 15
Tiedon sijainti suoritusaikana n Muistissa (hidas) n kääntäjä valitsee sijaintipaikan n n globaali datasegmenttiin, joka varataan ja alustetaan ohjelman latauksen yhteydessä pienet vakiot voidaan sijoittaa konekäskyjen vakio-osaan koodisegmentissä ohjelma sijoittaa suoritusaikana n aliohjelmien paikalliset muuttujat, parametrit ohjelmointikielen tai käyttöjärjestelmän palveluohjelma sijoittaa suoritusaikana n n (jatkuu) dynaaminen data keossa Levy, levypalvelin (liian hidas ohjelman suoritukseen) n vaatii käyttöjärjestelmän varausohjelmien apua 5/22/2021 Liisa Marttinen kevät 2005 16
4. 2. Ohjelmoinnin peruskäsitteiden toteutus konekielellä n Aritmeettinen lause n miten toteutetaan laskutoimitukset n Yksinkertaiset tietorakenteet n yksiulotteiset taulukot, tietueet Ohjelman kontrolli – mikä käsky seuraavaksi n n n valinta: if – then – else, case toisto: for-silmukka, while-silmukka aliohjelmat, virhetilanteet Monimutkaiset tietorakenteet n n 5/22/2021 listat, moniulotteiset taulukot pinot, keot Liisa Marttinen kevät 2005 17
n Lasketaan muistipaikkojen 100 ja 101 sisältö yhteen, jaetaan summa muistipaikan 102 sisällöllä ja viedään tulos muistipaikkaan 100. LOAD ADD DIV STORE 5/22/2021 R 1, 100 R 1, 101 R 1, 102 R 1, 100 R 1 <- MEM[100] R 1 <- R 1 + MEM[101] R 1<- R 1/MEM[102] MEM[100] <- R 1 Liisa Marttinen kevät 2005 18
Aritmeettinen lause tilan varaus int a, b, c=5; . . . A B C DC DC DC 0 0 5 koodi: b=46; . . a=5*b + c; . . 5/22/2021 LOAD STORE. . . LOAD MUL LOAD ADD STORE R 1, =46 R 1, B R 1, =5 R 2, C R 1, R 2 R 1 Liisa Marttinen kevät 2005 tai LOAD R 1, =5 MUL R 1, B ADD R 1, C STORE R 1, A 19
Globaalin taulukon tilan varaus ja käyttö I DC 0 int i, X; X DC 0 int Table[20]; Table DS 20 . . . …. i=10; LOAD R 1, =10 X =Table[i]; STORE R 1, I LOAD R 2, Table(R 1) I STORE R 2, X X Table Optimoiva kääntäjä osaisi jättää pois tämän ”LOAD R 1, X” –käskyn! 5/22/2021 Liisa Marttinen kevät 2005 20
Kontrolli - valinta konekielellä n Ehdoton hyppy n n JUMP, CALL ja EXIT, SVC ja IRET Hyppy laiterekisterin arvon perusteella (verrattuna nollaan) n JZER, JPOS, . . . n Hyppy tilarekisterin arvon perusteella n n n COMP R 2, RAJA JEQU POIS COMP JEQU, JGRE, … Ongelma vai etu: ttk-91: ssä kaikki ALU käskyt asettavat tilarekisterin n ADD, SUB, MUL, DIV, NOT, AND, OR, XOR, SHL, SHR 5/22/2021 Liisa Marttinen kevät 2005 21
If-then-else -valinta ? 5/22/2021 if (a<b) x = 5; else x = y; LOAD COMP JNLE LOAD STORE JUMP Else LOAD STORE Done NOP Liisa Marttinen kevät 2005 R 1, A R 1, B Else R 1, =5 R 1, X Done R 1, Y R 1, X ? 22
Kirjoita konekielinen ohjelma, joka lukee näppäimistöltä luvun muuttujaan a ja tallettaa muistipaikkaan b luvun 1, jos luettu luku on suurempi kuin 5. Muuten b: n arvoksi tulee 2. a b if else ohi DS 0 …. IN STORE COMP JNGRE LOAD STORE JUMP LOAD STORE …. . varataan tilat muistipaikoille R 1, =KBD R 1, a R 1, =5 if ( a == 5 ) else a!=5, niin else-haaraan R 2, =1 b=1 R 2, b ohi R 2, =2 b=2 R 2, b 23
LOAD R 1, Lkm Case-lause Vrt 4 COMP R 1, =4 JNEQ Vrt 0 LOAD R 2, =11 STORE R 2, X JUMP Cont Vrt 0 COMP R 1, =0 JNEQ Def JUMP Cont Def LOAD R 2, =0 STORE R 2, X Cont NOP Switch (lkm) { case 4: x = 11; break; case 0: break; default: x = 0; break; } Onko järjestyksellä väliä? 5/22/2021 Liisa Marttinen kevät 2005 24
Toistolauseet n n n For-step-until -silmukka Do-while -silmukka While-do –silmukka …. 5/22/2021 Liisa Marttinen kevät 2005 25
Millä a: n arvoilla vähennys tehdään? Esim. alkuehtoinen toisto lue a; while (a >0) {a = a-1; } ? Esim. loppuehtoinen toisto lue a; do ? {a= a-1; } until (a < 0) 5/22/2021 Liisa Marttinen kevät 2005 ehto silmukan alussa ehto silmukan lopussa 26
Alkuehtoinen toisto konekielellä IN R 1, =KBD while COMP R 1, =0 JNGRE R 1, endwhile SUB R 1, =1 OUT R 1, =CRT JUMP while endwhile …. Mitä ohjelma tulostaa, kun sille syötetään luku 10? 27
Loppuehtoinen toisto konekielellä IN do SUB OUT JPOS SVC R 1, =KBD R 1, =1 R 1, =CRT R 1, do SP, =HALT Mitä ohjelma tulostaa, kun sille syötetään luku 10? 28
I For-lause for (int i=20; i < 50; ++i) T[i] = 0; DC 0 … LOAD R 1, =20 STORE R 1, I Loop LOAD R 2, =0 LOAD R 1, I STORE R 2, T(R 1) LOAD R 1, I ADD R 1, =1 STORE R 1, I Voiko koodia optimoida? LOAD R 3, I COMP R 3, =50 JLES Loop 5/22/2021 Liisa Marttinen kevät 2005 29
Nollataan peräkkäiset muistipaikat. Ensimmäisen muistipaikan osoite on R 2: ssa ja viimeisen R 3: ssa LOAD Loop STORE ADD COMP JNGRE 5/22/2021 R 1, =0 R<- 0 R 1, 0(R 2) MEM[R 2] <-0 R 2, =1 seurava paikka R 2, R 3 joko mentiin yli? Loop jos ei, niin jatketaan Liisa Marttinen kevät 2005 30
While-do -lause X = 12345; Xlog = 1; Y = 10; while (Y < X) { Xlog++; Y = 10*Y } 5/22/2021 LOAD R 1, =12345 STORE R 1, X LOAD R 3, =1 ; R 3=Xlog LOAD R 2, =10 ; R 2=Y While COMP R 2, R 1 JNLES Done ADD R 3, =1 MUL R 2, =10 JUMP While Done STORE R 3, Xlog ; talleta tulos STORE R 2, Y Liisa Marttinen kevät 2005 31
Summan laskeminen: n Lasketaan muistipaikoissa 100 -200 olevien lukujen summa rekisteriin R 1. LOAD R 2, =100 LOAD R 1, =0 Summaa ADD R 1, 0(R 2) ADD R 2, =1 COMP R 2, =201 JLES Summaa SVC SP, =HALT 24/05/2005 MEM[0+R 2] 32
Lasketaan muistipaikoissa 100 -200 olevien lukujen summa rekisteriin R 1 lähtien lopusta. LOAD R 2, =100 indeksirekisteri LOAD R 1, =0 lukujen summa Alku JNEG R 2, Loppu kaikki laskettu? ADD R 1, 100(R 2) summataan SUB R 2, =1 seuraava muistipaikka JUMP Alku laskemaan lisää Loppu SVC SP, =HALT lopetetaan 24/05/2005 33
Lasketaan muistipaikoissa 100 -200 olevien lukujen summa rekisteriin R 1 lähtien lopusta . Alku LOAD R 2, =100 indeksirekisteri LOAD R 1, =0 lukujen summa ADD R 1, 100(R 2) summataan SUB R 2, =1 seuraava muistipaikka JNNEG R 2, Alku laskemaan lisää SVC SP, =HALT lopetetaan 34
Koodin generointi n Kääntäjän viimeinen työvaihe n n n voi olla jopa puolet kääntäjän työstä tuottaa alustukset, konekieliset lauseet, kontrollirakenteet Koodin optimointi n n n käännös paljon hitaampaa suoritus paljon nopeampaa milloin muuttujan arvo rekisterissä, milloin muistissa ja jos rekisterissä, niin missä rekisterissä? 5/22/2021 Liisa Marttinen kevät 2005 35
for (int i=20; i < 50; ++i) T[i] = 0; Optimointia: for-silmukka I DC 0 … LOAD R 1, =20 STORE R 1, I Loop LOAD R 2, =0 LOAD R 1, I STORE R 2, T(R 1) LOAD R 1, I ADD R 1, =1 STORE R 1, I LOAD R 3, I COMP R 3, =50 JLES Loop 5/22/2021 I DC 0 … LOAD R 1, =20 LOAD R 2, =0 Loop STORE R 2, T(R 1) ADD COMP JLES Liisa Marttinen kevät 2005 R 1, =1 R 1, =50 Loop 36
Monimutkaisemman summan laskeminen n n Lasketaan lukujen 1, …, 20 20 2 neliöiden summa eli Si=1 i Javalla tämä käy seuraavasti: s=0; for (i = 1; i < 21; i++) s= s + i*i; 37
n Konekielellä kääntäjän tyyliin: s DC 0 i DC 1 Taas LOAD R 1, i ; luvut väliltä [1, 20] MUL R 1, R 1 ; luvun neliö ADD R 1, s ; lisätään summaa STORE R 1, s ; summa talteen LOAD R 1, i ; luvun ADD R 1, =1 ; kasvatus yhdellä STORE R 1, i ; luku talteen COMP R 1, =21 ; joko luku 21? JLES Taas ; jos ei vielä SVC SP, =HALT 38
n Konekielellä (fiksun) opiskelijan tyyliin: n käytetään rekistereitä LOAD R 1, =20 ; luku i LOAD R 2, =0 ; summalaskuri s Taas LOAD R 3, R 1 ; lasketaan luvun i MUL R 3, R 3 ; neliö i 2 ADD R 2, R 3 ; lisätään se summaan SUB R 1, =1 ; i =i-1 JPOS R 1, Taas ; i > 0 ? SVC SP, =HALt 39
Virhetilanteisiin varautuminen n Prosessori tarkistaa käskyn suoritusaikana automaattisesti n nollalla jaon (divide by xero) luvun ylivuodon (interger overflow) Muita tarkistuksia varten on generoitava konekielisiä käskyjä, jotka virhetilanteen havaitessaan aiheuttavat keskeytyksen tai käyttöjärjestelmän palvelupyynnön n liian suuri tai liian pieni taulukon indeksi virheellinen metodi tai virheellinen operandi tai mitä tahansa haluaakin testata 5/22/2021 Liisa Marttinen kevät 2005 40
Taulukon indeksitarkistus Tkoko Taulu EQU 100 DS Tkoko COMP R 1, Tkoko ; indeksin tarkistus JLES Goodind ; indeksi kunnossa SVC SP, =Badind ; KJ hoitaa virhetilanteen Goodind LOAD R 2, Taulu(R 1) ; nyt voidaan lukea 5/22/2021 Liisa Marttinen kevät 2005 41
Taulukon indeksitarkistus for (int i=20; i < 50; ++i) T[i] = 0; Optimoiva kääntäjä osaa yhdistää silmukan ehdon ja indeksitarkistuksen! 5/22/2021 I DC 0 … LOAD R 1, =20 STORE R 1, I Loop LOAD R 2, =0 LOAD R 1, I JNNEG R 1, ok 1 SVC SP, =Badind ok 1 COMP R 1, Tkoko JLES ok 2 SVC SP, = Badind ok 2 STORE R 2, T(R 1) LOAD R 1, I ADD R 1, =1 STORE R 1, I LOAD R 3, I COMP R 3, =50 JLES Loop Liisa Marttinen kevät 2005 42
Linkitetty lista DATA 1 DATA 2 DATA 3 L P Lista on tietorakenne, johon voidaan tallettaa tietoa. Koostuu solmuista, joissa tietoa ja viite seuraavaan solmuun. Viite solmuun on solmun ensimmäisen muistipaikan osoite 43
Lista muistiin talletettuna 100: P = 100 510 …. 510: data 1 625 510 data 1 511 625 …. 625: data 2 727 625 data 2 626 727 …. 727: data 3 -1 727 data 3 728 -1 …. 44
n Listan alkioiden summan laskeminen Käytetään epäsuoraa osoitusta summa DC 0 Sum LOAD R 1, 100 ; listan alku JNEG R 1, Loppu ; tyhjä lista? LOAD R 2, =0 ; summalaskurin nollaus Loop ADD R 2, @R 1 ; data ADD R 1, =1 ; seuraava muistipaikka LOAD R 1, @R 1 ; seuraavan osoite JNNEG R 1, Loop Loppu STORE R 2, summa ; summa talteen SVC SP, =HALT 45
LOAD R 1, 100: 510 R 1<= MEM[100] = 510 R 2= 0 ADD R 2, @R 1 510: R 2<= R 2 + MEM[R 1] = 0 + MEM[510] = 0 + 10 = 10 511: 10 ADD R 1, =1 625 R 1 <= R 1 +1 = 511 46
n LOAD R 1, @R 1 510: 10 511: 625 Loop ADD R 2, @R 1 625: 20 R 1 = 511 R 1 <= MEM[511] = 625 R 2<= R 2 + MEM[R 1] = 10 + MEM[625] = 10 + 20 =30 626 727 47
n ADD R 1, =1 625: R 1 = 625 R 1 <= R 1+1 = 626: 20 727 LOAD R 1, @R 1 Loop ADD R 2, @R 1 727: 30 728: R 1<= MEM[R 1] = MEM[626] = 727 R 2 <= R 2 + MEM[R 1] = 30 + MEM[727] = 30 +30 = 60 -1 48
n ADD R 1, =1 727: 30 R 1 = 727 R 1 <= R 1+1 = 728 -1 LOAD R 1, @R 1 JNNEG R 1 Loop Loppu STORE R 2, summa SVC SP, =HALT R 1<= MEM[R 1] = MEM[728] = -1 Summa: 60 49
Monimutkaiset tietorakenteet n 2 -ulotteinen taulukko Opisk, jonka jokainen alkio on tietue, jossa on kentät n n n kurssin lopullinen arvosana n n opiskelijan nimi opiskelijatunnus kurssin 6 harjoituskerralla tehdyt tehtävät kurssin 3 kokeesta saadut pistemäärät kurssin suorituspäivä Miten tämä pitäisi tallettaa? Miten tietoihin viitataan? Mitä tarkistuksia pitäisi tehdä? 5/22/2021 Liisa Marttinen kevät 2005 50


