Konekielinen ohjelmointi



Samankaltaiset tiedostot
Ohjelmointikielten periaatteet Syksy Antti-Juhani Kaijanaho

LOAD R1, =2 Sijoitetaan rekisteriin R1 arvo 2. LOAD R1, 100

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

4. Lausekielinen ohjelmointi 4.1

Laitteistonläheinen ohjelmointi

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

Johdanto. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 8. syyskuuta 2009 TIETOTEKNIIKAN LAITOS. Johdanto. Luennoija.

Ongelma(t): Miten mikro-ohjelmoitavaa tietokonetta voisi ohjelmoida kirjoittamatta binääristä (mikro)koodia? Voisiko samalla algoritmin esitystavalla

Luento 1 Tietokonejärjestelmän rakenne

Luento 1 Tietokonejärjestelmän rakenne. Järjestelmän eri tasot Laitteiston nopeus

Luento 1 Tietokonejärjestelmän rakenne

Luento 1 Tietokonejärjestelmän rakenne. Järjestelmän eri tasot Laitteiston nopeus

Laitteistonläheinen ohjelmointi

Tiedon esitysmuodot. Luento 6 (verkkoluento 6) Lukujärjestelmät Kokonaisluvut, liukuluvut Merkit, merkkijonot Äänet, kuvat, muu tieto

Ohjelmointikielten periaatteet Syksy Antti-Juhani Kaijanaho

Luento 1 (verkkoluento 1) Ohjelman sijainti Ohjelman esitysmuoto Laitteiston nopeus

Ohjelmointikielten periaatteet Syksy Antti-Juhani Kaijanaho

2 Konekieli, aliohjelmat, keskeytykset

Harjoitustyö: virtuaalikone

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Luento 3 (verkkoluento 3) Ttk-91 konekielinen ohjelmointi. Ohjelman esitysmuoto Konekielinen ohjelmointi ttk-91:llä (Titokone, TitoTrainer)

Intel Pentium Pro -prosessori. tietokonearkkitehtuurit, syksy -96 Ari Rantanen

Luento 1 (verkkoluento 1) Tietokonejärjestelmä

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Paavo Räisänen. Ohjelmoijan binaarialgebra ja heksaluvut.

Kertausluento luennoista 1-3 1

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Johdatus Ohjelmointiin

Ongelma(t): Miten tietokoneen komponentteja voi ohjata siten, että ne tekevät yhdessä jotakin järkevää? Voiko tietokonetta ohjata (ohjelmoida) siten,

Java-kielen perusteet

Tieto ja sen osoite (3) Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Osoitinmuuttujat. Tieto ja sen osoite (5)

Teemun juustokakku Rekisterien, välimuistin, muistin, levymuistin ja magneettinauhan nopeudet suhteutettuna juuston hakuaikaan juustokakkua tehdessä?

etunimi, sukunimi ja opiskelijanumero ja näillä

Java-kielen perusteet

13. Loogiset operaatiot 13.1

Tietokoneen rakenne: Harjoitustyö. Motorola MC prosessori

Kertausluento 1 (lu01, lu02, lu03) Tietokonejärjestelmän rakenne ttk-91 ja sillä ohjelmointi

Tietokoneen toiminta, Kevät Copyright Teemu Kerola Järjestelmän eri tasot Laitteiston nopeus

13. Loogiset operaatiot 13.1

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. FT Ari Viinikainen

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

11/20: Konepelti auki


815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

ITKP102 Ohjelmointi 1 (6 op)

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

TIES325 Tietokonejärjestelmä. Jani Kurhinen Jyväskylän yliopisto Tietotekniikan laitos

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Tietokoneen toiminta (Computer Organization I)

811120P Diskreetit rakenteet

Käskykannat. Tietokoneen rakenne. Ch [Sta06] Operaatioista Operandeista Osoitustavoista Pentium / PowerPC. Luento 7-1

Ohjelmoijan binaarialgebra ja heksaluvut

TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 27. lokakuuta 2009

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. Operaatioiden suoritusjärjestys

Tietokoneen toiminta (Computer Organization I)

Tietokoneen toiminta (Computer Organization I)

Tietokoneen rakenne Käskysykli CPU suorittaa ohjelmaa konekielinen käsky kerrallaan

Aihepiiri Tietokoneen toiminta (Computer Organization I) Tavoitteet (4) Mitä hyötyä tästä on? (4) Kurssien välisiä riippuvuuksia

Luento 7: Käskykannat Tietokoneen rakenne / 2006 / Teemu Kerola 9/25/2006

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

ANSI/IEEE Std

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

1. luento. Ohjelmointi (C) T0004 Syksy luento. 1. luento. 1. luento. 1. luento. kurssin sisältö ja tavoitteet työmuodot.

