Datorteknik Föreläsning 2 Programmering i C och assembler MIPS instruktionsarkitektur
Mål Att ge en inblick i programspråket C Att veta varför assemblerprogrammering är viktigt Att börja arbeta med MIPS-assembler Att känna till något om programmeringstekniker Att kunna gå från flödesschema till program Att kunna använda ett antal MIPS-instruktioner
Innehåll Flödesschema och grovprogram för JPEG Programmeringshjälpmedel C: datatyper, funktioner och andra konstruktioner Adresser i C MIPS assemblerinstruktioner Registerkonventioner Subrutiner
Vad händer med en add-instruktion? En add-instruktion i MIPS är ett 32-bits bitmönster Vad gör processorn med detta bitmönster? Enklaste exemplet: Addera innehållet i reg 4 med innehållet i reg 5 och lägg resultatet i reg 3. add $3, $4, $5 Vi möter några viktiga byggblock i processorn: ALU, register och styrlogik
Instruktioner som bitmönster i minnet Alla MIPS-instruktioner är 32 bitar stora, 4 byte De kodas binärt på något av tre följande sätt: I-typ op (6) rs (5) rt (5) offset (16) R-typ op (6) rs (5) rt (5) rd (5) sa (5) funk (6) J-typ op (6) hoppadress (26)
Vad händer med en add-instruktion add $3,$4,$5 är av R-typ op (6) rs (5) rt (5) rd (5) sa (5) funk (6) op=000000, rs=00100, rt=00101, rd=00011, sa=00000, funk=100000
Byggblock: registerbanken rs (läs) [4] rt (läs) [5] rd (skriv) [3] skriv data läs data 1 32 bit läs data 2 32 bit Registernummer: 5 bit Registren är organiserade som 32 parallella D-vippor per register skriv styrn.
Var hamnar det vi läser från registren? Vi ska ju göra en aritmetisk operation (add) Aritmetisk Logisk Enhet (ALU)
Byggblock: ALU In 1 32 bit In 2 32 bit Ut 32 bit Styrning Med styrsignalerna kan funktionen hos ALU:n påverkas. Exempel: Styrsignal Funktion 000 and 001 or 010 add 110 sub 111 slt
Hur vet ALUn vad den ska göra? Resterande bitar i instruktionen används till styrlogik. Vi kan göra ett blockschema över hur det funkar i add-fallet!
I N S T R U K T I O N Dataväg för add-instruktion Läs reg 1 läs data 1 In 1 Läs reg 2 Skriv reg skriv data läs data 2 32 bit In 2 32 bit ALU Ut 32 bit Styrning skriv styrn. Styrlogik
Datavägar Processorn byggs upp genom att definiera datavägar, dvs hur data transporteras mellan olika enheter På motsvarande sätt kan datavägar ritas upp för andra typer av instruktioner
Hjälpmedel Editor: För att skriva in programtexten Kompilator: Översätter t.ex. C-koden till assembler/maskinkod Assemblator: Översätter assemblerkod till maskinkod (binära mönster) Länkare: Kopplar ihop maskinkod från olika håll C-bibliotek: Förkompilerade, ofta använda rutiner (tex för utskrift) Debugger: Miljö för kontrollerad körning av program
Programmera i C Funktioner: Subrutiner i C returnerar värde av viss typ har ett antal argument lokala variabler returtyp void - inget värde /* Struktur för C-funktion */ typ fknnamn(typ par1, typ par2) { } /* lokala variabler */ /* satser */ /* returnera värde */ return ret_value; /* Exempel på riktig funktion */ /* Returnera det största av 2 tal */ int max(int x, int y) { } int biggest; /* lokal var */ if (x < y) { biggest = y; } else { biggest = x; } return biggest;
Grundläggande datatyper C har en mängd fördefinierade datatyper, tex heltal, flyttal etc. Man kan definiera egna typer ur de tillgängliga. HELTAL int i; POSITIVT HELTAL unsigned int k; FLYTTAL float f; FLYTTAL I DUBBEL PRECISION double d; TECKEN char ch; POSITVT TECKEN (0-255) unsigned char c;
Vektorer I C är det enkelt att definiera vektorer av olika typer. Kom ihåg: Index går alltid från 0 till storleken-1! VEKTOR MED 11 HELTAL MATRIS 8x8 HELTAL 3-DIM MATRIS AV FLYTTAL TECKENSTRÄNG 40 TKN int v[11]; int blk[8][8]; float f[17][17][17]; char str[40];
Egendefinierade datastrukturer I C kan man definiera egna typer med typedef. Kan göra programmen mer överskådliga EXEMPEL typedef struct { z.real = 2*3.14159; float real; z.imag = 1.0E-7; float imag; } complex;
Enkla satser Några grundläggande satser i C int a,b,c,d; /* Deklaration */ a=3; b=c=5; /* Man får göra så här! */ d=a+b; b=d-(c-d); a=b/d; /* Heltalsdivision */ c=(a+b)*c % d; /* % betyder resten */
Villkorssatser Om man behöver göra olika saker beroende på ett villkor... int flag, a; if (flag == 1) { a = a - 2; } else { /* Obs flag=1 är ett uttryck som */ a = a + 96; /* alltid har värdet 1!!! */ }
Relationsoperatorer Det finns flera olika relationsoperatorer int x,y; x == y /* Värdet 1 om x lika med y, 0 annars */ x!= y /* Värdet 1 om x skilt från y, 0 annars */ x < y /* Värdet 1 om x mindre än y, 0 annars */ x >= y /* Värdet 1 om x större än eller lika med y */
For-loop Tre grundläggande strukturer finns för repetition: FOR MALL: for (initalvärde; körkriterium; uppdatering per varv); int i; for (i=0; i < 467; i++) { /* Satser i for-loopen */ }
While-loop Tre grundläggande strukturer finns för repetition: WHILE MALL: while (körkriterium) { /* satser */ } int i = 54; while (i > 0) { /* satser */ i--; /* Minska i med 1 */ } /* Hur många gånger körs while-loopen? */
Do-loop Tre grundläggande strukturer finns för repetition: DO-WHILE MALL: do {/*satser */ } while (körkriterium) int i = 54; do { /* satser */ i--; /* Minska i med 1 */ } while (i > 0) /* Hur många gånger körs do-while-loopen? */
Argument till funktioner EXEMPEL: (kodavsnitt) VI VILL BYTA VÄRDE PÅ a OCH b MED FUNKTIONEN swap() void swap(int a, int b) { int temp; int a, b; a = 5; b = 7; swap(a, b); /* Byt värde */ printf( a=%d, b=%d\n, a, b); UTSKRIFTEN BORDE BLI a=7, b=5. VAD HÄNDER? } temp = a; a = b; b = temp; KOMMER DETTA ATT FUNGERA? VARFÖR?
Adresser till argument Vill vi förändra argumenten, kan vi inte bara skicka värdet, utan måste skicka en referens (adress) till argumentet! &: Adressoperatorn - ger adressen för en variabel *: Tar fram det som finns i adressen (dereferens) int *p; /* p är en adress till en int */ void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } ANROP: swap(&a, &b);
Varför är C ett bra språk? C är ett högnivåspråk samtidigt som det tillåter hårdvarunära konstruktioner Lämpligt för oss på vår nivå i programmeringsmodellen Mycket mjukvara finns skrivet i språket Tyvärr är C också nästan helt utan kontroller och ställer vissa krav på disciplin hos programmeraren
MIPS-arkitekturen Generella register Programräknare Minne $0 $1 $2 $3... $30 $31 PC 32 generella register $0-$31 Programräknaren, PC, innehåller adressen till nästa instruktion som ska utföras Minnet innehåller både instruktioner och data
Modell av minnet 0 1 2 3 4 5 6 7 n-2 n-1 Hexadecimal 6A CB 18 E7 00 0F C1 07.. Binär notation 0 01101010 1 11001011 2 00011000 3 11100111 4 00000000 5 00001111 6 11000001 7 00000111.. n-2 n-1 M[0] = 01101010 = 0x6A M.w[0] = 0110 1010 1100 1011 0001 1000 1110 0111 = 0x6A CD 18 E7 M.w[0] betyder ordet som finns på adress 0 M.h[2] = 0x18 E7 halvord (16 bit)
Assemblerinstruktioner MIPS-instruktioner finns för några olika ändamål: Minnesinstruktioner (hämtar från och skriver i minnet. Aritmetiska instruktioner (addition, multiplikation, etc.) Kan bara göras i register. Logiska operationer (and,or, nor, etc). I register. Programflödesinstruktioner. Hopp och villkorssatser.
Assemblerinstruktioner Instruktion Förklaring Vad den gör add $3,$4,$5 Addera innehållen i reg. $4 och $5, lägg resultatet i reg $3 addi $3,$4,456 Addera innehållet i reg $4 med konstanten 456, lägg resultatet i reg $3 lw $4,12($10) Läs ett ord i minnet på adress 12+$10 och lägg det i reg. $4 sw $5,16($11) Skriv innehållet i reg. $5 till minnet på adress 16+$11 lui $2,0xA000 ori $2,$2,0x0020 Lägg 0xA0000020 i register $2 $3 = $4 + $5 $3 = $4 + 456 $4 = M.w[12+$10] M.w[16+$11] = $5 $2 = 0xA0000020
Minnesinstruktioner MIPS-namn lb $rt,offset($rs) lh $rt,offset($rs) lw $rt,offset($rs) sb $rt,offset($rs) sh $rt,offset($rs) sw $rt,offset($rs) Kommentar $rt = M[$rs + offset] (8 bitar) $rt = M.h[$rs + offset] (16 bitar) $rt = M.w[$rs + offset] (32 bitar) M[$rs + offset] = $rt (8 bitar) M.h[$rs + offset] = $rt (16 bitar) M.w[$rs + offset] = $rt (32 bitar) Minnesaccesser kan göras med 8, 16 eller 32 bitar Adressen räknas ut som summan av innehållet i ett register plus en offset offset är 16 bitar stor: -32768 32767
Aritmetiska instruktioner MIPS-namn Kommentar add $rd,$rs,$rt Addera två tal i register addi $rd,$rs,k Addera ett tal i register med en konstant sub $rd,$rs,$rt Subtrahera två tal i register slt $rd,$rs,$rt Gör $rd = 1 om $rs < $rt annars gör $rd = 0 slti $rd,$rs,k Gör $rd = 1 om $rs < K annars gör $rd = 0 Aritmetiska instruktioner har två källoperander och en destinationsoperand Operanderna är alltid i register utom ena källoperanden som också kan vara en konstant. Konstanten får då vara max 16 bitar lång!
MIPS-namn and $rd,$rs,$rt andi $rd,$rs,k or $rd,$rs,$rt ori $rd,$rs,k nor $rd,$rs,$rt xor $rd,$rs,$rt xori $rd,$rs,k Logiska instruktioner Kommentar Bitvis OCH mellan två tal i register Bitvis OCH mellan ett tal i register och en konstant Bitvis ELLER mellan två tal i register Bitvis ELLER mellan ett tal i register och en konstant Bitvis ELLER mellan två tal i register. Varje bit inverteras i resultatet Bitvis exklusivt ELLER mellan två tal i register Bitvis exklusivt ELLER mellan ett tal i register och en konstant
Problem: lägg 32-bits tal i ett register Vanligt problem. Immediate-instruktionerna kan inte klara det (max 16 bitars konstant) Speciellt för adresser Lösning: Kombination av två instruktioner Ex: talet 0xAB074081 ska in i register $4 lui $4, 0xAB07 # Lägg de 16 högsta bitarna i övre delen ori $4,$4,0x4081 # Logiskt eller i de lägsta 16 bitarna
Villkorliga hopp MIPS-namn beq $rs,$rt,label bne $rs,$rt,label Kommentar Hoppa till label om $rs == $rt Hoppa till label om $rs!= $rt Översätt följande C-kod till assembler. a, b, x och y finns i register $16-$19. if (a == b) { x = 0; } y = x; Omskriven C-kod: if (a!= b) goto L1; x = 0; L1: y = x; Assemblerkod: bne $16,$17,L1 nop or $18,$0,$0 L1: or $19,$0,$18
Ovillkorliga hopp MIPS-namn j label jr $rs Kommentar Hoppa till label. Adressen label anges med 26 bitar Hoppa till adressen som finns i register $rs
Subrutinanrop i MIPS-assembler För att kunna anropa subrutiner måste vi veta Vart ska vi hoppa? Hur ska vi efter subrutinen veta vart vi ska hoppa tillbaka? Instruktioner: jal <label> och jalr $register. Dessa sparar automatiskt återhoppsadressen i $31 (ra) Återhoppsinstruktionen jr $31 hoppar tillbaka!
Subrutinanrop Huvudprogram Subrutin Subrutinen ska hoppa tillbaka till olika ställen beroende på varifrån den anropades. Återhoppsadressen måste alltså sparas! (Reg $31) MIPS-namn jal label jalr $rs jr $31 Kommentar Hoppa till label. Kom ihåg återhoppsadressen i register $31. Hoppa till adressen som finns i register $rs. Kom ihåg återhoppsadressen i register $31. Hoppa tillbaka från subrutin
Hur ser maskinkoden ut i MIPS? Det finns tre huvudsakligen olika typer av instruktioner som representeras med olika bitmönster I-typ (immediate) instruktioner R-typ (register) instruktioner J-typ (jump) instruktioner Varje instruktion är 32 bit lång
Instruktionsformat Alla instruktioner är 32 bitar stora, 4 byte De kodas binärt på något av tre följande sätt: op (6) rs (5) rt (5) offset (16) op (6) rs (5) rt (5) rd (5) sa (5) funk (6) op (6) hoppadress (26)
I-typ op (6) rs (5) rt (5) offset (16) Instruktioner av I-typ är t.ex.: addi, ori, beq, lw, sw op är en 6-bitar stor operationskod rs, och rt är 5 bitar och pekar ut operanderna i register offset är 16 bitar och används som konstant eller adressdifferens
R-typ op (6) rs (5) rt (5) rd (5) sa (5) funk (6) Instruktioner av R-typ är t.ex.: add, or, sub op är en 6-bitar stor operationskod rs, rt, och rd är 5 bitar och pekar ut operanderna i register sa är 5 bitar shift amount (vid skiftinstruktioner) funk är 6 bitar funktionskod
J-typ op (6) hoppadress (26) Instruktioner av J-typ är t.ex.: j, jal op är en 6-bitar stor operationskod hoppadressen är en 26 bitar stor konstant
Registren i MIPS REG NAMN KOMMENTAR $0 zero alltid noll $1 at används av assemblern $2-$3 v0-v1 returvärden från funktioner $4-$7 a0-a3 argument till subrutiner $8-$15 t0-t7 temporära register $16-$23 s0-s7 får ej förändras av subrutiner $24-$25 t8-t9 temporära register $26-$27 k0-k1 används av operativsystem el avb.rutiner $28 gp global datapekare $29 sp stackpekare (nästa tisdag!) $30 s8/fp ibland frame pointer $31 ra return address: återhoppsadress
Sammanfattning Introduktion till C: standardtyper, funktioner, villkorssatser, repetitionsslingor, pekare Assemblerinstruktioner för MIPS olika typer av instruktioner (aritm, logisk, hopp, ) maskinkod för I,R och J-instruktioner Subrutiner registerkonventionen för MIPS