TKT-3201 Tietokonearkkitehtuuri 2 Luku 2: Käskyt: Tietokoneen kieli Tietokonetekniikka
#2 Käskykanta Käytettävissä olevien käskyjen joukko Erilaisilla prosesoreilla erilainen käskykanta Mutta paljon yhteisiä piirteitä Ensimmäisissä tietokoneissa yksinkertainen käskykanta Yksinkertainen toteutus Monissa nykyaikaisissa tietokoneissa on myös yksinkertainen käskykanta Kirjassa käsitellään MIPS-prosessoria Stanford MIPS, jonka kaupallistanut MIPS Technologies (www.mips.com) Esimerkki tyypillisestä modernista käskykannasta
Aritmeettiset operaatiot Summaus, vähennys, kolme operandia Kaksi lähdettä, yksi kohde add a, b, c # a sijoitetaan b + c kaikilla aritmeettisilla operaatiolla on tämä muoto Sunnitteluperiaate 1: yksinkertaisuus suosii säännöllisyyttä Säännöllisyys yksinkertaistaa toteutusta Yleensä yksinkertainen ratkaisu tarjoaa korkeamman suorituskyvyn pienemmällä kustannuksella #3
Aritmetiikka, esimerkki C -koodi: f = (g + h) - (i + j); käännetty MIPS -koodi: add t0, g, h # temp t0 = g + h add t1, i, j # temp t1 = i + j sub f, t0, t1 # f = t0 - t1 #4
Rekisterioperandit Aritmetiikkakäskyt käyttävät rekisterioperandeja MIPS:ssä 32 32-bit rekisteritiedosto (register file) Käytetään usein tarvittavan datan säilytykseen Rekisterit numeroitu 0-31 32-bit data: word Assemblerin nimeämiskäytäntö $t0, $t1,, $t9 : väliaikaismuuttujat $s0, $s1,, $s7 : talletetut muuttujat Suunnitteluperiaate 2: pienempi on nopeampi vrt. päämuisti: miljoonia muistipaikkoja #5
Registerioperandi, esimerkki C -koodi: f = (g + h) - (i + j); Muuttujat f,, j rekistereissä $s0,, $s4 käännetty MIPS -koodi: add $t0, $s1, $s2 add $t1, $s3, $s4 sub $s0, $t0, $t1 #6
Muistioperandit päämuistia käytetään yhdistelmädatalle taulukot, rakenteet, dynaaminen data aritmetiikkaoperaatio Lataa operandit muistista rekisteriin Tallenna tulos rekisteristä muistiin muisti tavu-osoitettu Yksi osoite identifioi 8-bitisen tavun 32-bittiset sanat järjestetty muistiin Sanan osoite on 4:n monikerta #7
Tavujärjestys (Endianness) Ilmaisee missä järjestyksessä tietokone käsittelee suurempia kuin yhden tavun kokonaisuuksia osoite data Big Endian eniten merkitsevät tavut tallentuvat alempiin osoitteisiin MIPS, Internetin dataliikenne Little Endian vähiten merkitsevät tavut tallentuvat alempiin osoitteisiin Intelin prosessorit 4N+3 4N+2 b 15 b 14... b 8 4N+1 4N+0 osoite 4N+3 4N+2 4N+1 4N+0 b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 b 23 b 22... b 16 b 31 b 30... b 24 data b 31 b 30... b 24 b 23 b 22... b 16 b 15 b 14... b 8 b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 #8
Muistioperandi, esimerkki 1 C -koodi: g = h + A[8]; g rekisterissä $s1, h rekisterissä $s2, A:n kantasosoite rekisteri $s3 käännetty MIPS -koodi: Indeksi 8 vaatii poikkeaman (offset) 32 4 tavua per sana lw $t0, 32($s3) add $s1, $s2, $t0 # load word offset Kantaosoitteen rekisteri #9
Muistioperandi, esimerkki 2 C -koodi: A[12] = h + A[8]; h rekisterissä $s2, A:n kantaosoite rekisterissä $s3 käännetty MIPS -koodi: Indeksi 8 vaatii poikkeaman 32 lw $t0, 32($s3) # load word add $t0, $s2, $t0 sw $t0, 48($s3) # store word #10
Rekisterit / muisti Rekisteriviittaus nopeampi kuin muistiviittaus Muistissa olevan datan operointi vaatii latauksen ja tallennuksen Useampia käskyjä suoritettavana Kääntäjä käyttää mahdollisimman usein rekistereitä muuttujien tallentamiseen Muistiin talletetaan harvemmin viitattavat muuttujat Rekisterioptimointi yksi tärkeimmistä optimoinneista #11
Välitön osoitus (Immediate) Käskysanassa oleva vakio addi $s3, $s3, 4 Ei vähennyskäskya välittömällä osoituksella Summaus negatiivisella vakiolla addi $s2, $s1, -1 Suunnitteluperiaate 3: yleisimmät tapaukset tehdään nopeiksi Pieniä vakioita käsitellään usein Välittömällä osoituksella vältetään latauskäsky #12
Vakio nolla MIPS:n rekisteri 0 ($zero) vakio 0 Rekisterin sisältöä ei voi muuttaa Käytännöllinen useissa toimenpiteissä Esim. sijoita arvo rekisteristä toiseen add $t2, $s1, $zero #13
Etumerkittömät kokonaisluvut (unsigned integers) n-bittinen kokonaisluku lukualue: [0, +2 n 1] Esim. 0000 0000 0000 0000 0000 0000 0000 1011 2 = 0 + + 1 2 3 + 0 2 2 +1 2 1 +1 2 0 = 0 + + 8 + 0 + 2 + 1 = 11 10 32-bittiset kokonaisluvut 0 +4,294,967,295 #14
Kahden komplementtiluvut (2s-Complement) n-bittinen kahden komplementtiluku lukualua: [ 2 n 1, +2 n 1 1] Esim. 1111 1111 1111 1111 1111 1111 1111 1100 2 = 1 2 31 + 1 2 30 + + 1 2 2 +0 2 1 +0 2 0 = 2,147,483,648 + 2,147,483,644 = 4 10 32-bittinen luku 2,147,483,648 +2,147,483,647 #15
Kahden komplementtiluvut Eniten merkitsevä bitti on (Bit 31) etumerkkibitti 1 negatiivisille luvuille 0 ei-negatiivisille luvuille ( 2 n 1 ) ei ole esitettävissä Ei-negatiivisilla luvuilla on sama etumerkitön ja kahden komplementti -esitys Muutamia erityislukuja 0: 0000 0000 0000 1: 1111 1111 1111 Pienin negatiivinen luku: 1000 0000 0000 Suurin positiivinen luku: 0111 1111 1111 #16
Etumerkin vaihto (Signed Negation) komplementoi ja summaa 1 Komplementti: 1 0, 0 1 x + x = 1111...1112 = 1 x + 1= x Esim: negaatio +2 +2 = 0000 0000 0010 2 2 = 1111 1111 1101 2 + 1 = 1111 1111 1110 2 #17
Etumerkin laajennus (Sign Extension) Luvun esittäminen suuremmalla bittimäärällä Säilytetään numeerinen arvo MIPS:n käskykannassa addi: laajenna välittömän vakion etumerkkibitit lb, lh: laajenna ladatun tavun/puolisanan etumerkki beq, bne: laajenna siirtymän etumerkki Kopioidaan etumerkkibittiä vasemmalle Etumerkittömät luvut: lisätään etunollia Esim: 8-bittinen luku 16-bittiseksi +2: 0000 0010 => 0000 0000 0000 0010 2: 1111 1110 => 1111 1111 1111 1110 #18
Käskyjen esitys Käskyt enkoodataan binäärisanoiksi konekoodi MIPS -käskyt Enkoodataan 32-bittisiksi käskysanoiksi Pieni määrä formaatteja, joiden mukaan enkoodataan operaatiokoodi (opcode), rekisterinumero, säännöllisyys! Rekisterinumerot $t0 $t7 : rekisterit 8 15 $t8 $t9 : rekisterit 24 25 $s0 $s7 : rekisterit 16 23 #19
MIPS R-formaatin käsky käskykentät op rs rt rd shamt funct 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits op: operaatiokoodi (opcode) rs: ensimmäisen lähderekisterin numero rt: toisen lähderekisterin numero rd: kohderekisterin numero shamt: siirtojen lukumäärä (toistaiseksi 00000) funct: funktiokoodi (laajentaa opcodea) #20
R-formaatti, esimerkki op rs rt rd shamt funct 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits add $t0, $s1, $s2 special $s1 $s2 $t0 0 add 0 17 18 8 0 32 000000 10001 10010 01000 00000 100000 00000010001100100100000000100000 2 = 02324020 16 #21
Hexadesimaaliluvut 16-kantainen esitys (Base 16) Kompakti esitystapa bittijonoille 4 bittiä per hex digit 0 0000 4 0100 8 1000 c 1100 1 0001 5 0101 9 1001 d 1101 2 0010 6 0110 a 1010 e 1110 3 0011 7 0111 b 1011 f 1111 Example: eca8 6420 1110 1100 1010 1000 0110 0100 0010 0000 #22
MIPS I-formaatin käsky op rs rt constant or address 6 bits 5 bits 5 bits 16 bits Välittömät aritmetiikka- ja lataa/tallenna-käskyt rt: kohde- tai lähderekisterin numero Constant: 2 15 to +2 15 1 Address: rs-rekisterissä olevaan kantaosoitteeseen lisättävä poikkeama Suunnitteluperiaate 4: Hyvä suunnittelu vaatii hyviä kompromissejä Erilaiset formaatit monimutkaistavat dekoodausta Formaatit kannattaa pitää mahdollisimman samanlaisina #23
#24 Talletetun ohjelman periaate (Stored Program) Käskyt esitetään binäärisinä kuten data Käskyt ja data talletetaan muistiin Ohjelmat voivat ohjelmoida ohjelmiin Esim. kääntäjät, linkkerit, Binääriyhteensopivuus sallii käännettyjen ohjelmien toimimisen myös erilaisissa tietokoneissa standardoidut käskykannat
Loogiset operaatiot käskyt bittien manipulointiin Operaatio C Java MIPS Siirrä vasemmalle << << sll Siirrä oikealle >> >>> srl AND & & and, andi OR or, ori NOT ~ ~ nor käyttökelpoisia poimittaessa tai lisättäessä bittiryhmiä sanaan #25
Siirto-operaatiot (Shift) op rs rt rd shamt funct 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits shamt: siirrettävien bittipositioiden lukumäärä Looginen siirto vasemmalle Siirrä vasemmalle ja lisää 0 oikealta i-bittinen Sll vastaa kertomista luvulla 2 i Looginen siirto oikealle Siirrä oikealle ja lisää 0 vasemmalta i-bittinen srl vastaa luvun jakamista luvulla 2 i (ainoastaan etumerkittmillä luvuilla) #26
AND -operaatio bittien maskaus sanan sisällä Valitse muutamia bittejä, nollaa kaikki muut and $t0, $t1, $t2 $t2 $t1 $t0 0000 0000 0000 0000 0000 1101 1100 0000 0000 0000 0000 0000 0011 1100 0000 0000 0000 0000 0000 0000 0000 1100 0000 0000 #27
OR -operaatio Lisätään bittejä sanaan Aseta osa biteistä 1 koskematta muihin or $t0, $t1, $t2 $t2 $t1 $t0 0000 0000 0000 0000 0000 1101 1100 0000 0000 0000 0000 0000 0011 1100 0000 0000 0000 0000 0000 0000 0011 1101 1100 0000 #28
NOT -operaatio Sanan bittien invertointi Muuta 0 1 ja 1 0 MIPS: 3-operandin NOR -käsky a NOR b == NOT ( a OR b ) nor $t0, $t1, $zero Rekisteri 0: luettaessa aina nolla $t1 $t0 0000 0000 0000 0000 0011 1100 0000 0000 1111 1111 1111 1111 1100 0011 1111 1111 #29
Ehdolliset operaatiot Haarautuminen nimiöityyn käskyyn, jos annettu ehto on tosi muutoin jatketaan sekventiaalista suoritusta beq rs, rt, L1 jos (rs == rt), haaraudu L1-nimiöityyn käskyyn bne rs, rt, L1 jos (rs!= rt), haaraudu L1-nimiöityyn käskyyn j L1 ehdoton hyppy L1-nimiöityyn käskyyn #30
If-lausekkeiden kääntäminen C -koodi: if (i==j) f = g+h; else f = g-h; f, g, rekistereissä $s0, $s1, käännetty MIPS -koodi: bne $s3, $s4, Else add $s0, $s1, $s2 j Exit Else: sub $s0, $s1, $s2 Exit: Assembler laskee osoitteet #31
Silmukkalausekkeiden kääntäminen C -koodi: while (save[i] == k) i += 1; i rekisterissä $s3, k rekisterissä $s5, save:n osoite rekisterissä $s6 käännetty MIPS -koodi: Loop: sll $t1, $s3, 2 add $t1, $t1, $s6 lw $t0, 0($t1) bne $t0, $s5, Exit addi $s3, $s3, 1 j Loop Exit: #32
Peruslohkot (Basic Block) käskysekvenssi, jossa ei ole haarautumisia (paitsi lopussa) ei ole haarautumisen kohteista (paitsi alussa) Kääntäjät identifioivat peruslohkot optimointeja varten Kehittyneissä prosessoreissa voidaan kiihdyttää peruslohkojen suoritusta #33
Lisää ehdollisia operaatioita Aseta tulokseksi 1, jos ehto on tosi muutoin aseta 0 slt rd, rs, rt if (rs < rt) rd = 1; else rd = 0; slti rt, rs, constant if (rs < constant) rt = 1; else rt = 0; Käytetään yhdessä beq- tai bne -käskyn kanssa slt $t0, $s1, $s2 # if ($s1 < $s2) bne $t0, $zero, L # branch to L #34
Haarautumiskäskyn suunnittelu miksei blt, bge, jne? Laitteisto vertailuille <,, on hitaampi kuin =, haarautumisen yhdistäminen vaatii enemmän työtä per käsky, hidastaa kellotaajuutta kaikki käskyt kärsivät! beq ja bne ovat yleisimmin tarvitut vertailut hyvä suunnittelukompromissi #35
Etumerkillinen / etumerkitön etumerkillinen vertailu: slt, slti etumerkitön vertailu: sltu, sltui esimerkki $s0 = 1111 1111 1111 1111 1111 1111 1111 1111 $s1 = 0000 0000 0000 0000 0000 0000 0000 0001 slt $t0, $s0, $s1 # signed 1 < +1 $t0 = 1 sltu $t0, $s0, $s1 # unsigned +4,294,967,295 > +1 $t0 = 0 #36
Aliohjelmakutsu (Procedure Calling) Tarvittavat askeleet 1. Tallenna aliohjelman argumentit rekistereihin 2. Siirrä ohjelman hallinta aliohjelmalle 3. Hanki aliohjelmalle tallennustilaa 4. Suorita aliohjelman operaatiot 5. Talleta tulos rekisteriin kutsujaa varten 6. Palaa kutsukohtaan #37
Rekistereiden käyttö $a0 $a3: argumentit (reg. 4 7) $v0, $v1: tulosarvot (reg. 2 3) $t0 $t9: välitulokset Kutsuttava voi kirjoittaa näihin vapaasti $s0 $s7: talletus Kutsuttavan talletettava/palautettava $gp: globaali osoitin staattiseen dataan (reg. 28) $sp: pino-osoitin (stack pointer) (reg. 29) $fp: kehysosoitin (frame pointer) (reg. 30) $ra: paluuosoite (reg. 31) #38
Aliohjelmakutsujen käskyt Aliohjelmakutsu: jump and link jal ProcedureLabel Kutsua seuraavan käskyn osoite talletetaan rekisteriin $ra Hypätään kohdeosoitteeseen Aliohjelmasta paluu: jump register jr $ra Kopioi rekisterin $ra ohjelmalaskuriin (program counter) Tätä voidaan käyttää myös etukäteen laskettuihin hyppyihin Esim. case/switch -lausekkeet #39
Aliohjelmakutsu, esimerkki C-koodi: int leaf_example (int g, h, i, j) { int f; f = (g + h) - (i + j); return f; } g,, j rekistereissä $a0,, $a3 f rekisterissä $s0 (joten ei tarvetta tallentaa rekisteriä $s0 pinoon) Tulos talletetaan rekisteriin $v0 #40
Aliohjelmakutsu, esimerkki MIPS-koodi: Leaf_example: addi $sp, $sp, -4 sw $s0, 0($sp) add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1 add $v0, $s0, $zero lw $s0, 0($sp) addi $sp, $sp, 4 jr $ra Save $s0 on stack Procedure body Result Restore $s0 Return #41
Sisäkkäiset aliohjelmakutsut (Nested Procedures) Aliohjelma kutsuu muita aliohjelmia Sisäkkäisissä kutsuissa, kutsuja tallettaa pinoon paluuosoitteen ja kaikki argumentit ja väliaikaismuuttujat, joita tarvitaan kutsun jälkeen palauttaa talletetut tiedot pinosta kutsun jälkeen #42
Sisäkkäiset kutsut, esimerkki C -koodi: int fact (int n) { if (n < 1) return f; else return n * fact(n - 1); } Argumentti n rekisterissä $a0 Tulos rekisterissä $v0 #43
Sisäkkäiset kutsut, esimerkki MIPS -koodi: fact: addi $sp, $sp, -8 # adjust stack for 2 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument slti $t0, $a0, 1 # test for n < 1 beq $t0, $zero, L1 addi $v0, $zero, 1 # if so, result is 1 addi $sp, $sp, 8 # pop 2 items from stack jr $ra # and return L1: addi $a0, $a0, -1 # else decrement n jal fact # recursive call lw $a0, 0($sp) # restore original n lw $ra, 4($sp) # and return address addi $sp, $sp, 8 # pop 2 items from stack mul $v0, $a0, $v0 # multiply to get result jr $ra # and return #44
Paikallinen data pinossa Kutsuttavan aliohjelman allokoima paikallinen data esim. C:n automaattisen muuttujat Aliohjelman kehys (aktivointitietue, frame pointer $fp) Jotkut kääntäjät käyttävät pinon talletustilan hallintaan #45
Muistisegmentit Text: ohjelmakoodi Static data: globaalit muuttujat esim. staattiset muuttujat C- kielessä, vakiotaulukot ja merkkijonot Rekisteri $gp alustetaan osoitteella siten, että ±poikkeamia voidaan käyttää osoittamaan tähän segmenttiin Dynamic data: heap Esim. malloc (C-kieli), new (Java-kielessä) Stack: automaattitallennus #46
Merkkijonot tavu-enkoodattu kirjainmerkkijoukko ASCII: 128 merkkiä 95 grafiikkamerkkiä, 33 ohjausmerkkiä Latin-1: 256 merkkiä ASCII, +96 lisägrafiikkamerkkiä Unicode: 32-bit merkkijoukko Käytetään Java, C++ wide characters, Suurin osa kaikista maailman kirjainmerkeistä, plus erilaisia symboleita UTF-8, UTF-16: muuttuvan mittaiset enkoodaukset #47
Tavu/puolisana-operaatiot Voidaan käyttää bittioperaatioissa MIPS: tavun/puolisanan lataus/tallennus Yleensä merkkijonojen käsittelyssä lb rt, offset(rs) lh rt, offset(rs) Rekisterissä rt etumerkin laajennus 32 bittiin lbu rt, offset(rs) lhu rt, offset(rs) Rekisterissä rt nollalla laajennus 32-bittiin sb rt, offset(rs) sh rt, offset(rs) Tallenna 32-bittisen rekisterin oikeanpuoleisin (least significant) tavu tai puolisana #48
String Copy -esimerkki C -koodi (naïve): Null-terminoitu merkkijono void strcpy (char x[], char y[]) { int i; i = 0; while ((x[i]=y[i])!='\0') i += 1; } x:n ja y:n osoitteet rekistereissä $a0 ja $a1 i rekisterissä $s0 #49
String Copy -esimerkki MIPS -koodi: strcpy: addi $sp, $sp, -4 # adjust stack for 1 item sw $s0, 0($sp) # save $s0 add $s0, $zero, $zero # i = 0 L1: add $t1, $s0, $a1 # addr of y[i] in $t1 lbu $t2, 0($t1) # $t2 = y[i] add $t3, $s0, $a0 # addr of x[i] in $t3 sb $t2, 0($t3) # x[i] = y[i] beq $t2, $zero, L2 # exit loop if y[i] == 0 addi $s0, $s0, 1 # i = i + 1 j L1 # next iteration of loop L2: lw $s0, 0($sp) # restore saved $s0 addi $sp, $sp, 4 # pop 1 item from stack jr $ra # and return #50
32-bittiset vakiot Suurin osa vakioista on pieniä 16-bittinen välitön vakio on useimmiten riittävä 32-bittinen vakio lui rt, constant kopioi 16-bittisen vakion rt:n vasemmanpuoleisiin 16 bittiin Nollaa rt:n oikeanpuoleiset 16 bittiä lui $s0, 61 0000 0000 0111 1101 0000 0000 0000 0000 ori $s0, $s0, 2304 0000 0000 0111 1101 0000 1001 0000 0000 #51
Haarautumisosoitteet Haarautumiskäsky määrittelee Opcode, 2 rekisteriä ja kohdeosoitteen Yleensä haarautumiskohde on lähellä haarautumiskohtaa joko edessä tai takana op rs rt constant or address 6 bits 5 bits 5 bits 16 bits Ohjelmalaskuriin suhteutettu osoitus (PC-relative addressing) Kohdeosoite = PC + offset 4 (offset voi olla ±) PC inkrementoitu jo 4:llä ennen kohteen laskemista #52
Hyppyosoitteet Hyppyjen (j,jal) kohteet voivat olla missä tahansa text-segmentissä Täydellinen kohdeosoite enkoodataan käskyyn op address 6 bits 26 bits (Pseudo)suora hyppyosoitus kohdeosoite= PC 31 28 : (address 4) #53
Haarautumiskohde, esimerkki Loop koodi aiemmasta esimerkistä oletetaan Loop osoitteessa 80000 Loop: sll $t1, $s3, 2 80000 0 0 19 9 4 0 add $t1, $t1, $s6 80004 0 9 22 9 0 32 lw $t0, 0($t1) 80008 35 9 8 0 bne $t0, $s5, Exit 80012 5 8 21 2 addi $s3, $s3, 1 80016 8 19 19 1 j Loop 80020 2 20000 Exit: 80024 #54
Haarautuminen kauemmas haarautumiskohde on liian kaukana enkoodattavaksi 16-bittiseen poikkeamaan Assembler kirjoittaa koodin toisella tavalla Esim. beq $s0,$s1, L1 bne $s0,$s1, L2 j L1 L2: #55
#56 Osoitusmuodot; yhteenveto