Ohjelmointi 1. Kumppanit

Toisessa kyselyssä alueella on 1 ruudussa A ja 3 ruudussa B, joten suosituin ehdokas on B.

VIII. Osa. Liitteet. Liitteet Suoritusjärjestys Varatut sanat Binääri- ja heksamuoto

Tietokonearitmetiikka

4. Lausekielinen ohjelmointi 4.1

Tietokoneen toiminta (Computer Organization I) Mitä hyötyä tästä on? (4) Kurssien välisiä riippuvuuksia. Aihepiiri.

PERL. TIE Principles of Programming Languages. Ryhmä 4: Joonas Lång & Jasmin Laitamäki

Lukujärjestelmät. Digitaalitekniikan matematiikka Luku 9 Sivu 3 (26) Lukujärjestelmät ja lukujen esittäminen Fe

ITKP102 Ohjelmointi 1 (6 op)

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 30. marraskuuta 2015

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Ohjausjärjestelmien jatkokurssi. Visual Basic vinkkejä ohjelmointiin

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Ohjelmoinnin perusteet Y Python

TKT-3201 Tietokonearkkitehtuuri 2

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

Ongelma(t): Miten jollakin korkeamman tason ohjelmointikielellä esitetty algoritmi saadaan suoritettua mikro-ohjelmoitavalla tietokoneella ja siinä

Monipuolinen esimerkki

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

Ohjelmoinnin perusteet Y Python

Miksi konekieltä? Jakso 2 TTK-91-tietokone ja sen KOKSI-simulaattori. Tietokone TTK-91. Miksi ei oikeaa konekieltä? TTK-91: tietotyypit (2)

5.6. C-kielen perusteet, osa 6/8, Taulukko , pva, kuvat jma

Jakso 2 TTK-91 -tietokone ja sen KOKSI -simulaattori

Jakso 2 TTK-91 -tietokone ja sen KOKSI -simulaattori

Aihepiiri Tietokoneen toiminta (Computer Organization I)

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Miksi konekieltä? Jakso 2 TTK-91-tietokone ja sen KOKSI-simulaattori. Tietokone TTK-91. Miksi ei oikeaa konekieltä? TTK-91: rekisterit

Käyttöjärjestelmän rakenne

Ohjelmoinnin perusteet Y Python

Jakso 2 TTK-91-tietokone ja sen KOKSI-simulaattori

Transkriptio:

