Seppo Mustonen: Sukrojen ohjelmointi Survossa

9. Aritmetiikka ja muistin välitön hallinta

Sukrokieltä ei ole tarkoitettu, kuten vaikkapa Basic tai C, yleiseksi ohjelmointikieleksi. On silti usein kätevää toimittaa yksinkertaisia laskutoimituksia suoraan sukromuistissa tarvitsematta turvautua Survon varsinaisiin laskentakeinoihin, jotka ovat laajamittaisissa sovelluksissa tehokkaampia. Tietoa on myös, olipa se numeerista tai sanallista, joskus siirrettävä muistipaikasta toiseen ja yhdistettävä toisiin tietoihin. Näitä toimenpiteitä tehdään sukrokielessä seuraavilla käskyillä:

{Wi=Wj} Paikan Wj sisältö kopioidaan paikkaan Wi.
{Wi=Wj+Wk} Yhteenlasku
{Wi=Wj-Wk} Vähennyslasku
{Wi=-Wj} Etumerkinvaihto
{Wi=Wj*Wk} Kertolasku
{Wi=Wj/Wk} Jakolasku
{Wi=Wj%Wk} Jakojäännös kokonaislukujen osamäärässä
{Wi=Wj&Wk} Merkkijonojen asettaminen peräkkäin

Muistipaikkojen asemasta operandeina saa olla myös vakioita eli esim. {W3=W3-2} pienentää paikan W3 sisältöä kahdella. Merkkijonovakioissa ei saa esiintyä merkkejä

    + - * / % & { } @
Esim. {W1=SURVO 84C} ja {W2=      &W2} ovat sallittuja käskyjä. Jälkimmäisessä lisätään W2:n sisältämän merkkijonon eteen 5 välilyöntiä.
     Samaan käskyyn ei voi yhdistää useita laskutoimituksia. Jos esim. pitää laskea paikkojen W1, W2 ja W3 sisältämien lukujen summa paikkaan W4, se tehdään kahdessa vaiheessa näin: {W4=W1+W2}{W4=W4+W3} .

Laskutoimitusten tulokset muunnetaan merkkijonoiksi ja niille käytetään lyhintä mahdollista luvun esitystapaa. Eteen ei siis jätetä mitään välilyöntejä eikä loppuun turhia desimaalinollia.
     Kokonaisluvuilla laskut tapahtuvat koneen long-tyyppisessä kokonaislukuesityksessä. Jos operandina on desimaalilukuja tai tehdään jakolasku, käytetään liukulukulaskentaa double-tyyppisillä luvuilla. Jälkimmäinen on hitaampaa myös sikäli, että Survon toimitin (editor) ei tee liukulukulaskentaa vaan siirtää sen erilliselle ohjelmalle, jonka käynnistys vie oman aikansa. Näin säästetään kallista keskusmuistia noin 10 kilotavua, jonka liukulukualiohjelmat tarvitsisivat pysyvästi. (SURVO 98:n toimitin vastaa itse suoraan myös liukulukulaskennasta.)

Esimerkki 1: Alkuluvut

Sukro ALKUL luettelee alkulukuja (jaottomia kokonaislukuja) toimituskenttään, kunnes se keskeytetään painamalla pistettä. Ohjelma tutkii peräkkäisiä parittomia lukuja jakamalla niitä itseään pienemmillä parittomilla luvuilla. Tällöin se päätyy joko siihen, että jako menee tasan (jakojäännös on 0), jolloin luku ei ole alkuluku tai siihen, ettei jako mene koskaan tasan, jolloin luku on alkuluku. Kunkin luvun kohdalla tekijöiden etsiminen saatetaan lopettaa silloin, kun tekijän neliö ylittää tutkittavan luvun.
     Ohjelma ja sen toiminta näyttää seuraavalta:
  44  1 SURVO 84C EDITOR Fri May 10 17:42:50 1991         C:\SUOPAS\ 120  80 0
   1 *
   2 *TUTSAVE ALKUL
   3 / def Wluku=W1 Wtekijä=W2 Wjakojäännös=W3 Wneliö=W4
   4 *{tempo 1}{R}
   5 *SCRATCH {act}{home}2 3{Wluku=1}
   6 + A: {Wluku=Wluku+2}{Wtekijä=1}
   7 + B: {Wtekijä=Wtekijä+2}{Wjakojäännös=Wluku%Wtekijä}
   8 - if Wjakojäännös = 0 then goto A
   9 *{Wneliö=Wtekijä*Wtekijä}
  10 - if Wneliö < Wluku then goto B
  11 * {write Wluku}{goto A}{end}
  12 *
  13 */ALKUL
  14 *2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
  15 *101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191
  16 *193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283
  17 *293 307 311 313 317 331 337 347 349 353 359_
  18 *

