Luku 3

Taulukot, tietueet ja muu rakenteinen tieto

Rakenteisen tieto talletetaan yleensä yhtenäiselle muistialueelle peräkkäisiin muistipaikkoihin, mutta tiedon tallennusjärjestys voi vaihdella.

1-ulotteiset taulukot ja tietueet

1-ulotteiset taulukot talletetaan yleensä aina peräkkäisiin muistipaikkoihin ja taulukon osoite on sen ensimmäisen alkion osoite. Tietokonejärjestelmissä ensimmäinen indeksi on yleensä nolla (0), koska tällä tavoin taulukon T alkion T[i] osoite on T+i. Indeksoitu tiedonosoitusmoodi tukee tehokkaasti 1-ulotteisiin taulukoihin viittaamista. Yleensä taulukon alkuosoite annetaan vakiona konekäskyssä ja taulukon indeksi on samassa konekäskyssä olevan indeksirekisterin arvo.

load  r1, Tbl(r2)     ; hae rekisteriin r1 taulukon Tbl alkion Tbl[r2] arvo

Tiedon suojauksen kannalta olisi tärkeää, että em. esimerkissä rekisterin r2 arvo tarkistetaan ennen taulukkoviittauksen tekemistä. Se ei saa olla negatiivinen eikä liian suuri. Usein näihin tarkistuksiin menee enemmän koodia kuin itse tietoon viittaamiseen, mutta tarkistukset ovat tärkeä osa tiedon suojaamisessa koodausvirheiden ja tietosuojahyökkäysten varalta.

Tbl      DS  300      ; varaa tilaa 300 sanaa taulukolle Tbl
TblSize  EQU 300      ; symbolin TblSize arvona on taulukon Tbl koko
...
                      ; tarkista indeksi r2:ssa
jneg  r2, HandleBadIndex  ; onko r2 negatiivinen?
comp  r2, =TblSize        ; onko r2 liian iso?
jnles HandleBadIndex      ; hyppää, jos arvo ei ole pienempi kuin TblSize.

load  r1, Tbl(r2)     ; hae rekisteriin r1 taulukon Tbl alkion Tbl[r2] arvo

Tietueet on talletettu samalla tavalla yhtenäiselle muistialueelle, jossa tietueen eri kentät ovat peräkkäisissä muistipaikoissa. Myös tietueen osoite on sen ensimmäisen kentän osoite. Indeksoitu tiedonosoitusmoodi tukee tehokkaasti myös tietueisiin viittaamista, vaikkakin nyt vähän eri tavalla. Taulukkojen osoite annetaan käskyn vakiokentässä, kun tietueen osoite annetaan indeksirekisterissä. Tietueen kentän sijainti tietueen sisällä annetaan nyt konekäskyn vakiokentässä. On erittäin kätevää, että yhtä ja samaa tiedonosoitusmoodia voidaan käyttää yleisimpiin rakenteisiin tietotyyppeihin viitattaessa.

Id      equ 0
Age     equ 1
Nr      equ 2

load  r1, Nr(r2)    ; hae rekisteriin r1 rekisterin r2 osoittaman tietueen
                    ; kentän Nr arvo

2-ulotteiset taulukot

2-ulotteiset taulukot (matriisit) ovat jo hankalia käyttää. Ne talletetaan peräisrakenteina, riveittäin tai sarakettain. Välimuistin toiminnan kannalta olisi tehokkaampaa, jos ne talletettaisiin samassa järjestyksessä kuin mitä alkiota yleensä käytetään. Valitettavasti vain useimmissa tapauksissa matriiseihin tulee viittauksia sekä rivi- että sarakejärjestyksessä. Esimerkiksi matriisitulon laskennan yhteydessä ensimmäistä matriisia käydään läpi riveittäin ja toista sarakettain.

Matriisin osoite on kuitenkin aina sen ensimmäisen muistiin talletetun alkion osoite. Jos esimerkiksi 3 rivin ja 4 sarakkeen matriisi M[3, 4]

 1  2  3  4
 5  6  7  8
 9 10 11 12

talletetaan muistiin riveittäin osoitteeseen 876, niin muistissa on muistipaikasta 876 alkaen arvot

 876: 1  2  3  4  5  6  7  8  9 10 11 12