Konekielinen ohjelmointi Antti-Juhani Kaijanaho 9. tammikuuta 2007 1 Konekielet Konekielellä tarkoitetaan sitä kieltä, jota tietokone ymmärtää suoraan. Koska kaikki nykytietokoneet perustuvat samaan ideaan siitä, miten tietokone toimii (ns. von Neumannin kone), ovat myös eri koneiden konekielet suurpiirteisesti katsoen samanlaisia. Yhteistä kaikille konekielille on se, että ne eivät ole tekstuaalisia vaan asiat ilmaistaan konekielellä koodaamalla ne jollakin annetulla tavalla tavujonoksi 1, jota sitten koneen prosessori tulkitsee. Yhteistä myös kaikille konekielille on se, että ohjelmat voidaan jäsentää dataksi ja koodiksi, ja koodi voidaan edelleen jäsentää jonoksi käskyjä (engl. instructions), jotka viittaavat dataan ja muualle koodiin. Käskyt puolestaan voidaan luokitella karkeasti seuraavasti: 1. datan siirto 2. kokonaislukuaritmetiikka 3. vertailu 4. ehdolliset hypyt 5. ehdottomat hypyt 6. järjestelmäkutsut 7. sovellusaluekohtaiset käskyt 8. järjestelmäkäskyt Näistä viisi ensimmäistä käskyluokkaa ovat jatkuvassa käytössä kaikissa ohjelmissa. Järjestelmäkutsujakin käytetään kaikissa ohjelmissa, mutta 1 Tavu (engl. byte) ei välttämättä ole kahdeksanbittinen, vaikka nykykoneissa näin onkin. Huolitellussa kielenkäytössä tavu tarkoittaa koneen pienintä osoitettavissa olevaa tietoyksikköä; jos halutaan puhua nimenomaan kahdeksanbittisestä tietoyksiköstä, korrekti termi on oktetti. niiden käyttötaajuus vaihtelee. Järjestelmäkäskyjä eivät tavalliset ohjelmat kykene käyttämään, ne ovat olemassa käyttöjärjestelmien tarpeita varten. Useimmat tietokoneet tarjoavat lisäksi koko joukon erilaisia sovellusaluekohtaisia käskyjä; näistä lähes yleiskäyttöisen aseman on saanut liukulukukäskyt, pöytäkoneissa tavallisia ovat erilaiset reaaliaikagrafiikan piirtämisessä tarvittavat laskentamenetelmät (esimerkiksi SIMD ja MMX). Yleensä konekielissä on jokin varsin yksinkertainen mekanismi, jolla eri käskyt voidaan erottaa toisistaan. Vanhoissa, ns. CISC-malleissa 2 käskyn aloitti yleensä ns. operaatiokoodi (engl. opcode), joka yleensä vei yhden tavun. Operaatiokoodi ilmaisi, mistä käskystä oli kyse sekä mistä löytynyttä dataa käsky käsitteli. Operaatiokoodia seurasi vaihteleva määrä operandeja, jotka tarkensivat datan sijaintia (antaen esimerkiksi kiinteän osoitteen, mistä data löytyy). Uudemmissa RISC-maleissa 3 käskyt ovat yleensä kiinteämittaisia (esimerkiksi neljän tavun mittaisia riippumatta käskystä) sekä sisältävät operaatiokoodin ja yhden tai useamman operandin. Vaikka konekielet ovatkin suurpiirteisesti katsoen samanlaisia, niiden välillä on huomattavia eroja yksityiskohdissa. Pääsääntöisesti vain samanlaiselle koneelle tarkoitettu konekielinen ohjelma toimii toisessa koneessa. Eri prosessorit jaotellaan sen mukaan, toimivatko toiselle kirjoitetut ohjelmat toisessa prosessorissa. Keskeinen käsite on käskykanta-arkkitehtuuri (engl. instruction set ar- 2 Complex Instruction Set Computer; valtaosassa pöytäkoneita käytettävä Intelin 32-bittinen prosessoriarkkitehtuuri IA- 32 (80386, Pentium ym.) kuuluu tähän luokkaan historiansa vuoksi. 3 Reduced/Regular Instruction Set Computer; näitä ovat käytännössä kaikki 1980-luvun loppupuolella tai sitä myöhemmin puhtaalta pöydältä suunnitellut prosessoriarkkitehtuurit; esimerkiksi Sparc, Alpha ja mobiililaitteista usein löytyvä ARM. 1

chitecture), joka määrää, mitä käskyjä prosessori tukee. Tällä hetkellä merkittävät käskykanta-arkkitehtuurit ovat IA-32 Ehkäpä kaikkien aikojen menestynein käskykanta-arkkitehtuuri: Lähes kaikki pöytäkoneet ja kannettavat viimeisen 20 vuoden ajalta perustuivat IA-32:lle. Myös monet vähäistä tai keskinkertaista tehoa vaativat palvelimet käyttävät IA-32:a. Ensimmäinen prosessori, joka tuki tätä käskykantaa, oli Intelin 80386 vuodelta 1985. Myöhemmät prosessorit ovat laajentaneet käskykantaa, mutta sen ydin on edelleen sama, jota 80386 tuki. IA- 32:ta tukevia prosessoreita valmistavat lähinnä Intel ja AMD, mutta on muitakin valmistajia. Kuten tietokonealalla yleensäkin on tapana, markkinajohtaja IA-32 ei ole teknisesti paras markkinoilla olevista vaihtoehdoista. AMD64 AMD:n suunnittelema uusi (2003) käskykanta-arkkitehtuuri, joka on IA-32:n laajennus samassa mielessä kuin IA-32 itse oli aiempien Intel 8086- ja 80286-arkkitehtuurien laajennus. Vaikka AMD64 on varsin nuori, se on jo pitkälti korvannut IA-32:n uusissa laitteistoissa. Kuten IA-32:ta, AMD64:ää tukevia prosessoreita valmistavat sekä AMD (Athlon64 ja Opteron) että Intel (Intel64). PowerPC Applen, IBM:n ja Motorolan yhteishankkeena 1990-luvun alussa lanseeraama käskykanta-arkkitehtuuri, jota käyttävät nykyisin lähinnä uudehkot Macintosh-koneet. ARM ARM on suhteellisen suurta laskentatehoa tarvitsevien sulautettujen järjestelmien (esimerkiksi mobiilipäätelaitteet) ja kämmenmikrojen prosessorien käskykanta-arkkitehtuuri. ARM-yhteensopivia prosessoreita valmistaa moni mikroprosessorivalmistaja. MIPS Merkittävä suurta laskentatehoa vaativien sulautettujen ja mobiilien järjestelmien prosessorien käskykanta-arkkitehtuuri; käytössä myös SGI:n työasemien prosessoreissa. Sparc Suosittu käskykanta-arkkitehtuuri palvelinkäytössä. Alkuperäinen Sparc on 32-bittinen; sen 64-bittinen laajennus on nimeltään UltraSparc. 2 Symboliset konekielet Konekieltä ei juuri koskaan kirjoiteta käsin. Konekieliset ohjelmat syntyvät yleensä varsinaisten ohjelmointikielten kääntäjien vasteena. Toisinaan kuitenkin ohjelmoija haluaa kirjoittaa samalla abstraktiotasolla, jonka konekieli tarjoaa. Tällaisia tilanteita varten jokaiseen konekieleen liittyy symbolinen konekieli (engl. assembly). Se on konekielisen ohjelman tekstuaalinen esitysmuoto, jossa kukin käsky on omalla rivillään, osoitteiden sijasta käytetään symbolisia nimiä ja jossa käskyn toimittama operaatio ja sen operandit on selvästi erotettu toisistaan. Symbolisella konekielellä kirjoitetun ohjelman kääntämiseen varsinaiselle konekielelle tarvitaan oma ohjelmansa (tosin onnistuu se kyllä käsinkin), ns. assembler 4. Lähes kaikilla symbolisilla konekielillä on sama perusrakenne. Kuten edellä jo todettiin, kukin käsky on omalla rivillään. Pystysuunnassa symbolisella konekielellä kirjoitettu ohjelma jakautuu sarakkeisiin, joiden avulla käskyn eri osat jäsentyvät. Tavallisesti käskyn osoitetta edustava symbolinen nimi, ns. label, on ensimmäisessä sarakkeessa. Jos sellaista ei ole, ensimmäinen sarake on tyhjä. Toinen sarake on varattu käskyn muistikkaalle (engl. mnemonic) yleensä kolmikirjaiminen, joskus kaksi- tai nelikirjaiminen tunnus, joka nimeää käskyn. Kolmas, neljäs ja joskus viideskin sarake on käskyn operandien käytössä. Tämän tarkemmin ei symbolisia konekieliä voi kuvata yleisesti, sillä jokaisella symbolisella konekielellä on omat merkintätapansa. Tavallisesti kullakin käskykanta-arkkitehtuurilla on täsmälleen yksi symbolinen konekieli. IA-32 on tästä poikkeus, sillä on nimittäin niitä kaksi: AT&T:n ja Intelin symboliset konekielet. Kuvissa 2, 3 ja 4 on kuvattu yksinkertainen aliohjelma kolmella eri symbolisella konekielellä. Vastaava C-kielinen aliohjelma on kuvassa 1. 3 Abstraktit koneet Abstrakti kone on käskykanta-arkkitehtuuri, jota ei ole tarkoitettu toteutettavaksi suoraan laitteistossa. Jos abstaktilla koneella on ohjelmistototeutus, se on virtuaalikone. 4 Huomaa: assembly on kieli, assembler ohjelma. 2

