OHJ-4200. Laitteistonläheinen ohjelmointi



Samankaltaiset tiedostot
Laitteistonläheinen ohjelmointi

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

Laitteistonläheinen ohjelmointi

Jakso 4 Aliohjelmien toteutus

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Aktivaatiotietue. Yleiskäsite funktio (aliohjelma) -mekanismin tarvitsemille tiedoille. Kehysosoitin (%fp) missä tiedot ovat

Luento 4 Aliohjelmien toteutus

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Jakso 4 Aliohjelmien toteutus

Luento 1 Tietokonejärjestelmän rakenne

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

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

Luento 1 Tietokonejärjestelmän rakenne

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

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

käännösprosessi Kääntäjä Konekielikääntäjä (Assembler) Yhdistelijä (linker) Lataaja (loader)

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

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

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

Luento 4 Aliohjelmien toteutus

Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö C-ohjelmassa

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

Luento 2 (verkkoluento 2) Ttk-91 järjestelmä

Luento 4 Aliohjelmien toteutus

Harjoitustyö: virtuaalikone

Luento 1 (verkkoluento 1) Tietokonejärjestelmä

Luento 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Kertausluento luennoista 1-3 1

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

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

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

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Käännös, linkitys ja lataus

2 Konekieli, aliohjelmat, keskeytykset

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

1. Keskusyksikön rakenne

Sisältöä. Tietokoneen rakenne. Ch 1 - Ch 8 [Sta06] Valikoituja paloja TITO-kurssista. Tietokonejärjestelmä

Jakso 4 Aliohjelmien toteutus

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

Jakso 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

Tietokonejärjestelmä. Tietokoneen rakenne. Ch 1 - Ch 8 [Sta06] Valikoituja paloja. TITO-kurssista. John von Neumann ja EDVAC, 1949.

Luento 2 (verkkoluento 2) Ttk-91 järjestelmä

Jakso 12 Yhteenveto. Keskeiset asiat Teemu Kerola, K2000

Tietokoneen toiminta, K Tavoitteet (4)

Loppukurssin järjestelyt C:n edistyneet piirteet

Tietorakenteet ja algoritmit

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

Loppukurssin järjestelyt

SISÄLLYS sisällys 1 Tietokoneen toimintaperiaate ja käyttö 2 Tietokoneen historia 3 Tietokoneen rakenteen ja toiminnan perusteet

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Tietorakenteet ja algoritmit

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

4. Lausekielinen ohjelmointi 4.1

Tiedon sijainti suoritusaikana (3) Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Miten tietoon viitataan? (4)

Käyttöjärjestelmän rakenne

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

Monipuolinen esimerkki

Osoitin ja viittaus C++:ssa

Jakso 10 Ohjelman suoritus järjestelmässä

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

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

PRINCIPLES OF PROGRAMMING LANGUAGES - DEBUGGER

Järjestelmän ulkoinen muisti I/O

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Muuttujat Tietorakenteet Kontrolli Optimointi Tarkistukset

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Perinteiset tietokoneohjelmat alkavat pääohjelmasta, c:ssä main(), jossa edetään rivi riviltä ja käsky käskyltä.

Tietueet. Tietueiden määrittely

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Muuttujat Tietorakenteet Kontrolli Optimointi Tarkistukset

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Osoittimet ja taulukot

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

Luento 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Muuttujat Tietorakenteet Kontrolli Optimointi Tarkistukset

Muistihierarkia Kiintolevyt I/O:n toteutus

Luento 10 Käännös, linkitys ja lataus

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

Luento 2 TTK-91 tietokone ja sen KOKSI simulaattori

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

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

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

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

Jakso 10 Ohjelman suoritus järjestelmässä. Käännös Linkitys Dynaaminen linkitys Lataus

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

Zeon PDF Driver Trial

Luento 10 Käännös, linkitys ja lataus. Käännös Linkitys Dynaaminen linkitys Lataus

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

Jakso 10 Ohjelman suoritus järjestelmässä

Luento 10 Käännös, linkitys ja lataus

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Muuttujat Tietorakenteet Kontrolli Optimointi Tarkistukset

Ohjelmointiharjoituksia Arduino-ympäristössä

Transkriptio:

OHJ-4200 Laitteistonläheinen ohjelmointi

Laitteistonläheinen ohjelmointi 4 op Luennoija: Pertti Lehtinen Harjoitustyö: Jyke Jokinen Esitiedot: Mikroprosessorit Perusohjelmointikurssi Kursiin osat: luennot, harjoitustyö, tentti Materiaali: luentomoniste

Kurssin tavoite Oppia ymmärtämään konekielisiä ohjelmia Mitä on ohjelma prosessorin tasolla Saada käsitys ohjelman luomiseen käytetyistä työkaluista ja niiden tehtävistä Tutustua erilaisiin arkkitehtuureihin Mikrokontrollerista työasemasuorittimiin Tutustua lausekielten perusmekanismien toteutukseen konekielitasolla Mitä kääntäjä tekee lähdekoodista

Miksi Jos pitää tehdä jotain mitä kääntäjä ei osaa tai jos kääntäjää ei ole Kääntäjän tuloksen tarkistaminen Kääntäjissä on joskus virheitä Oleellista tietoa, jos teet Laiteajuria Käyttöjärjestelmää tai muuta stand-alone ohjelmaa Kääntäjän toteutusta Suorittimen suunnittelua Useilla eri kielillä ohjelmoitua sovellusta

Ohjelmoijan työkaluketju Hello World esimerkki lintu% more hello.c #include <stdio.h> int main() { printf( Hello, World\n ); return 0; } lintu% gcc o hello hello.c lintu%./hello Hello, World lintu% Ohjelmoija luo tekstimuotoisen ohjelman jollakin ohjelmointikielellä, kääntää sen konekielelle ja ajaa

Ohjelmoijan työkaluketju Editori konekielikääntäjä Hello.c Hello.o Crt0.o Esikääntäjä yhdistelijä hello Libc.so Kääntäjä suoritin lataaja Hello.s

Editori Ohjelma luodaan teksteditorilla, vaikkapa emacs

Esikääntäjä C(++)-kielen esikääntäjä suorittaa tekstikorvauksia ennen varsinaista käännöstä Käsittelee #include direktiivit Laajentaa #define määrittelyiden mukaiset makrot Jättää osia koodista pois #if #endif direktiivien ohjaamana Poistaa kommentit

Esikääntäjä C(++)-kielen ominaisuus Paikkaa C-kielen rajallisuutta Import mekanismi puuttuu Modulirakenne puuttuu Tarjoaa makromekanismin, aiemmin myös nimetyt vakiot Alun perin ei const- määrettä Mahdollistaa ehdollisen kääntämisen

Esikäännetty Hello-ohjelma Nyt #include direktiivi korvataan viitatun tiedoston sisällöllä. lintu% gcc E hello.c extern int printf( const char *, ); int main() { printf( Hello, World\n ); return 0; } lintu% tässä esitetty vain relevantti osa laajennosta, paljon muutakin tulee mukaan

Kääntäjä Kääntäjän tehtävä on kääntää lähdekielinen ohjelma symboliselle konekielelle Suoritetaan gcc S hello.c, saadaan hello.s

Käännetty hello.c Tulos gcc O S hello.c komennosta.file "hello.c".section.rodata.str1.8,"ams",@progbits,1.align 8.LLC0:.asciz "Hello, World".section ".text".align 4.global main.type main, #function.proc 04 main: save %sp, -112, %sp sethi %hi(.llc0), %o0 call puts, 0 or %o0, %lo(.llc0), %o0 jmp %i7+8 restore %g0, 0, %o0.size main,.-main.ident "GCC: (GNU) 4.1.1"

Kääntäjä Muunnoksessa lähdekielestä konekielelle Kontrollirakenteet (if, while, for, ) muutetaan hyppykäskyiksi (jmp, branch ) ja kohdeosoitteiksi (label) Muuttujat sijoitetaan muistiin tai rekistereihin Lausekkeet evaluoidaan sopivilla käskyjonoilla Vakiot (merkkijonot) sijoitetaan muistiin Kääntäjä tekee myös paljon tarkistuksia Kielissä on sääntöjä ja rajoituksia, jotta Mahdollisimman paljon virheitä paljastuisi ennen ajoa Kääntäjien ja tulkkien tekeminen olisi mahdollista

Konekielikääntäjä Konekielikääntäjä muuntaa symbolisen konekielen binääriseen muotoon 00: 9d e3 bf 90 save %sp, -112, %sp 04: 11 00 00 00 sethi %hi(0x0), %o0 08: 40 00 00 00 call 0x8 0c: 90 12 20 00 or %o0, %lo(0x0), %o0 10: 81 c7 e0 08 ret 14: 91 e8 20 00 restore %g0, 0, %o0 Toiminto yleensä hyvin suoraviivainen Yksi symbolinen käsky on yksi konekielen käsky Symboliset osoitteen korvataan numeerisilla osoitteilla Lopulliset osoitteet vielä tuntemattomia