Jos vastaava ohjelma kirjoitetaan Basic-kielellä ja ajetaan Basic-tulkin avulla samassa koneessa, se nopeutuu noin viisinkertaisesti. Sukro-ohjelma häviää nopeudessa näin paljon, koska sillä ei ole käytössään kokonaislukumuuttujia, vaan kaikki laskutoimitukset lähtevät sukromuistin tekstimuodossa olevista tiedoista. Jokaisessa laskutoimituksessa tekstimuodossa olevat luvut muunnetaan ensin kokonaislukuesitykseen ja tuloksena saatu luku palautetaan jälleen tekstimuotoon sekä talletetaan takaisin sukromuistiin.
     Laskutoimitusten hitaudella ei kuitenkaan ole mitään olennaista merkitystä sukrokielen järkevissä sovelluksissa, joissa niiden osuus on häviävän pieni verrattuna suoraan Survolla toteutuviin toimintoihin. Sukrokielen tarjoamaa käyttöympäristöä ei toisaalta ole syytä väheksyä esim. ohjelmoinnin opetuksessa, jolloin myös aritmetiikalle löytyy mielekästä käyttöä.

Esimerkki 2: Kertotaulut

Sukrokielessä ei ole ohjelmakierroksia varten erityistä for- tai muuta vastaavaa rakennetta. Kierrokset on kuitenkin helppo hoitaa ottamalla jokin muistipaikka laskuriksi, tyhjentämällä se ennen kierroksen alkua, kasvattamalla sitä joka kierroksella ja testaamalla if-lauseella, joko tarvittava kierrosmäärä on saavutettu. Näin on mahdollista synnyttää jopa sisäkkäisiä kierroksia.
     Sukro KERTO10 laatii tavanomaisen 10-järjestelmän kertotaulun kaikille kertojille 1,2,3,...,10. Ohjelmassa on kaksi sisäkkäistä kierrosta, ulompi ensimmäiselle tekijälle WM ja sisempi toiselle tekijälle WN .
  16  1 SURVO 84C EDITOR Sat May 11 09:09:58 1991         C:\SUOPAS\ 120  80 0
  20 *
  21 *TUTSAVE KERTO10_
  22 / def WM=W1 WN=W2 WMN=W3
  23 / Tyhjennetään kenttä komentorivin alapuolelta:
  24 *{tempo -1}{init}{line start}{R}SCRATCH {act}{home}
  25 *Kertotaulu:{R}
  26 / Ulompi kierros alkaa:
  27 *{WM=0}
  28 + M: {WM=WM+1}
  29 - if WM > 10 then goto Loppu
  30 / Sisempi kierros alkaa:
  31 *{WN=0}
  32 + N: {WN=WN+1}
  33 - if WN <= 10 then goto MN
  34 / Sisemmän kierroksen lopuksi siirrytään uudelle riville:
  35 *{R}{goto M}
  36 / Lasketaan tekijöiden tulo:
  37 + MN: {WMN=WM*WN}
  38 / Tulon suuruudesta riippuen kirjoitetaan sopiva määrä välilyöntejä,
  39 / jotta luvut tulevat taulukkoon siististi allekkain:
  40 - if WMN >= 10 then goto A1
  41 * {}
  42 + A1:
  43 - if WMN >= 100 then goto A2
  44 * {}
  45 + A2:  {write WMN}{goto N}
  46 + Loppu: {tempo +1}{end}
  47 *

Sukro KERTO10 tuottaa taulukon:
   1  1 SURVO 84C EDITOR Sat May 11 09:11:31 1991         C:\SUOPAS\ 120  80 0
  47 *
  48 */KERTO10
  49 *Kertotaulu:
  50 *   1   2   3   4   5   6   7   8   9  10
  51 *   2   4   6   8  10  12  14  16  18  20
  52 *   3   6   9  12  15  18  21  24  27  30
  53 *   4   8  12  16  20  24  28  32  36  40
  54 *   5  10  15  20  25  30  35  40  45  50
  55 *   6  12  18  24  30  36  42  48  54  60
  56 *   7  14  21  28  35  42  49  56  63  70
  57 *   8  16  24  32  40  48  56  64  72  80
  58 *   9  18  27  36  45  54  63  72  81  90
  59 *  10  20  30  40  50  60  70  80  90 100
  60 *_
  61 *