unsigned long str2ulong(char const * s) { unsigned long rv = 0; for (/**/; *s!= 0; s++) { rv = 10 * rv + (*s - 0 ); } return rv; } Kuva 1: Yksinkertainen aliohjelma C-kielellä.text.p2align 4,,15.globl str2ulong.type str2ulong, @function str2ulong: pushl %ebp xorl %edx, %edx movl %esp, %ebp movl 8(%ebp), %ecx movzbl (%ecx), %eax testb %al, %al je.l8.p2align 4,,15.L6: movsbl %al,%eax incl %ecx leal (%edx,%edx,4), %edx leal -48(%eax,%edx,2), %edx movzbl (%ecx), %eax testb %al, %al jne.l6.l8: popl %ebp movl %edx, %eax ret Kuva 2: Yksinkertainen aliohjelma IA32-arkkitehtuurin symbolisella konekielellä (AT&T).section ".text".align 4.global str2ulong.type str2ulong, #function.proc 016 str2ulong:!#prologue# 0!#PROLOGUE# 1 ldub [%o0], %o4 sll %o4, 24, %g1 cmp %g1, 0 be.ll8 mov 0, %o3 mov %g1, %o4.ll6: add %o0, 1, %o0 ldub [%o0], %g1 sra %o4, 24, %o5 sll %g1, 24, %g1 orcc %g1, 0, %o4 sll %o3, 2, %g1 add %g1, %o3, %g1 add %g1, %g1, %o3 add %o3, %o5, %g1 bne.ll6 add %g1, -48, %o3.ll8: retl mov %o3, %o0 Kuva 3: Yksinkertainen aliohjelma UltraSparc-arkkitehtuurin symbolisella konekielellä.section ".text".align 2.globl str2ulong.type str2ulong,@function str2ulong: mr 11,3 lbz 0,0(11) li 3,0 cmpwi 0,0,0 bclr 12,2.L6: slwi 9,3,3 add 9,9,3 add 9,9,3 addi 9,9,-48 add 3,0,9 lbzu 0,1(11) cmpwi 0,0,0 bc 4,2,.L6 blr Kuva 4: Yksinkertainen aliohjelma PowerPC-arkkitehtuurin symbolisella konekielellä 3