Konekielikääntäjä Symbolinen konekieli koostuu Konekäskyistä Data-alkioiden määritteluistä Nimetyistä muistiosoitteista (label) Ohjauskomennoista (directives) Kaksi ensimmäistä varsinaisesti tuottavat ohjelmaa, direktiivit ohjaavat käännöstä Konekielikääntäjän tuottama objektitiedosto on yleensä muodoltaan varsin monimutkainen.

Objektiformaatteja ELF, Executable and Linkable Format Solaris, Linux, System V Unix, BSD Unix COFF, Common Object File Format Tru64 Unix, Systen V Unix, Linux PE, Portable Executable Windows NT MSDOS.EXE,.COM Unix a.out

Konekielikääntäjä (symbolinen) Konekieliohjelma koostuu käskyistä, muistiosoitteiden nimistä (label) ja ohjauskomennoista (direktiiveistä) Käskyt ovat yleensä yksi yhteen arkkitehtuurin konekäskyjä, joskus myös ns. synteettisiä käskyjä (clr a xor a,a ) Labelit julkisia (esim. funktiot) tai paikallisia (esim. paikalliset hypyt/silmukat) paikallisia symboleita varten yleensä oma syntaksi, jolla vähennetään symbolitaulun täyttymistä

Konekielikääntäjä Direktiiveillä ohjelma jaetaan osiin text, data, bss, section direktiivit Määritellään dataa Tekstiä: ascii, asciz Kokonaislukuja: byte, half, word, nword, quad Liukulukuja: single, double, quad Alustamatonta tilaa: skip, reserve, space Symbolin (label) ominaisuuksia voidaan tarkentaa common, local, global, func, proc, size Muita toimintoja align, file, ident

konekielikääntäjä Konekielikääntäjä yleensä toimii hyvin suoraviivaisesti Joskus sen tehtäväksi on jätetty yksinkertaisia optimointeja Käskyn valinta siirtymän koon mukaan (Suhteelliset) hyppykäskyt Osoitusmuodon valinta 8, 16, 32 bittinen siirtymä Vakion lataus Arkkitehtuurikohtaisia, samoin kuin synteettiset käskyt

Yhdistelijä Yhdistelijä kokoaa ohjelman Kääntäjän tuottama objektitiedosto Edellä hello.o Muut erikseen käännetyt objektit Tällä kertaa niitä ei ole, isommissa ohjelmissa on Kirjastosta haettavat osat IO-funktiot (printf, ) Apufunktiot (strlen, ) Kielen tuki (esim kertolasku arkkitehtuureissa, joissa ei käskykannassa) Alustus- ja lopetuskoodi Pinon alustus, globaalit rakentajat/purkajat Yhdistelijä kiinnittää ohjelman sijainnin muistissa, käyttöjärjestelmä tai ympäristö määrää, mikä tämä osoite on (esim. SUN ympäristössä 0x10000 )

Yhdistelijä Yhdistely voi olla staattista tai dynaamista Perinteisessä staattisessa yhdistelyssä kaikki osat kootaan yhdeksi suoritettavaksi tiedostoksi Nykyaikaisessa dynaamisessa yhdistelyssä kirjastot liitetään vasta ohjelman latauksen yhteydessä Joissain ympäristöissä vasta ensimmäisen viittauksen yhteydessä

Yhdistelijä Ohjelman perusosat ovat Text eli ohjelman koodialue Kirjoitussuojattu Tänne on koottu kaikista ohjelman osista löytyvä koodi Sisältö levytiedostossa Data eli ohjelmassa määritellyt alustetut muuttujat Kirjoitettavissa Alkuarvot levytiedostosta Bss eli ohjelman alustamattomat muuttujat Kirjoitettavissa Varataan käyttöjärjestelmältä, alkuarvo yleensä nolla Lisäksi muita sektioita joiden avulla ohjelman alueita ryhmitellään

Lataaja Lataaja lukee levytiedoston muistiin ja siirtää kontrollin sille Koodi (text) ja alustettu data (data) ladataan tiedostosta Alustamaton data (bss) vain varataan, samoin pinoalue Dynaamisessa latauksessa lataaja hakee tarvittavat kirjastot, sijoittaa ne muistiin ja kiinnittää tarvittavat osoitteet (tästä lisää myöhemmin) Dynaaminen lataus käytössä kehittyneissä käyttöjärjestelmissä Yksinkertaisissa systeemeissä käytetään staattista latausta

C-kieli C++ -kielen edeltäjä Käytössä laitteiston läheisessä ohjelmoinnissa Lähellä konekieltä, pikemminkin rakenteinen assembler eikä korkean tason kieli Etuja laitteistonläheisessä ohjelmoinnissa Suoraviivainen käännös Rakenteet helposti hahmotettavissa konekielessä Kevyt ajoajan tuki

C-kieli Merkittäviä haittapuolia Heikko siirrettävyys Alustariippuvaisia toimintoja Määrittelemättömiä toimintoja Virhealtis kielioppi Helppo tehdä syntaktisesti laillista, mutta järjetöntä koodia Heikko modulimekanismi Esikääntäjä ja erikseen käännös Ei ajonaikaisia tarkistuksia Taulukkorajat? Osoitinviittaukset? Ylivuodot? Osoittimien käyttö näkyvää Viiteparametrit? Merkkijonot? Taulukot? Alkeelliset kontrollirakenteet Ei kunnollista for-silmukkaa. Switch rakenteena avoin. Vaikea staattinen analysoitavuus Osoittimia pakko käyttää Paljon sivuvaikutuksia Heikot tyyppitarkastukset Näkymättömät tyyppimuunnokset, void osoitin Alunperin ei funktion parametrien tarkistusta C++ yrittää korjata ongelmia, mutta monimutkaistaa kieltä valtavasti

C vs. C++ Ckielessä Ei luokkia Ei rakentajia, purkajia Ei templateja Ei geneerisyyttä Viiteparametreja (ANSI) Käytetään eksplisiittisiä osoittimia Primitiivinen standardikirjasto ei tietorakennekirjastoa

C vs. C++ Ei poikkeuksia (ANSI) Virhekäsittely manuaalista Ei kuormitusta Ei nimiavaruuksia Ei oletusparametreja Ei sisäänrakennettua muistinvarausta Malloc/free kirjastofunktioina primitiivisempiä

C vs. C++ Otsikkotiedostot eri nimisiä Kommentti käytäntö erilainen Muuttujat vain lohkon alussa Käytäntö vaihtelee eri kääntäjissä Ei inline avainsanaa (ANSI)

C-kielen piirteitä Kaksi tasoa muuttujille Paikalliset Funktion parametrit alustettuja paikallisia Globaalit C-kielessä modulitason muuttujat globaaleita muuttujia Määrittely yhdessä.c-tiedostossa Extern-määrittely modulin otsikko tiedostossa (jos tarpeen) Globaali muuttuja tai funktio voidaan piilottaa static-määreellä

C-kielen piirteitä Osoitinaritmetiikka C-kielessä Tavallinen näky C-ohjelmissa, harvinainen muualla. Yleisesti ottaen ei kovin hyvä ajatus. Parametrina toteuttavat viiteparametrin Näin viiteparametri toimii konekielessä Taulukko määrittelee muistialueen, johon annetaan vakio-osoitin char s[80]; Määrittelee muistialueen 80-merkkiä kooltaan ja sen osoitteen (kuten konekielessä) Merkintä s[i] on lyhenne merkinälle *(s+i) Symboli s on vakio-osoitin taulukon alkuun Merkintä s[i] viittaa muistiosoitteeseen s + i * sizeof(s[0]) Indeksointi sisältää aina näkymättömän kertolaskun (siksi C- ohjelmoijat suosivat osoittimia taulukkojen käytössä)

C-kielen piirteitä Sivuvaikutuksia Taulukko on osoitin osoitin on taulukko Merkitään int *p; p[0] vastaa *p Indeksointi on vaihdannainen Siis s[4] = *(s+4] = *(4+s) = 4[s] Vakio merkkijono on merkkitaulukko Vakiotahan voi käyttä silloin kuin muuttujaakin Siis hexdigit = 0123456789ABCDEF [number & 0x0F]; käy mainiosti Huomaa ero seuraavissa char *s = huuhaa ; char s[] = huuhaa ;

C-kielen piirteitä Moniulotteiset taulukot Taulukkojen taulukoita int v[10]; int m[10][10]; int mm[10][10][10];... ja niin edelleen Edellä v on vakio-osoitin kokonaislukuun m on vakio-osoitin kokonaislukutaulukkoon mm on vakio-osoitin taulukkoon kokonaislukutaulukoita Mitä on m[0]? Entä mm[0][0]? Entä *mm? Entä **mm? Entä ***mm;