Koska yhden rivin pituus on 4 alkiota, niin alkion M[i,j] osoite on 876+4*i+j. Ennen haluttua alkiota M[i,j] pitää sivuuttaa i kokonaista riviä ja j alkiota halutulla rivillä. Useimmissa suorittimissa ei ole valmista tiedonosoitusmoodia tämän laskemiseksi. Tällöin viitatun alkion osoitteen laskeminen pitää ensin toteuttaa usealla konekäskyllä ja sitten vasta tehdä varsinainen muistiviite tuohon alkioon. Esimerkiksi, alkion M[i,j] lukeminen rekisteriin r2 tapahtuu konekäskyillä

  load r1, i        ; laske alkion M[i,j] suhteellinen osoite matriisissa M
  mul  r1, =4
  add  r1, j
  load  r2, M(r1)   ; hae alkion M[i,j] arvo rekisteriin r2

Jos taas matriisi M olisi talletettu sarakettain osoitteeseen 654, niin muistissa olisi muistipaikasta 654 alkaen arvot

 654: 1  5  9  2  6 10  3  7 11  4  8 12

Sarakkeen pituus on 3 riviä, joten alkion M[i,j] lukeminen rekisteriin r2 tapahtuu nyt konekäskyillä

  load r1, j       ; laske alkion M[i,j] suhteellinen osoite matriisissa M
  mul  r1, =3
  add  r1, i       ; suhteellinen osoite on i+3j
  load  r2, M(r1)  ; hae alkion M[i,j] arvo rekisteriin r2

Kumpikin on ihan yhtä kätevää, mutta vähän hidasta koska osoitteen laskeminen täytyy tehdä useamman konekäskyn avulla. Lisäksi em. esimerkeistä puuttuu täysin indeksitarkistukset, jotka lisäävät koodin määrää vielä pikkasen.

3-ulotteiset taulukot ja muu rakenteinen tieto

3-ulotteiset taulukot talletetaan vastaavasti joko "riveittäin" tai "sarakettain" ja niihin viittaaminen tapahtuu samalla tavalla kuin edellä. Ajatellaan esimerkkinä riveittäin talletettua 3-ulotteista taulukkoa T[3,4,5]. Siinä on 3 tasoa (tasot 0, 1, 2), kussakin tasossa 4 riviä (rivit 0, 1, 2, 3) ja kullakin rivillä 5 alkiota (alkiot 0, 1, 2, 3, 4). Kullakin tasolla on siis 4*5=20 alkiota. Alkion T[i,j,k] arvo voidaan lukea (ilman indeksitarkistuksia) rekisteriin r0 käskyillä

  load r1, i     ; laske alkion T[i,j,k] suhteellinen osoite taulukossa T
  mul  r1, =20         ; ohita i tasoa (4*5*i sanaa)
  load r2, j
  mul r2, =5           ; ohita j riviä (5*j sanaa) tällä tasolla
  add r1, r2
  add r1, k            ; ohita k sanaa tällä rivillä
  load  r0, T(r1)  ; hae alkion T[i,j,k] arvo rekisteriin r0

Samalla tavalla toimitaan kaikissa monimutkaisissa tietorakenteissa. Tällaisia ovat esimerkiksi 2-ulotteiset taulukot, joissa kukin alkio on 8-kenttäinen tietue. Toinen esimerkki on 8-ulotteinen taulukko. Niissä kaikissa tietoon viittaaminen tapahtuu kolmessa vaiheessa. Ensin tarkistetaan kaikki viittausparametrien (taulukon indeksit, kenttien indeksit) kelvollisuus, sitten lasketaan viitattavan tiedon osoite ja lopulta tehdään itse viittaus tietoon. Vähän monimutkaista, mutta näin se toimii!

Muut tavat tallettaa rakenteista tietoa

Rakenteisen tiedon voi tallettaa myös linkitettyinä tietorakenteina. Tällöin tietorakenne on talletettu muistiin erillisinä yhtenäisinä muistilohkoina, jotka on linkitetty toisiinsa muistiosoitteiden avulla. Tällöin esimerkiksi riveittäin talletettu 2-ulotteinen taulukko T[5,6] voisi olla talletettu siten, että kukin rivi on oma muistilohkonsa. Osoitteessa T olisikin nyt vain 1-ulotteinen taulukko T, joka sisältää kunkin rivin osoitteen muistissa. Taulukon T rivit voivat nyt sijaita erillisinä alueina muistissa.

  load r1, i       ; rivin i indeksi
  load r2, T(r1)   ; rivin i osoite muistissa
  add  r2, j       ; alkion T[i,j] osoite muistissa
  load  r1, (r2)   ; hae alkion T[i,j] arvo rekisteriin r1

Emme käsittele tällä tavoin talletettuja linkitettyjä tietorakenteita tämän enempää tällä kurssilla.

Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan:

Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!