Ohjelmoijan näkemä tietokone on harvoin täsmälleen se, jonka tietokoneen laitteisto toteuttaa. Yleensä ohjelmoija voi luottaa käyttöjärjestelmän palveluihin. Käyttöjärjestelmä siis rakentaa fyysisen tietokoneen päälle eräänlaisen virtuaalisen tietokoneen, siis virtuaalikoneen. Joskus ohjelmoijan kirjoittamaa ohjelmaa suorittaa simulaattori, joka imitoi jotain abstraktia konetta; tällöin ohjelmoijan näkemä kone on tyystin toinen kuin mitä laitteistosta voisi päätellä. Tällainen tilanne on esimerkiksi silloin, kun Java-ohjelmaa ajetaan Javavirtuaalikoneessa. Tämän luvun loppuosa esittelee erään abstraktin koneen, joka on eräänlainen todellisten koneiden idealisaatio, ja se tarjoaa jonkin verran myös käyttöjärjestelmältä odotettavia palveluita. Ideana on, että myöhemmin tässä monisteessa voidaan sitten pohtia kehittyneempien ohjelmointikielten toteutusta tämän abstraktin koneen tarjoamassa viitekehyksessä ilman, että tarvitsee miettiä sellaisia kääntäjätekniikan inhottavuuksia kuten rekisteripaineen hallintaa. 4 Nelikielen idea Nelikieli on erään abstraktin koneen symbolinen konekieli. Ennen kuin voidaan puhua itse kielestä, pitää hahmotella kyseinen abstrakti kone. Olkoon se nimeltään Nelikone. Nelikoneen rakenne on kaksijakoinen: sillä on muisti ja prosessointiyksikkö. Nelikoneen muisti on 2 64 tavun taulukko; tavun koko on tavanomaiset kahdeksan bittiä. Jokaisella muistin tavulla on yksikäsitteinen osoite, joka on 64-bittinen etumerkitön kokonaisluku. Vaikka muisti onkin tavutaulukko, sitä tavallisesti käsitellään kahdeksan tavun eli 64 bitin eli sanan (engl. word) yksiköissä 5. Sana voidaan tilanteesta riippuen tulkita etumerkittömäksi 64- bittiseksi kokonaisluvuksi tai etumerkilliseksi 64- bittiseksi kokonaisluvuksi. Liukulukuja kone ei toistaiseksi tue. Jos sanan tavut ovat x 0,..., x 7, missä x 0 on se tavu, jonka osoite on pienin, ja x 7 on se tavu, jonka osoite on suurin, sana tulkitaan seuraavasti 5 Sanan pituus vaihtelee käskykanta-arkkitehtuurista riippuen; yleensä se on kaksi, neljä tai kahdeksan tavua pitkä. Sitä sanotaan myös konesanaksi (engl. machine word). etumerkittömäksi kokonaisluvuksi Sanan lukuarvo etumerkittömänä kokonaislukuna on 7 256 7 i x i, i=0 toisin sanoen eniten merkitsevä tavu on sanassa ensimmäisenä. Nelikone on siis bigendian; jos vähiten merkitsevä tavu olisi ensimmäisenä, se olisi little-endian. etumerkilliseksi kokonaisluvuksi Kun sana tulkitaan etumerkilliseksi kokonaisluvuksi, on sen etumerkki negatiivinen, jos sanan eniten merkitsevä bitti on 1 ja positiivinen, jos sanan eniten merkitsevä bitti on 0. Jos sanan etumerkki on negatiivinen, sanan itseisarvo saadaan, kun siihen sovelletaan ensin biteittäistä negaatiota, minkä jälkeen se tulkitaan yllä esitetysti etumerkittömäksi kokonaisluvuksi ja tulokseen lisätään 1. Positiivisen luvun arvon saamiseksi riittää soveltaa sanaan suoraan yllä esitettyä etumerkittömän luvun menetelmää. Toisin sanoen Nelikone käyttää kahden komplementti -esitystä (engl. two s complement). Toisinaan ohjelmassa joudutaan käsittelemään tietoa pienemmissä yksiköissä, esimerkiksi puolisanoina (32 bittiä), neljännessanoina (16 bittiä) tai tavuina (8 bittiä). Nelikielessä ei ole tätä varten erillisiä käskyjä, mutta nämä operaatiot voidaan koostaa bitittäisten operaatioiden avulla. Kukin käsky vie 8 tavua; käskyjen koodaus jätetään tarkoituksella määrittelemättä. Koneessa on 2 1 6 eli 65536 rekisteriä, joista kaikki paitsi yksi ovat yleiskäyttöisiä. Rekisterit on numeroitu 0 65535; rekisteriin viitataan symbolisessa konekielessä rekisterin numerolla, jonka eteen on sijoitettu dollarinmerkki, siis $0, $15, $65535. Rekisterit $0 $65533 ovat yleiskäyttöisiä. Rekisteriä $65534 voidaan haluttaessa käyttää yleiskäyttöisen rekisterin tapaan, mutta se on tavanomaisesti varattu erityiseen käyttöön (ks. slide-käsky). Rekisteri $65535 on erikoisrekisteri: sen arvo on aina nolla, eikä sinne kirjoittaminen muuta sen arvoa. Tätä voidaan käyttää ilmaisemaan, että käs- 4