Sukroa KERTO10 ei ole vaikea yleistää sellaiseksi, joka laskee kertotaulun mille tahansa kantaluvulle k niin, että tauluun tulevat luvut merkitään k-kantaisina. Tässä otetaan avuksi Survon muunnoskäskyt. Esim. kun aktivoidaan 249(10:16)=_ , saadaan 249(10:16)=F9 eli 10-järjestelmän luku 249 on 16-järjestelmässä (heksadesimaalisena) F9. Kun kantaluku on yli 10, tarvitaan lisää numeromerkkejä. Sellaisiksi valitaan A=10, B=11, C=12, ..., F=15 jne. Esim. heksadesimaalinen F9 on 16*F+9=249.
     Sukro KERTO varustettuna parametrilla K laskee K-kantaisen lukujärjestelmän kertotaulun. Laskut tapahtuvat tietenkin kymmenjärjestelmässä, mutta tulokset saatetaan aina lopuksi K-järjestelmään muuntamalla ne nykyisen rivin alapuolella.
  14  1 SURVO 84C EDITOR Sat May 11 09:33:11 1991         C:\SUOPAS\ 120  80 0
  63 *
  64 *TUTSAVE KERTO_
  65 / def Wkanta=W1 WM=W2 WN=W3 WMN=W4 Wneliö=W5
  66 *{tempo -1}{init}{line start}{R}
  67 *SCRATCH {act}{home}Kertotaulu {print Wkanta}-kantaisille luvuille:{R}
  68 *{Wneliö=Wkanta*Wkanta}
  69 *{WM=0}
  70 + M: {WM=WM+1}
  71 - if WM > Wkanta then goto Loppu
  72 *{WN=0}
  73 + N: {WN=WN+1}
  74 - if WN <= Wkanta then goto MN
  75 *{R}
  76 *{goto M}
  77 + MN: {WMN=WM*WN}
  78 - if WMN >= Wkanta then goto A1
  79 * {}
  80 + A1: {}
  81 - if WMN >= Wneliö then goto A2
  82 * {}
  83 + A2:  {ref}{R}{print WMN}(10:{print Wkanta})={act}
  84 *{l} {save word WMN}{home}{erase}{ref}{ref}
  85 *{write WMN}{goto N}
  86 + Loppu: {tempo +1}{end}
  87 *

Esim. heksadesimaalinen kertotaulu syntyy näin:
   1  1 SURVO 84C EDITOR Sat May 11 09:36:46 1991         C:\SUOPAS\ 120  80 0
  87 *
  88 */KERTO 16
  89 *Kertotaulu 16-kantaisille luvuille:
  90 *   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F  10
  91 *   2   4   6   8   A   C   E  10  12  14  16  18  1A  1C  1E  20
  92 *   3   6   9   C   F  12  15  18  1B  1E  21  24  27  2A  2D  30
  93 *   4   8   C  10  14  18  1C  20  24  28  2C  30  34  38  3C  40
  94 *   5   A   F  14  19  1E  23  28  2D  32  37  3C  41  46  4B  50
  95 *   6   C  12  18  1E  24  2A  30  36  3C  42  48  4E  54  5A  60
  96 *   7   E  15  1C  23  2A  31  38  3F  46  4D  54  5B  62  69  70
  97 *   8  10  18  20  28  30  38  40  48  50  58  60  68  70  78  80
  98 *   9  12  1B  24  2D  36  3F  48  51  5A  63  6C  75  7E  87  90
  99 *   A  14  1E  28  32  3C  46  50  5A  64  6E  78  82  8C  96  A0
 100 *   B  16  21  2C  37  42  4D  58  63  6E  79  84  8F  9A  A5  B0
 101 *   C  18  24  30  3C  48  54  60  6C  78  84  90  9C  A8  B4  C0
 102 *   D  1A  27  34  41  4E  5B  68  75  82  8F  9C  A9  B6  C3  D0
 103 *   E  1C  2A  38  46  54  62  70  7E  8C  9A  A8  B6  C4  D2  E0
 104 *   F  1E  2D  3C  4B  5A  69  78  87  96  A5  B4  C3  D2  E1  F0
 105 *  10  20  30  40  50  60  70  80  90  A0  B0  C0  D0  E0  F0 100
 106 *_
 107 *

Sukrojen ohjelmointi Survossa - Seppo Mustonen 1991
  1. Johdanto
  2. Esimerkki
  3. Sukrokielen koodisanoja
  4. Sukromuisti
  5. Hapuilukoodit, tulostus ja kohdistimen liikuttelu
  6. Sukrojen aloittaminen ja kytkeminen toisiinsa
  7. Ehdolliset toiminnat
  8. Käyttäjän vuorovaikutus
  9. Aritmetiikka ja muistin välitön hallinta
  10. Sukrotiedostot
  11. Sukrojen lajit
  12. Sukrojen laatiminen käytännössä
  13. Virhetilanteet
  14. Näytesovelluksia
Liite: Sukrokielen koodisanat