C-kielen piirteitä Moniulotteiset taulukot hankalia hahmottaa Ja lisäksi jos teemme int x[10]; int *v[10]; v[0] = x; Voimme viitata v[0][0] =? Ja mitä meillä onkaan nyt?

C-kielen piirteitä Moniulotteinen taulukko funktion parametrina ei toimi halutulla tavalla C-kielessä voi välittää parametrina taulukon jonka koko on tuntematon Entä kaksi ulotteinen taulukko, jonka molemmat indeksit ovat tuntemattomia? Ei käy!

C-kielen piirteitä Oudot operaattorit Address of & Viiteparametri on osoitin, tarvitaan tämä toteutukseen Pilkku operaattori Useita lausekkeita voidaan ketjuttaa yhdeksi lausekkeeksi Järkevä käyttö esim. for-lauseen initialisoinnissa Tuskin muualla Sijoitus on operaattori Siis a = b = c = 0; sallittua Ehdollinen lauseke a = (x==0)?b:c; Mahdollistaa yksinkertaisen if-lauseen lausekkeen paikalla Päivitys operaattorit Eli +=, -=,

C-kielen piirteitä Parametrit funktioille aina arvoparametreja Viitteparametrit eksplisiittisinä osoittimina Taulukot ja rakenteet aina osoittimina Joissain c-versioissa rakenteet arvoparametreina Kiusallista vaihtelua siirrettävyyden kannalta Lisäksi parametri aina vähintään int tai double Eli char ja short int konvertoidaan aina int-tyypiksi Float konvertoidaan double-tyypiksi Long int? Unsigned int?

C-kielen piirteitä Funktio-osoittimet Funktioon voi soveltaa address-of operaattoria Voit määritellä osoittimen funktioon Siis int (*fp)(long, char ); int foo( long a, char c ); int bar( long b, char x ); if( kumpi ) { fp = foo; } else { fp = bar; } q = (*fp)( x + 2, x ); Käytetään takaisin kutsujen toteutukseen, käyttöjärjestelmissä laiteohjainteen liittämiseen, c++ virtuaalifunktiot näiden perillinen

C-kielen piirteitä C-kielestä on monia eri ikäisiä, laajalti käytettyjä versioita. Esim C99, ANSI C ja alkuperäinen K&R. Alkuperäisen C-kielen tyypitys hyvin hatara Funktion arvattiin palauttavan int ellei muuta mainita Parametri lista ohjeellinen, esittelyssä ei parametreja mainittu, määrittely sanoi odota suurinpiirtein tällaista. Mahdollistaa muuttuva parametriset funktiot, esim. printf Uusi määrittely long func( char x, int y ) { } Vanha määrittely long func( x, y ) char x; int y; { }

C-kielen piirteitä Vaihtuva parametrilista C-kieli mahdollistaa funktiolle muuttuvan tyyppiset parametrit. Listan alussa voi olla jokin määrä pakollisia parametreja ja sen jälkeen kertomassa että enemmänkin voi olla Funktio itse päättelee, millainen parametrilista on oikeasti Syytä olla joku pakollinen, joka antaa vihjeitä lopuista Tyyppitarkastus ei mahdollista Parametreihin pääsee käsiksi makroilla va_start, va_arg ja va_end Esim printf-funktio: extern int printf( char*, ); Käyttö printf( Merkkijono %s osoite %lx ja pituus %d\n, x, (unsigned long) x, strlen(x) ); Yleisesti ottaen huono ajatus, käytösssä lähinnä standardikirjaston printf ja scanf perheiden funktioissa Kiusallinen siirrettävyyden kannalta

C-kielen piirteitä Esikääntäjän makrot Esikääntäjällä voi määritellä makroja Makrot puretaan tekstikorvauksena Elikä #define ARRAY_SIZE 256 #define ARRAY_MASK ARRAY_SIZE-1 /*vaarallista*/ #define nl printf( \n ) #define swap_bytes16(w) ((((int)(w) & 0x00FFU) << 8 \ (((int)(w) & 0xFF00U) >> 8 )) Kannattaa käyttää sulkeita Mitä on 2*ARRAY_MASK? Makrojen käyttö voi olla vaarallista xs = swap_bytes16( s++ ); /* oops*/ Standardi IO-kirjaston rutiinit joskus makroja!

C-kielen piirteitä Esikääntäjän #include-mekanismi Ko.rivi korvataan rivillä mainitulla tiedostolla <nimi> hakee järjestelmän hakemistoista nimi työhakemistosta Rakennetaan c-kieleen modulirakennetta Riippuvuuksien hallintaan ulkoinen työkalu (make) Ei hierarkiaa, stdio:n mukana tulee kaikki, mitä se tarvitsee omiin määrittelyihinsä nimiavaruus saastuu Otsikko tiedostot vaikuttavat toisiinsa Tiedostot täytyy suojata kahdelta mukaan otolta Järjestys voi vaikuttaa lopputulokseen

C-kielen piirteitä Primitiiviset ohjausrakenteet For-silmukka hyvin avoin for( INIT; TEST; INC ) BODY; Osien välillä ei mitään sidontaa Vaikea optimoida Switch lähinnä computed-goto switch( EHTO ) { BODY } Labelit goto-labeleita BODYn sisällä ei rakennetta Mahdollistaa ns. DUFF-devicen switch ja while lomitettu Goto olemassa Ainakin vanhemmissa kääntäjissä Outoja ominaisuuksia Mahdollista soveltaa address-of goto-labeliin!

C-kielen piirteitä Em. Ominaisuudet mahdollistavat perin sekavan koodin Vrt. obsfuscated C-code contest