kyn rekisterioperandin arvo on aina nolla, ja kone saattaa käsitellä tällaiset käskyt nopeammin. Lisäksi koneessa on käskyosoitinrekisteri, johon ei voi ohjelmassa suoraan viitata. Se sisältää seuraavaksi suoritettavan käskyn osoitteen. Kun Nelikone käynnistyy, se lataa ajettavan ohjelman jostakin tarkemmin määrittelemättömästä lähteestä. Suorituksen alkaessa rekisterin $65534 sisältö on nolla, muiden rekisterien lähtöarvoon ei saa luottaa. Nelikoneen käskykanta on esitelty taulukoissa 1 ja 2. Jokainen käsky esitellään symbolisen konekielen kannalta; koneen simulaattorissa käskyjä voi latoa myös ohjelmallisesti kulkematta symbolisen konekielen kautta; tästä voi lukea tarkemmin ohjelman dokumentaatiosta. Symbolisessa konekielessä tulee olla myös tapa määritellä symbolisia nimiä osoitteille ja vakioille. Sovitaan niin, että rivin alussa oleva sana, jonka perässä on kaksoispiste, määrittelee kyseisen sanan symboliseksi vakioksi, jonka arvona on seuraavan käskyn osoite. Sovitaan myös, että pseudokäsky dw, jonka perään kirjoitetaan lukuja pilkuilla erotettuina, lisää siihen kohtaan uusia kahdeksantavuisia muuttujan, jodien alkuarvot ovat kyseiset luvut. Lisäksi on käytössä db, joka toimii samoin yksitavuisille muuttujille; mutta jos lukuja on annettu määrä, joka ei ole kahdeksalla jaollinen, laitetaan loppuun nollatavuja niin monta, että lukumäärästä tulee kahdeksalla jaollinen. Myös on käytössä ds, jonka perään kirjoitetaan merkkijono: se luo tarvittavan määrän muuttujia, joiden alkuarvoiksi se latoo merkkijonon merkit järjestyksessä; tarvittaessa loppuun sijoitetaan nollatavuja tasaamaan lukumäärä kahdeksalla jaolliseksi. Kuvassa 5 on esitetty kuvien 1, 2, 3 ja 4 aliohjelma nelikielellä. 5 Systeemikutsut Ollakseen hyödyllinen ohjelman tulee voida vaikuttaa ympäristöönsä sekä ottaa ympäristöstään vaikutteita. Tämä tapahtuu ohjaamalla erilaisia oheislaitteita kuten näyttöä, printteriä ja hiirtä. Yleensä tavallisen ohjelman ei anneta kuitenkaan vapaasti keskustella oheislaitteiden avulla; syyt lienevät kaikille selvät. Sen sijaan käyttöjärjestelmä keskustelee laitteiden kanssa ja välittää ohjelmien pyynnöt eteenpäin huolehtien siitä, että samaan aikaan käynnissä olevat ohjelmat eivät tallo toisiaan varpaille. Käytännössä ohjelman tulee voidakseen keskustella ympäristönsä kanssa siis keskustella käyttöjärjestelmän kanssa. Tavallisesti tämä tapahtuu systeemikutsujen (engl. system calls) avulla: kun ohjelma haluaa käyttää käyttöjärjestelmän palveluita, se käyttää jotain erityistä mekanismia kutsuakseen käyttöjärjestelmää 6. Nelikoneen tapauksessa koneeseen on sisäänrakennettu jokunen systeemikutsu. 6 Konekielellä ohjelmoinnista Symbolisella konekielellä ohjelmointi voi olla tottumattomalle outoa, joten sanotaan sananen siitä. Symbolisella konekielellä ohjelmoinnin kaksi tärkeintä eroa korkean tason kielillä ohjelmointiin nähden on, että konekielellä joudutaan kaikki kontrollirakenteet kirjoittaa hyppyjä tai muuta vastaavaa menetelmää käyttäen ja että lausekkeet joudutaan käsin purkamaan osaoperaatioihinsa (päättäen samalla, minne välitulokset tallennetaan). Näinpä konekieliohjelmointi on hyvinkin matalan tason näperöintiä ja se kannattaa pääosin jättää kääntäjän huoleksi. Yksi asia, joka saattaa tuntua oudolta korkean tason ohjelmointikieliin tottuneesta, on tietotyyppien erilainen tulkinta. Lähes kaikissa korkean tason kielissä jokaiseen tiedonpalaseen liittyy tyyppi, joka kertoo, mitä operaatioita sille saa tehdä ja miten se pitää tulkita arvoksi; monissa asetetaan vielä rajoitus, jonka mukaan muuttuja voi pitää sisällään vain yhden tyyppisiä tiedonpalasia. Symbolisessa konekielissä tiedonpalalla ei ole mitään sisäsyntyistä tyyppiä; jokaiselle tiedonpalaselle voi periaatteessa tehdä mitä vain, ja valittu operaatio kertoo, minkä tyypin mukaisena sitä käsitellään. 6 Toinen vaihtoehto olisi antaa käyttöjärjestelmän kutsua ohjelmaa tarvittaessa. Tätä sanottaisiin tapahtumapohjaiseksi (engl. event-based) systeemiksi. Tavallisesti todellisissa järjestelmissä käytetään tarpeen mukaan molempia järjestelyitä. 5

ld $tgt, $src ld $tgt, imm ld $tgt, label ld $tgt, [addr] ld $tgt, [label] ld $tgt, [$base+offset] ld $tgt, [$base-offset] st $src, [addr] st $src, [label] st $src, [$base+offset] st $src, [$base-offset] add $tgt, $opr 1, imm add $tgt, $opr 1, $opr 2 sub $tgt, $opr 1, $opr 2 muls $tgt, $ovr, $opr 1, $opr 2 mulu $tgt, $ovr, $opr 1, $opr 2 divs $quot, $rem, $dend 1, $dend 2, $sor divu $quot, $rem, $dend 1, $dend 2, $sor Latauskäskyt Kopioi rekisterin $src sisällön rekisteriin $tgt. Kopioi kokonaisluvun imm rekisteriin $tgt. Kopioi osoitteen label rekisteriin $tgt. Kopioi osoitteesta addr löytyvän sanan rekisteriin $tgt. Kopioi osoitteesta addr löytyvän sanan rekisteriin $tgt. Kopioi osoitteesta, joka saadaan laskemalla rekisterin $base sisältö yhteen kokonaisluvun offset kanssa, löytyvän sanan rekisteriin $tgt. Kopioi osoitteesta, joka saadaan vähentämällä rekisterin $base sisällöstä kokonaisluku offset, löytyvän sanan rekisteriin $tgt. Tallennuskäskyt Kopioi osoitteesta addr löytyvän sanan päälle rekisterin $src sisällön. Kopioi osoitteesta addr löytyvän sanan päälle rekisterin $src sisällön. Kopioi osoitteesta, joka saadaan laskemalla rekisterin $base sisältö yhteen kokonaisluvun offset kanssa, löytyvän sanan päälle rekisterin $src sisällön. Kopioi osoitteesta, joka saadaan vähentämällä rekisterin $base sisällöstä kokonaisluku offset, löytyvän sanan päälle rekisterin $src sisällön. Kokonaislukuaritmetiikka Laskee yhteen rekisterin $opr 1 sisällön ja luvun imm, ja tallentaa tuloksen rekisteriin $tgt. Laskee yhteen rekistereiden $opr 1 ja $opr 2 sisällöt ja tallentaa tuloksen rekusteriin $tgt. Vähentää rekisterin $opr 1 sisällöstä rekisterin $opr 2 sisällön ja tallentaa tuloksen rekisteriin $tgt. Kertoo rekisterin $opr 1 sisällön rekisterin $opr 2 sisällöllä ja tallentaa tuloksen 64 vähiten merkitsevää bittiä rekisteriin $tgt ja 64 eniten merkitsevää bittiä rekisteriin $ovr. Luvut tulkitaan etumerkillisiksi. Kuten muls, mutta luvut tulkitaan etumerkittömiksi. Jakaa 128-bittisen luvun, jonka 64 eniten merkitsevää bittiä ovat rekisterissä $dend 1 ja 64 vähiten merkitsevää bittiä rekisterissä $dend 2, 64- bittisellä luvulla, joka on rekisterissä $sor, sekä tallentaa osamäärän rekisteriin $quot ja jakojäännöksen rekisteriin $rem. Luvut tulkitaan etumerkillisiksi. Kuten divs, mutta luvut tulkitaan etumerkittömiksi. Taulukko 1: Nelikoneen käskykanta, osa 1 6