Prosessori arkkitehtuuri Perinteinen fetchdecode-execute Käskyt noudetaan ja suoritetaan järjestyksessä Ohjelmoijan perinteinen ajattelu, yhä voimissaan LOOP instr := MEM(PC); PC := PC + 1; CASE instr.opcode is WHEN st0 => MEM(instr.address := %0; WHEN ld0 => %0 := MEM(instr.address); WHEN jmp >= PC = instr.address; END CASE; END LOOP;

Von Neumann arkkitehtuuri CPU käsittelee muistissa olevan ohjelman käskyjen mukaisesti muistissa olevaa dataa Yhteinen koodi ja datamuisti Von Neumann pullonkaula muistiväylä Harvard arkkitehtuuri Erillinen ohjelma- ja datamuisti (väylä) Muita vaihtoehtoja Dataflow arkkitehtuuri

Nykypäivän arkkitehtuurit Erilliset cachet, yhteinen keskusmuisti Eli siis sovellettu harvard-arkkitehtuuri Signaaliprosessoreissa joskus oikeasti erilliset muistiväylät Joskus jopa yksi käskyille, kaksi datalle

Prosessorin rakenne Toimintayksiköitä Aritmeettisloogiset yksiköt, yksi tai useampia Kokonaisluku Liukuluku Muita? (SSE, MMX, etc ) Ohjausyksikkö Muistiyksiköt Data ja koodi erikseen Hyppy-yksikkö huolehtivat kontrollin siirrosta

Prosessorin rakenne Nykyään yleensä liukuhihnoitettu (pipelined) Monta peräkkäistä käskyä suorituksessa yhtä aikaa Liukuhihna voi olla näkymätön tai näkyvä Viivästetyt lataukset Viivästetyt hypyt scoreboarding

Prosessorin rakenne Jotkut prosessorit sisäisesti rinnakkaisia Monta käskyä yhtä aikaa suorituksessa Superscalar processor Out-of-order execution Käskyjä ei aina suoriteta siinä järjestyksessä, kuin ne ovat ohjelmassa Ei myöskään muistiviittauksia Näkyvä rinnakkaisuus VLIW-prosessorit, signaaliprosessorit

Muistihierarkia Rekisterit <-> keskusmuisti Tarkemmin rekisterit <-> cache <-> muisti <-> levy Viimeinen virtuaalimuistin yhteydessä Prosessorissa sisäistä muistia Rekisterit Perinteisesti 4-16 CISC-arkkitehtuurit ia32, mc68xxx, PDP-11, VAX-11, jne Nykyään 16-32, jopa enemmän RISC-arkkitehtuurit Sparc, alpha, MIPS, PowerPC, ARM

Muistinosoitus Miten muistiin voidaan viitata? Arkkitehtuurin keskeinen piirre Eri osoitus tavat: Käskylle ominainen muistipaikka (implicit, inherent) Vakio (immediate) Rekisteri (register, register direct) Rekisterin kautta muistiin (register indirect) Rekisterillä indeksin kera (indexed, register+offset) Suhteellinen (relative) Suoraan muistiin (absolute) Epäsuorasti muistiin (memory indirect) Epäsuorasti rekisteriä muuttaen (autoincrement, autodecrement) Kahden rekisterin summalla (register+register, base+offset) Edellisten yhdistelmiä Muita, kuten modulo-addressing Suorittimen ominaisuus, suunnitteluaikana päätetty

Osoitusmuodot visualisoituna Osoitusmuoto käsky rekisteri muisti ---------------------------------------------------------------------- välitön operandi ---------------------------------------------------------------------- rekisteri R operandi ---------------------------------------------------------------------- suora osoite operandi ---------------------------------------------------------------------- epäsuora osoite osoite operandi ---------------------------------------------------------------------- rekisteriepäsuora R osoite operandi ---------------------------------------------------------------------- indeksoitu R,osoite + indeksi operandi ---------------------------------------------------------------------- kantaosoite R,indeksi + osoite operandi ---------------------------------------------------------------------- muistiepäsuora R,R,offset + osoite,indeksi osoite operandi

osoitusmuodot CISC-arkkitehtuurit: vaihtuvamittaiset käskyt käytössä yleensä useita osoitusmuotoja Käytettävissä useimmissa käskyissä Monimutkainen koodaus RISC-arkkitehtuurit: Vakiomittaiset käskyt vähän osoitusmuotoja Käytettävissä vain lataus ja talletuskäskyissä Load-store arkkitehtuuri Monet nykyarkkitehtuurit jostain RISC CISC välimaastosta Muistiviittauksissa arkkitehtuurikohtaisia rajoituksia Alignment-rajoitukset Käskykoodi sanarajalla Muistialkio sanarajalla

Käskykanta Prosessorilla on ns. ISA, Instruction Set Architecture, käskykanta Jaetaan neljään ryhmään Siirtokäskyt, aritmeettisloogiset, hyppykäskyt ja ohjauskäskyt Käskyt käyttävät toiminnoissa rekistereitä Yleisrekistereitä Erikoisrekistereitä (ohjelmalaskuri, pino-osoitin) Tilalippuja (tai tilarekistereitä) Useimiten rekisterit mahdollisimman yleiskäyttöisiä Vanhemmissa arkkitehtuureissa joskus erikoistuneita rekistereitä Samoin erikoisarkkitehtuureissa IA-32 kehittynyt akkukoneesta yleisrekisteriarkkitehtuuriksi

Käskykanta Käskyssä määritellään operaatio ja kohde Kohteesta osoitusmuoto kertoo sijainnin Yleisrekisterien määrä vaikuttaa koodaukseen, samoin osoitusmuotojen määrä Esim. 16 rekisteriä 4 bittiä 4 osoitusmuotoa 2 bittiä Eli tasapainotellaan käskyn pituuden kanssa valintakysymyksiä suunnitteluvaiheessa RISC: vakiomittainen käsky, nopea dekoodaus CISC: vaihtuvamittainenkäsky, hidas dekoodaus

siirtokäskyt Yleensä kaksi operandia Mistä minne Move CISC yleissiirto, siirtää tietoa paikasta toiseen Load, store Rekisterin lataus, talletus (RISC) Erikoisrekisterin lataus/talletus (kaikki) push, pop Talletus/lataus pinoon

Huomioitavaa Load immediate Pienet vakiot usein koodataan käskysanaan CISC: Pitkät vakiot venyttävät käskykoodia Vakiomittaisilla käskyillä sanan mittainen vakio ei mahdu käskyyn (RISC) Miten ladataan absoluuttinen osoite rekisteriin? SPARC: erikoiskäsky (LOADHI) + OR immediate ARM: load immediate lataa 8 bittiä parillisiin positioihin PC yksi yleisrekistereistä, PC-relative viittaa lähistölle PowerPC: or-immedate ja or-immediate-shifted Käytetään sopivia osoitteita tai vakioita RISC: ei yleensä rekisteri <-> rekisteri siirtoa syntetisoidaan muista käskyistä nollarekisterin avulla

Aritmeettisloogiset käskyt Laskenta Add, sub, mul, div Logiikka And, or, xor Siirrot Lsl, asl, rotate Arkkitehtuurit luokitellaan aritmetiikan toteutuksen myötä 0-3 operandi arkkitehtuureiksi

0-operandikone Ns. pinokone Push ja pop siirtävä tietoa pinoon ja pois Operandit implisiittisiä pinossa a := b + c toteutuu push b push c add pop a Toteutuksina nykyään harvinaisia, mutta yleisiä virtuaalikoneena

1- operandikone Ns. akkukone Käskyllä yksi operandi, toisena ns. akku, johon myös tulos sijoitetaan Yleinen 8-bittisissä prosessoreissa, mikrokontrollereissa MC68xx, PIC, 8085, Z80, 6502 a := b + c toteutuu lda c adda b sta a

2-operandikone Ns. rekisterikone Yleinen mikroprosessoreissa ja minikoneissa Mm. mc680x0, PDP-11, ia32 Nykyään atmel avr, arm thumb Kaksi operandia, joista toinen lähde, toinen lähde ja kohde Joskus mahdollista kaikki osoitusmuodot molemmissa operandeissa (PDP-11) Useimmiten rajatummin (mc680x0), toinen aina rekisteri

2-operandikone a := b + c toteutuu mov c, a add b, a tai yleensä rekisterillä mov c, %r0 add b, %r0 mov %r0, a

3-operandikone Kolme operandia Kohde := Lähde + lähde Yleinen tämän päivän RISC-koneissa a := b+c toteutuu add a, b, c - eipä juuri näin tai todella ld %1, c ld %2, b add %3, %2, %1 st %3, a

Esimerkki eri arkkitehtuureilla Lasketaan c := (d-2b)/2a Tarkastellaan koodin koko ja muistiviittausten määrä (käskyn nouto ja dataviittaukset)

0 ja 1, c := (d-2b)/2a 0-operandi kone push d rrrw- d push b -rrrw- b d push 2 -rrw- 2 b d mul -rrrw- 2b d sub -rrrw- d 2b push a -rrrw- a d-2b push 2 -rrw- 2 a d-2b mul -rrrw- 2a d-2b div -rrrw- (d-2b)/2a pop c -rrrw- 10 käskyä, 4 osoitetta, 2 vakiota 16 fetch/3 data READ/1 data WRITE/9 STACK READ/9 STACK WRITE YHTEENSÄ 38 muistiviittausta 1-operandikone (1 akku A) lda a -rrradd A -r- x+x = 2x sta tmp -rrwlda b -rrradd A -r- x+x = 2x neg A -radd d -rrrdiv tmp -rrrsta c -rrw- 9 käskyä/6 osoitetta 15 fetch/4 data READ/2 data WRITE YHTEENSA 21 viittausta

2 ja 3 operandi 2-operandikone mov b,%1 -rrrasl #1,%1 -rmov d,%2 -rrrsub %1,%2 -rmov a,%1 -rrradd %1,%1 -rdiv %1,%2 -rmove %2,c -rrw- 8 käskyä, 4 osoitetta 12 fetch/3 data READ/1 data WRITE YHTEENSÄ 16 viittausta 3-operandikone add b,b,%1 -rrrrrsub d,%1,%1 -rrradd a,a,%2 -rrrrrdiv %1,%2,c -rrw- 4 käskyä/6 osoitetta 10 fetch/5 data READ / 1 data WRITE YHTEENSÄ 16 viittausta

Huomioita Esimerkit suuntaa antavia Todellisissa ohjelmissa operandit perin harvoin absoluuttiosoitteissa Todennäköisemmin viittaukset rekisteriepäsuorana tai rekisteriin

Hyppykäskyt Ehdoton hyppy Jmp, branch Ehdollinen hyppy Branch Aliohjelmakutsu ja paluu Call, return Poikkeuksen aiheuttavat käskyt eli ohjelmalliset keskeytykset Trap, emt, sys, int,

hyppykäskyt Absoluuttisia tai suhteellisia Absoluuttisessa kohdeosoite ilmenee käskyssä Suoraan tai epäsuorasti Suhteellisessa kohde ilmaistaan siirtymänä nykyiseen ohjelmalaskuriin Koodin paikastariippumattomuus paranee RISC: absoluuttinen hyppy usein vain epäsuorana Absoluuttiosoite ei mahdu käskyyn

aliohjelmakutsut Absoluuttinen tai suhteellinen Kutsu tallettaa seuraavan käskyn osoitteen jonnekin CISC: talletus (yleensä) pinoon RISC: talletus (linkki) rekisteriin Aliohjelmasta paluu epäsuora hyppy RISC arkkitehtuureissa ei yleensä erillistä paluukäskyä

Ohjelmalliset keskeytykset Aiheuttavat kontrollin siirtymisen ennalta määrättyyn paikkaan Käytetään mm. systeemikutsuihin Yleensä hyppyyn liittyy tällöin prosessorin tilan vaihto (user->supervisor) Oma paluu käsky (return-from-interrupt, returnfrom-trap) vaihtaa tilan takaisin Tilanvaihto saattaa myös vaihtaa muistiavaruuden, kannattaa olla varovainen

Ehdolliset hypyt hyppykäskyistä on olemassa ehdollisia versioita (branch-on-equal, Ehdollisuus perustuu Tilalippuihin (MC680x0, ia32, arm, ) Perinteinen tapa Rekisterivertailuun (alpha, mips, ) Compare-and-branch Rekisterin arvoon (mc88000) ehtorekistereihin (powerpc, ) Tavallaan tilalippujen laajennus

Ehdollisuus Tilaliput Yleensä carry, overflow, negative, zero Hypyt näiden yhdistelmien perusteella Yleensä suhteellisia hyppyjä Joskus myös absoluuttisia Ja myös ehdollinen aliohjelmakutsu Tai kuten ARM, kaikki käskyt ehdollisia Liput asettuvat vertailukäskyillä Myös Aritmeettisloogisilla käskyillä (ia32, ) myös siirtokäskyillä (mc680x0, ) Vain pyydettäessä (RISC-arkkitehtuurit) Luo riippuvuuden käskyjen välille (asetus -> käyttö)

ehdollisuus Vaihtoehto: ei tilalippuja Compare-and-jmp (alpha) Erilliset ehtorekisterit Käsky specifioi käytettävän ehtorekisterin Tai ehdot yleisrekistereissä (mc88000) Vertailu tuottaa maskin yleisrekisteriin, hyppy branch-on-bit-set/branch-on-bit-clear

ehdollisuus Kaikki käskyt voivat olla ehdollisia (ARM) käsky voidaan nollata lennossa Helpottaa liukuhihnoitusta hävittäessään lyhyitä hyppyjä

ohjauskäskyt Sekalaista kamaa Keskeytysten hallinta (enable-ints, ) Cachen hallinta Mmun hallinta

Muuta Useissa uusissa arkkitehtuureissa erilaisia sovelluskohtaisia laajennuksia Multimediakäyttöön, grafiikkaan, etc Ia32: MMX, SSE, Sparc: VIS ARM: Neon Useimmiten SIMD laskentaa Siis Single-Instruction-Multiple-Data

Esimerkki arkkitehtuureja Nykyisiä mikrokontrollerit Pic, avr, h8 Mikroprosessorit Sparc, ia32, powerpc, arm Perinteisiä Mikrokontrollerit 8051, 6811 mikroprosessorit PDP-11, mc680x0, 88000, alpha Tulevia? FPGA-pohjaiset prosessorit Microblaze, picoblaze, NIOS Xtensa

PDP-11 DEC (Digital Equipment Corporation) toi 1970 markkinoille minikoneen PDP-11 16-bittinen, 64k muistiavaruus, CISC 6(8)-yleisrekisteriä (R0-R5,SP,PC) 8-osoitusmuotoa register, autoincrement, autodecrement, index Ja samat epäsuorana Kaksioperandikone, kaikki osoitusmuodot sallittu molempiin operandeihin Mov(b), cmp(b), add(b), sub(b), bit(b), bic(b), bis(b) Pinon toteutus autoincrement/autodecrement kautta

MC680x0 Motorolan 32-bittinen arkkitehtuuri (CISC) 16-rekisteriä 8-datarekisteriä (d0-d7) 8-osoiterekisteriä (a0-a6,sp) Erillinen ohjelmalaskuri (pc) ja tilarekisteri 12+ osoitusmuotoa Register, register indirect, autoincrement, autodecrement, indexed (constant/register), absolute, pc-relative, memory indirects Kaksioperandikone Vain move ymmärtää kaikki osoitusmuodot molemmin puolin Muutoin R R op <EA> tai <EA> <EA> op R Pinon toteutus autoincrement/autodecrement kautta

ia-32 Intelin PC-prosessori, CISC 8 yleisrekisteriä+segmenttirekisterit 4 datarekisteriä (ax, bx, cx, dx) 4 osoiterekisteriä (si, di, bp, sp) 6 segmenttirekisteriä (cs, ss, ds, es, gs, fs) Ohjelmalaskuri ja tilarekisteri Osoitusmuodot register, immediate, direct, indirect (base+index+disp) 16-bittisenä» Base: BX tai BP, index: SI tai DI 32-bittisenä» Base: yleisrekisteri, index: ei SP Kaksioperandikone M M op R tai R R op M Pinon käsittely push/pop käskyjen kautta

Sparc SUNin RISC-arkkitehtuuri 32 yleisrekisteriä (g0-g7,i0-i7,l0-l7, o0-o6, o7/link) Nollarekisteri (g0), luettaessa aina 0 Lisäksi 32 liukulukurekisteriä Erillinen ohjelmalaskuri ja tilarekisteri Rekisteri-ikkunointi Load-store arkkitehtuuri 2 osoitusmuotoa (Rn+immediate, Rn+Rm) Sign-extended 13-bit immediate 3 operandikone Rd Rs1 op Rs2, Rd Rs op imm Pino vain ohjelmointikäytäntö

ARM Advanced (Acorn) Risc Machine Ensimmäinen kaupallinen RISC-prosessori (1985) 16-yleisrekisteriä (R0-R13,link,PC) Osoitusmuodot [R], [R+imm], [R+R] Suolana modify, jossa kantarekisteri päivitetään indeksillä (ennen/jälkeen käytön) Unsigned 12-bit immediate, (sub/add erikseen) Load-store, 3-operandi Kaikki käskyt ehdollisia Tilarekisteri (alun perin osa PC-rekisteriä) Lisänä thumb-käskykanta (2-operandi, supistettu)

mc88000 Motorolan RISC-arkkitehtuuri Väistyi sittemmin PPC:n tieltä 32 yleisrekisteriä (r0-r31) Nollarekisteri (r0), linkkirekisteri (r1) Ohjelmalaskuri Load-store arkkitehtuuri Osoitusmuodot [R+imm], [R+R] Zero-extended 16-bit immediate

PowerPC IBM, Apple ja Motorola 32-yleisrekisteriä 32 liukulukurekisteriä 8 ehtorekisteriä Erilliset link- ja count-rekisterit sekä ohjelmalaskuri Myös muita erikoisrekistereitä Osoitusmuodot [R],[R+imm],[R+R] Update muoto myös Sign-extended 16-bit immediate 3-operandi, load-store

AVR (ATMega8) 8-bittinen RISC kontrolleri 16-bittinen muistiavaruus Kaksioperandikone, load-store 32-yleisrekisteriä (8-bittisiä) 6 viimeistä muodostavat 3 16-bittistä osoiterekisteriä Rekistereillä myös muistiosoite Pino-osoitin erikseen Call, push, pop, ret-käyttävät Viitattavissa muistiosoitteen kautta Erillinen koodi ja datamuisti Omat käskyt koodimuistiin viittaukseen (lpm, stm) Osoitusmuotoja Immediate, direct, indirect, postincrement, predecrement, indexed

picoblaze 8-bittinen mikro-ohjain 64-tavua datamuistia Erillinen 31 osoitteen aliohjelmapino Kaksioperandi arkkitehtuuri, load-store Osoitus muodot direct, indirect (koko 96-fpga viipaletta, 12.5% 0.3% piiristä)

NIOS Alteran FPGA Core Täysi 32-bittinen RISC-prosessori Kolmioperandikone, load-store Osoitusmuoto [R+imm] Signed 16-bit immediate

Xtensa Laajennettava arkkitehtuuri Käyttäjä voi lisätä tarpeelliseksi katsomansa käskyn

Kääntäminen Käännöksessä ohjelmointikielen rakenteet muutetaan konekieleksi Rakenteita: Lausekkeen evaluointi Ohjausrakenteet If While Switch for aliohjelmakutsu

Lauseke Periaate sangen yksinkertainen Laske lausekkeen arvo väliaikaiseen paikkaan, sijoita tulos kohteeseen Vasen ja oikea alilauseke rekursiivisesti Eli a = 1; 1 tmp tmp a a = a + 1; a tmp 1 tmp2; tmp3 tmp + tmp2 tmp3 a

Lauseke Huomaa vastaavuus pinokoneeseen Käytännössä pystytään hiukan parempaan C-kieli PDP-11 M680x0 sparc a = a + 1 move.w a,%r0 move.l a,%d0 ld [%g7+a],%l0 add.w #1,%r0 addq.l #1,%d0 add %l0,#1,%l0 move.w %r0,a move.l %d0,a st %l0,[g7+a] Ylläoleva staattisilla muuttujilla

ohjausrakenteet Periaate myös yksinkertainen If Evaluoi ehtolauseke Generoi ehdollinen hyppy, kohde Label1 Generoi true-osa, loppuun hyppy, kohde Label2 Generoi Label1 Generoi else-osa Generoi Label2

ohjausrakenteet While Generoi Label1 Evaluoi ehto Generoi ehdollinen hyppy, kohde label2 Generoi runko Generoi hyppy, kohde Label1 Generoi label2

ohjausrakenteet Kaksi vaihtoehtoa: Hyppytaulu Sopii rajallisiin, pieniin arvoalueisiin Ketjutettu if-else Yleinen ratkaisu Kääntäjän (tekijän) päätettävä, kumpaa käytetään

ohjausrakenteet For C-kielen for avoin silmukka, generointi kuten while:llä, lisää vain initialisointi Muissa kielissä sidotumpi for Esim: FOR i := 0 to 20 DO END Oikea silmukkamuuttuja, mahdollistaa silmukkakäskyjen käytön

aliohjelmakutsu Periaate Evaluoi ja tallenna parametrit paikalleen Kutsu aliohjelmaa Tallenna paluuarvo paikalleen (vain funktioaliohjelmilla) Missä parametrit ovat? Arkkitehtuurista riippuu, minne parametrit käytännössä sijoitetaan Lausekielissä puhutaan ns. aktivaatiotietueesta, joka sisältää parametrit, paluutiedot ja mahdolliset paikalliset muuttujat Abstrakti käsite, ei välttämättä oikea tietue Useimmissa uusissa arkkitehtuureissa olemassa ihan oikeastikin

Muuttujat Missä muuttujat ovat? Muuttujat jaetaan (C-kielessä, ja useimmissa lausekielissä) Näkyvyyden mukaan Yleiset (global), paikalliset (local), parametrit Elinajan mukaan Pysyvät (static), automaattiset (auto) C-kielen automaattinen muuttuja olemassa määrittelylohkonsa sisällä, viitattavissa määrittelystä lohkon loppuun

muuttujat int x; int f( int a, int b ) { int i; static int j; } global, static local, auto local, auto local, static - globaalit muuttujat aina staattisia - lokaalit staattisia tai automaattisia - parametrit aina automaattisia, itse asiassa voidaan katsoa alustetuiksi paikallisiksi muuttujiksi

muuttujat Käännetyn koodin kannalta näkyy Staattisia muuttujia Absoluuttiosoitteissa Parametreja Aktivaatiotietueessa Paikallisia muuttujia aktivaatiotietueessa

Aktivaatiotietue Missä parametrit? Koodin seassa kutsun jälkeen Esim. Fortran Kiusallinen, koska parametrit vakioita kirjoitussuojatussa koodissa, pakottaa referenssien käyttöön (myös vakioparametreille) Staattisesti varatulla muistialueella Estää rekursion (tai ainakin hankaloittaa sitä) Pinossa Yleisin tapa nykyään Laitteistopino (ia32, mc68000, etc ) Ohjelmallinen pino (RISC-arkkitehtuurit yleensä) Rekistereissä Sopii vain skalaari muuttujille Yleensä rajallinen määrä rekistereitä rajallinen määrä parametreja Rekursion toteutus vaatii kuitenkin pinon Yleensä edellisen optimointia (SPARC, ja muutkin RISCit)

Aktivaatiotietue pinossa Mc680x0 tavanomainen esimerkki Pino-osoitin osoittaa pinon huippua FP (framepointer) osoittaa kehyksen keskelle Paramerit positiivisella siirtymällä Paikalliset negatiivisella Linkki osoittaa edelliseen kehykseen Kutsuja latoo parametrit paikalleen, aliohjelmakutsu paluuosoitteen, kutsuttu funktio rakentaa loput parametrit Paluuosoite Linkki Paikalliset muuttujat Talletetut rekisterit SP High address FP Low address

Sparc Sparc käyttää rekisteri-ikkunaa Ajatuksena korvata (osa) aktivaatiotietueesta Saapuvat parametrit i-rekistereissä Lähtevät parametrit o-rekistereissä Paikalliset muuttujat l-rekistereissä Onnistuu vain skalaarimuuttujille taulukot ja tietueet muistiin Myös debuggaus vaatii muuttujien pitämistä muistissa C-kieli muutenkin vastahankainen Address-of operaattori taistelee rekisterimuuttujia vastaan

Sparc aktivaatiotietue Sparc rekisteri-ikkunointi Ja aktivaatiotietue Rekistereissä pinossa

aktivaatiotietue Huomaa tilavaraus rekistereille Saapuvat parametrit edellisessä kehyksessä (tai rekistereissä) Tila pinossa myös rekisteriparametreille Debuggauksen takia Oletusarvoisesti sparc-gcc tallettaa rekisteriparametrit pinoon aina (jollei optimoida) Huomaa kooltaan muuttuva osuus keskellä kehystä Tilaa paikalliselle dynaamiselle varaukselle

Vielä muuttujista Paikalliset muuttujat siis aktivaatiotietueessa (pinossa useimmiten) Staattiset muuttujat data-alueella (joko.data tai.bss) Viitataan arkkitehtuurista riippuen joko absoluuttiosoitteilla tai kantarekisteriin nähden suhteellisena Dynaamiset muuttujat eivät muuta tilannetta, niihin viitataan aina joko paikallisen tai yleisen muuttujan kautta

Muuttujaan viittaus Skalaari muuttujat Globaali absolute tai offset+basereg Joskus myös pc+offset Paikallinen tai parametri fp + offset Offset positiivinen tai negatiivinen

Muuttujaan viittaus Entäpä ei-skalaarit Taulukon alkio C-kielessä base[index] eli *(base+index) yleisen taulukon base absolute Paikallisen fp+offset Siis hae base skaalaa indeksi summaa CISC arkkitehtuureissa saattaa olla suoraan kelvollinen osoitusmuoto Yleisessä tapauksessa tuskin käyttökelpoinen Usein myös load-effective-address käsky apuna Samoin scaled-index osoitusmuoto RISC laskenta usein käsityötä Joskus käytettävissä mukavia käskyjä ARM: multiply-and-accumulate, mahdollisuus shiftata operandia operoitaessa Rakenteen kenttä Base.offset Samoin kuin edellä, mutta ilman skaalausta

Muuttujaan viittaus Epäsuoruuden purku Osoitinmuuttuja tai referenssi Kuten normaali muuttuja Hae sisältö Sen jälkeen epäsuoraosoitus poimii operandin osoittimen perästä

Esimerkkejä käännöksestä Testi ohjelma f.c int y( int a, int b ) { return a - b; } int F( int a, int b ) { return a + Y( a,b); } Käännetään sparc, ia32 ja mc88000 arkkitehtuureissa. Sparc rekisteri-ikkunointia käyttävä RISC Ia32 klassinen CISC Mc88000 klassinen RISC

IA32 Optimoimaton tulos Gcc S f.c Optimoitu Gcc S O f.c Vahvasti optimoitu Gcc S -O3 f.c

mc88000 Optimoimaton Gcc S f.c Optimoitu Gcc S O f.c Vahvasti optimoitu Gcc S O3 f.c

Sparc Optimoimaton Gcc S f.c Optimoitu Gcc S O f.c

Käsitteitä Leaf-procedure, leaf-function Aliohjelma, joka ei kutsu ketään eteenpäin Mahdollista jättää kutsukehys rakentamatta Itsekirjoitetut konekielifunktiot useinmiten tälläisiä Inline-function Funktion koodi laajennetaan kutsukohtaan

Toinen esimerkki Koodi int f( int x, int y ) { int i; for( i = 0; i < 5; i++) x = x*y; } return x;

ia32 Optimoimaton Gcc S loop.c Optimoitu Gcc S O loop.c Vahvasti optimoitu Gcc S O3 loop.c

mc88000 Optimoimaton Gcc S loop.c Optimoitu Gcc S O loop.c Vahvasti optimoitu Gcc S O3 loop.c

sparc Optimoimaton Gcc S loop.c Optimoitu Gcc S O loop.c Optomoitu sparc versiolle 9 Gcc mcpu=v9 S O loop.c

käsitteitä Loop unrolling Silmukka avataan pistämällä riittävä määrä runkoja peräkkäin Constant propagation Vakion sijoitusta valutetaan eteenpäin

Kääntäjän optimoinneista Kääntäjä osaa tehdä kaikenlaisia optimointeja Tärkeitä etenkin geneerisen koodin yhteydessä (template) Erikoistavat yleisen tapauksen koodin Ohjelmoija voi aina kirjoittaa silmukan, kääntäjä huomaa jos vain yksi kierros Ohjelmoijan ei kannata juuri optimoida kooditasolla, keskity algoritmeihin

Omat funktiot Yleensä leaf-funktioita Ei kannata rakentaa aktivaatiotietuetta Tarpeen vain jos kutsut jotakuta eteenpäin Mieti missä parametrit? Missä tulos? Ia32: Pinossa [sp+4], [sp+8], (ilman kehystä) Pinossa [sp+8], (kehystä käytettäessä) Tulos eax Sparc: Rekisterit o0, o1,, o5 (ilman kehystä) Rekisterit i0, i1,, i5 (kehyksen kanssa) Tulos o0 (i0, kehyksen aikana) Mc88000: Rekisterit r2, r3, Tulos r2

Omat funktiot Taulukot parametrina C-kielessä aina viite Muissa kielissä määrittely kertoo onko kyseessä arvo vai referenssi Arvo yleensä kätketty rakenne, koko+sisältö Merkkijonot c-kielessä taulukoita Muissa kielissä yleensä rakenne, varaus+käytetty+sisältö, tms Rakenteet parametrina C-kielessä yleensä välitetään viite, joissakin kääntäjissä arvoparametrina Rakenteissa kääntäjäkohtainen sisältö Missä järjestyksessä kentät ovat Miten alignoitu Joskus valittavissa kääntäjän optiolla

Objektiformaatit Mitä assembler (kääntäjä) tuottaa? Missä muodossa on ajettava tiedosto? Koodia suoritetaan muistista, joten suoritettava ohjelma on ladattava muistiin ennen suoritusta Nykyaikaiset järjestelmät ovat levypohjaisia, joten lataus tapahtuu yleensä tiedostojärjestelmästä Puhutaan ns. Disk-Operating-System (DOS) järjestelmistä Suoritettava tiedosto säilytetään levyllä jossain muodossa

Objektiformaatit Itseasiassa kyseessä kaksi muotoa, ns. objekti (yhdisteltävä) formaatti ja executable (suoritettava) formaatti Aluksi executable formaatit järjestelmä (arkkitehtuuri, valmistaja) kohtaisia Yhdistely formaatit toimittaja (kääntäjä, arkkitehtuuri) kohtaisia Nyttemmin pyritty siirtymään standardiformaatteihin

Yhdistely Aluksi ohjelma käännettiin absoluuttisena Yksi lähdekoodi tiedosto suoritettava tiedosto Nopeasti havaittiin, ettei näin ole hyvä Koodin uudelleenkäyttö hankalaa Lähdekoodi kasvaa suureksi Pienillä muistiavaruuksilla hankala käsitellä Yhdistelijä mahdollistaa erikseen kääntämisen ja koodikirjastot Lisäksi Kirjoitussuojattu (ROM) koodi vaatii datan ja koodin erottelua Erottelu mahdollistaa myös koodin yhteiskäytön kehittyneemmissä (moniajo) käyttöjärjestelmissä

yhdistelijä Yhdistelijä ottaa syötteeksi joukon kääntäjän (assemblerin) tuottamia objekteja ja tuottaa suoritettavan tiedoston Nykyään inkrementaalinen yhdistely tuettua syöte joukko objekteja, tulos objekti objektitiedosto on muodoltaan kuten suoritettava tiedosto Suoritettavassa tiedostossa vain sattuu olemaan oikea koodi oikeassa paikassa

yhdistelijä Objektissa sektiot (koodi,data) + symbolitaulu + sijoittelutieto Symbolitaulu sisältää Määritellyt julkiset symbolit Symbolit, joihin viitataan, mutta joita ei määritellä Sijoittelutieto sisältää tiedot Viittaus absoluuttisesti paikalliseen symboliin Viittaus ulkoiseen symboliin Absoluuttinen tai suhteellinen Objekti rakennettu olettaen alkuosoitteeksi nolla Yhdistely on uudelleen sijoittelua ja symbolien sitomista Koodisektiot kootaan yhteen Datasektiot kootaan yhteen Viittaukset asetetaan kohdalleen sijoittelutiedon avulla

yhdistely Yhdistelijä käy tiedostot läpi Kokoaa koodisektiot peräkkäin ja määrää niiden osoitteet Kokoaa datasektiot peräkkäin ja määrää niiden osoitteet Sitoo määrittelemättömät viittaukset ja valittaa jos kaikkia symboleita ei löydy Sijoitellessaan korjaa viittaukset kohdalleen Kirjasto on kokoelma objekteja Erona on, että sellaisia kirjastomoduleita, joihin ei viitata, ei oteta mukaan

Uudelleen sijoitus Tiedosto sisältää otsikon, koodin (datan) ja uudelleensijoitustiedot (relocation info) Otsikko kertoo em.osien sijainnin tiedostossa Uudelleensijoitusta varten jokainen ohjelmassa oleva viittaus pitää tarkistaa Mistä kohtaa viitataan Minne viitataan Absoluuttisesti vai suhteellisesti

Uudelleen sijoitus Yleensä ohjelma jaetaan sektioihin Koodi, alustettu data, alustamaton data Mikä tahansa sektio voi olla viittauksen kohteena Koodi ja alustettu data voivat sisältää viittauksia Hyppykasky, latauskäsky, hyppytaulu, tms. Koodi (tai data) sektioita voi olla useita

Uudelleen sijoitus Ensin ladataan sektiot muistiin Kirjataan kunkin sektion alkuosoite Käydään relokointitiedot läpi Lasketaan kullekin viittaukselle kohdeosoite Sektion alkuosoite + siirtymä sektiossa Sijoitetaan se oikeaan paikkaan Huomaa Sektion sisäisiä suhteellisia viittauksia ei tarvitse relokoida Sektioiden väliset suhteelliset viittaukset? Tuloksena suoritettava tiedosto Tai uusi yhdisteltävä objekti

Suoritettavat tiedostot Absoluuttinen image CP/M MSDOS.COM Uudelleen sijoitettava image MSDOS.EXE AmigaDOS Kehittyneemmät muodot Unix a.out Coff (Common Object File Format) Elf (Executable and Linking Format) PE (Portable Executable)

Absoluuttinen image Levyllä on vedos keskusmuistista Ladataan aina vakio-osoitteeseen Esim. CP/M lataa suoritettavan ohjelman osoitteeseen 0x100, ja aloittaa suorituksen siitä MSDOS.COM ohjelmalle annetaan yksi 64k segmentti, jossa asustaa Ohjelma on siis yksi yhtenäinen alue sisältäen koodin ja (alustetun) datan Mahdollisesti lomitettuna

Uudelleen sijoitettava Jos syystä tahi toisesta ohjelmaa ei aina voi ladata vakiopaikkaan (eikä ole muistinhallintaa) AmigaDOS: moniajo vaatii, että ohjelma pitää voida suorittaa eri osoitteista MSDOS.EXE: ohjelma koostuu useista segmenteistä, joiden sijaintia ei etukäteen tiedetä Sijoittelu (relocation) tehdään käynnistyksen yhteydessä

AMIGADOS Koodi (ja data) jaettu palikoihin (chunk) Ohjelma ei ole yhtenäinen ei vaadi yhtenäistä vapaata muistia Helpottaa muistinhallintaa Ohjelma latautuu, jos jokaiselle palikalle löytyy tila Ohjelma luotu olettaen palikoiden sijoittuvan peräkkäin (alkaen osoitteesta 0) Absoluuttinen viittaus: Uusi kohde = vanha_kohde vanha_base + uusi_base Suhteellinen viittaus: Uusi siirtymä = vanha siirtymä + ( kohteen_muutos - lähteen_muutos )

MSDOS.EXE (8086) Koodin (absoluuttista) sijoituspaikkaa ei tiedetä Muistin alkuun ladataan ajurit, TSR:t, yms. Sovellus voi käynnistää toisen sovelluksen Ohjelma koostuu segmenteistä Intel segmentointi huolehtii offseteista Ainoastaan segementtirekisterien lataukset pitää relokoida Alustetaan niihin segmenttien alkuosoitteet

Kehittyneemmät muodot Yleensä sama muoto käytössä yhdistelyssä ja suoritettavalla tiedostolla Tiedosto koostuu otsikosta ja sektioista Koodi Data Uudelleensijoitustiedot Symbolitaulu Debug tiedot Ja kaikenlaista muuta

Unix a.out Unixin alkuperäinen objektiformaatti Peräisin PDP-11 arkkitehtuurista Ohjelma jaetaan kahteen sektioon, koodi ja data, jotka sijoitetaan peräkkäin Jako mahdollistaa koodin kohtelemisen readonly-sektiona ja datan read-write-sektiona. Shared text mahdollinen suoritusaikana Lisäksi otsikko sisältää tiedon alustamattoman datan määrästä Nollia ei talleteta levyimageen

elf Unixin toisen polven formaatti Edeltäjät (a.out ja coff) eivät tue kunnolla uusia vaatimuksia C++ vaatii tukea yhdistelijältä Dynaamiset kirjastot vaativat omaa tietoaan Arkkitehtuuri riippumattomuus Tuetaan eri tavujärjestyksiä Erilaisia viittaustapoja Eri siirtymäkoot Segmentoitu vai ei

Elf tiedoston rakenne

Elf header char magic[4] = \177ELF ; // taikanumero char class; // address size, 1 = 32 bits, 2 = 64 bits char byteorder; // 1 little-endian, 2 big-endian char hversion; // header version, aina 1 char pad[9]; short filetype; // type: reloc, exe, shared object, core short archtype; // Sparc, x86, m68k, int fversion; // version, aina 1 int entry; // exec entry point int phdrpos; // program header position int shdrpos; // section header position int flags; // architecture specific flags short hdrsize; // header size short phdrent; // header entry size short phdrcnt; // and count short shrdent; // section entry size short shdrcnt; // and count short strsec; // number of section for section names

Elf sektio tyypit PROGBITS: ohjelman sisältö, mm. koodi ja data NOBITS: sektiolle varataan tila muistista, mutta ei määritellä sisältöä tiedostossa SYMTAB ja DYNSYM: symbolitaulut. Normaali ja dynaamisen yhdistelyn STRTAB: nimitaulut REL ja RELA: relokointi tiedot DYNAMIC ja HASH: yhdistelyaikaista tietoa Lisäksi liput ALLOC: sektio ladataan muistiin WRITE: sektio merkitään kirjoitettavaksi EXECINSTR: sektio sisältää koodia

Tyypillisiä ohjelma sektioita.text: PROGBITS + ALLOC + EXECINSTR Varsinainen koodi.data: PROGBITS + ALLOC + WRITE Alustettu data.rodata: PROGBITS + ALLOC vakiodata.bss: NOBITS + ALLOC + WRITE Alustamaton data.rel.text,.rel.data,.rel.rodata: REL tai RELA Relokointi taulut.init,.fini: PROGBITS + ALLOC + EXECINSTR Mm. C++ globaalit rakentajat ja tuhoajat.symtab: SYMTAB.dynsym: DYNSYM + ALLOC.strtab: STRTAB.dynstr: STRTAB + ALLOC

Dynaamiset kirjastot Monen käyttäjän järjestelmissä havaittiin, että useampi käyttäjä suorittaa samaan koodia Tämä johti koodin jakamiseen Unix shared text segments Komentotulkkia kaikki suorittavat Työasemien ja 32-bittisten prosessorien myötä sovellusten koko alkoi kasvaa hello-world -ohjelma n. 400kb SUNos ympäristössä Kasvu johtui kirjastojen käytön lisääntymisestä Tarvittiin clib + xlib + graphics + Ikkunointi ja grafiikka vaativat lisää koodia, joka kuitenkin on kaikille sovelluksille yhteistä Tarvitaan keino jakaa kirjastokoodia sovellusten välillä Sovelluksen oma koodi pienenee -> muistia kuluu vähemmän Levy imagen koko pienenee -> levytilaa säästyy Kirjastoa voidaan vaihtaa -> bugit korjataan ilman uudelleenkääntämistä Sovellus ei myöskään itsessään sisällä kolmannen osapuolen koodia

Dynaamiset kirjastot Teknisesti Sovellus ja koodi ladataan erikseen muistiin Yhdistely (sovelluksen ja kirjaston) tehdään Etukäteen Käynnistettäessä Viitattaessa Kirjastoittain Symboleittain Yhdistely sisältää osoitteiden sitomisen

Yhdistely etukäteen Kirjasto(i)lle varataan kiinteä osoite muistiavaruudesta Sovellus yhdistellään tätä tietoa vasten Ajoaikana vain muistiavaruuden alustus Koska tällaista resident libraries ROM-koodi sulautetuissa Bios-koodi Vektorointi software interruptin kautta Käyttöjärjestelmä Vektorointi software interruptin kautta Paikasta riippumattomuus oman muistiavaruuden avulla

Ongelmia Kirjaston versiointi Version vaihtuessa rutiinien osoitteiden pitää säilyä Kutsuvektorien käyttö Paikasta riippumattomat kirjastot Eri sovellukset saattavat haluta eri version Entä jos on monta eri kirjastoa? Entä jos kirjastot kutsuvat toisiaan?

Yhdistely käynnistyksessä Sovelluksen käynnistyessä katsotaan, mitä kirjastoja se kaipaa, ja yhdistellään Kirjaston sijaintia muistissa ei sidota etukäteen Tarvitaan symbolitaulu ajoaikana Sisältää tiedot mistä ja mitä kutsutaan Myös kirjasto tulisi relokoida käynnistettäessä Kirjaston halutaan olevan yhteiskäyttöinen Eikä se ole eri sovelluksilla samassa paikassa Siis read-only Kirjastojen tulee olla paikasta riippumatonta koodia

Ongelmia Kirjastot ovat usein hierarkisia Tarve relokoida kirjastossa olevia kutsuja Koodin halutaan olevan read-only Ratkaisu Rakennetaan kutsuvektori käynnistyksessä Kirjastot isoja, paljon rutiineja, sovellus ei käytä läheskään kaikkia, raskasta Sovellus kutsuu vektorin kautta Sekä sovelluskoodi että kirjastokoodi voivat olla read-only

Yhdistely viitattaessa Vaihtoehto A Kutsut oletuksena ohjataan yhdistelijälle Kutsuttaessa etsii rutiinin ja ohjaa hypyn (jatkossa) sinne Kutsu kulkee data-alueella olevan vektorin kautta Data tehtävä kohtaista Yhdistelijä voi muokata sitä lennossa Vaihtoehto B Viittaus tuntemattomaan aiheuttaa poikkeuksen Vaatii enemmän kj-tukea Poikkeus kutsuu yhdistelijää Vaatii käsitteen laiton osoite Helppo juttu koodilla hankalampi datalla

Data kirjastoissa Kirjastot yleensä pelkkää koodia Data-alueet mahdollisia, mutta ei toivottuja Funktioiden staattista dataa, kirjaston globaalia dataa Allokoitava per käyttäjä Dynaamiseti linkattavat datasegmentit Vaativat laitteistotukea Poikkeuksen aiheuttava epäsuora osoitus tms. Katso Multics-järjestelmä, jos kiinnostaa Ei tuettu nykyisissä järjestelmissä Eivätkä niin kovin tarpeellisia

Käytännössä ELF Objekti sisältää kaksi taulua PLT ja GOT PLT, Procedure Linkage Table Koodin osa, muuttumaton, jaettavissa Sovellus koodi kutsuu entryä PLT:ssä Täältä epäsuora hyppy GOT:n kautta kirjastoon GOT, Global Offset Table Data-alueella, yksityinen, tätä dynaaminen lataaja muuttaa Oletusarvona hyppy yhdistelijään, joka selvittää Ketä yritettiin kutsua Korjaa kutsun oikeaan paikkaan

Windows DLL Kirjasto-objektilla kaksi erityissektiota Idata, imported symbols Minne viitataan Symboliin Tai järjestyslukuun (indeksi (export)osoitetauluun) Edata, exported symbols Mitä tarjotaan ulospäin Joko symboli (nimi) Tai järjestysluku (ordinal, indeksi osoitetauluun) Osoitetaulu sisältää symbolia vastaavan osoitteen Kutsut epäsuorina (import) osoitetaulun kautta

Muita ongelmia Entä jos sovellus haluaa ylimääritellä kirjastofunktion? Sellaisen jota kirjastossa olevat funktiot käyttävät Ja siten, että kirjastossa oleva kutsu ohjautuu käyttäjän funktioon

Geneerinen järjestelmä ja väylät

Staattiset järjestelmät Aluksi järjestelmät olivat staattisia Unix kj-generoitiin per alusta, lähdekoodista Asennusta varten oli perusversio, joka sisälsi konsoliajurin ja levyajurin Ensimmäinen tehtävä oli kirjata konfiguraatio ylös Laite xx osoitteessa yy Laite xx1 ositteessa zz Konfiguraation oli syytä olla oikein, tai crash käynnistyksessä

Askel 1 Probe-rutiinit Laiteohjaimeen ilmaantui probe-funktio, joka tarkisti, onko laite oikeasti läsnä Mahdollisti olemattoman laitteen ajurin lisäämisen ytimeen Root-device on sidottu kiinteästi, mutta kaikkia olemassa olevia levyjä voidaan käyttää (eivätkä olemattomat haittaa) Ajurin koodi yhä kasvatti ydintä (generoidaan oma kernel) Sittemmin probe siirtyi aiemmaksi, mikä mahdollisti rakentaa geneerinen ydin Ydin kyselee, mikä levyohjain löytyy ja päättää sen jälkeen kuka on root-device