Bitittäiset operaatiot shl $tgt, $opr, $n Siirtää rekisterin $opr bittejä vasemmalle rekisterin $n osoittaman määrän. Jos $n on negatiivinen, siirto tapahtuu kuitenkin oikealle. Uudet bitit saavat arvokseen nolla. sha $tgt, $opr, $n Siirtää rekisterin $opr bittejä vasemmalle rekisterin $n osoittaman määrän. Jos $n on negatiivinen, siirto tapahtuu kuitenkin oikealle. Uudet oikealle tulevat bitit saavat arvokseen nolla. Uudet vasemmalle tulevat bitit saavat arvokseen vanhan vasemmanpuolimmaisen bitin arvon (jolloin merkkibitti kopioituu). and $tgt, $opr 1, $opr 2 Suorittaa bitittäisen JA-operaation rekisterien $opr 1 ja $opr 2 välillä ja tallentaa or $tgt, $opr 1, $opr 2 tuloksen rekisteriin $tgt. Suorittaa bitittäisen TAI-operaation rekisterien $opr 1 ja $opr 2 välillä ja tallentaa tuloksen rekisteriin $tgt. xor $tgt, $opr 1, $opr 2 Suorittaa bitittäisen POISSULKEVA TAI -operaation rekisterien $opr 1 ja $opr 2 välillä ja tallentaa tuloksen rekisteriin $tgt. jump label jump [$tgt] jz $disc, label jn $disc, label jp $disc, label jnz $disc, label jnn $disc, label jnp $disc, label sys read sys write sys exit slide imm Hypyt ja haarautumiset Hyppää osoitteeseen label. Hyppää rekisterin $tgt osoittamaan osoitteeseen. Jos rekisterin $disc sisältö on nolla, hyppää osoitteeseen label. Jos rekisterin $disc sisältö on negatiivinen, hyppää osoitteeseen label. Jos rekisterin $disc sisältö on positiivinen, hyppää osoitteeseen label. Jos rekisterin $disc sisältö ei ole nolla, hyppää osoitteeseen label. Jos rekisterin $disc sisältö ei ole negatiivinen, hyppää osoitteeseen label. Jos rekisterin $disc sisältö ei ole positiivinen, hyppää osoitteeseen label. Systeemikutsut Lukee tiedostosta, jonka tunnus on rekisterissä $0. Tunnuksen tulee olla 0. Rekisteri $1 sisältää osoitteen, josta alkaa luettavalle datalle varattu tila. Rekisteri $2 kertoo tuon tilan pituuden tavuina. Systeemikutsun palattua rekisteri $0 sisältää luettujen merkkien määrän, tai luvun 1, jos lukeminen epäonnistui. Jos yritettiin lukea ainakin yksi tavu, ja systeemikutsu ei lukenut yhtään, on saavutettu tiedoston loppu. Kirjoittaa tiedostoon, jonka tunnus on rekisterissä $0. Tunnuksen tulee olla 1 (normaali tulostus) tai 2 (virheilmoitukset). Rekisteri $1 sisältää osoitteen, josta kirjoitettava data alkaa. varattu tila. Rekisteri $2 kertoo tuon datan määrän tavuina. Systeemikutsun palattua rekisteri $0 sisältää kirjoitettujen merkkien määrän, tai luvun 1, jos kirjoittaminen epäonnistui. Systeemikutsu saattaa kirjoittaa vain osan annetusta datasta, eikä tämä välttämättä tarkoita virhetilannetta. Lopettaa ohjelman. Rekisterissä $0 on ohjelman paluutieto: nolla tarkoittaa onnistunutta suoritusta. Pinonkäsittely Siirtää imm kpl rekistereitä pinoon (positiivinen imm) tai pinosta (negatiivinen). Rekisterien numerointia siirretään siten, että rekisteristä $imm tulee $0 (positiivinen imm) tai päinvastoin. Numeroinnin muutos ei koske rekistereitä $65534 (pino-osoitin) eikä $65535 (nollarekisteri). Taulukko 2: Nelikoneen käskykanta, osa 2 7

str2ulong: LD $2, 0 LD $4, 10 LD $8, 8 LD $9, 255 LD $10, 7 loop: LD $5, $1 DIVU $6, $7, $65535, $5, $8 SUB $7, $10, $7 MULU $6, $65535, $6, $8 MULU $7, $65535, $7, $8 SUB $7, $65535, $7 LD $3, [$6] SHL $3, $3, $7 AND $3, $3, $9 JZ $3, break MULU $2, $65535, $2, $4 ADD $3, $3, -48 ADD $2, $2, $3 ADD $1, $1, 1 JUMP loop break: ; return rv LD $1, $2 JUMP [$0] Kuva 5: Yksinkertainen aliohjelma Nelikielellä 8