Maskinnära programmering i C

Slides:



Advertisements
Liknande presentationer
Avlusning Debugger (”avlusare”) Breakpoints Watch.
Advertisements

INTRODUKTION TILL PROGRAMMERING
Kap 1 - Algebra och linjära modeller
Array Skriv ett program som frågar följande: ”Hur många tal vill du mata in?” användaren matat in ett tal t.ex n. då frågar programmet n ggr följande.
void hittaMax(int tal[], int antal, int *pmax) { int i; ??=tal[0]; for(i=1;i??) ??=tal[i]; } int main() { int v[]={1,2,3,4,2}; int.
Joomla © 2009 Stefan Andersson 1. Kontaktformulär  På varje seriös webbplats bör det finnas ett kontaktformulär.  Använd ej maillänkar, risk för spam!
Anders Sjögren Lagringsklasser •en variabel i C har två attribut –type( int, float, char..... ) –lagringsklass( auto, extern, register, static ) •lagringsklassens.
Programstruktur: C för enchipsdatorer
Introduktion till C för enchipsdatorer
Funktioner och programorganisation
Föreläsning 3 Repetition Operatorer Styrstrukturer Deklaration och anrop av metoder.
De fundamentala datatyperna
William Sandqvist Datorteknik övning 2 Subrutinanrop William Sandqvist
Operatorer.
23 August 2014 IS1200 Datorteknik vt09, föreläsning 10, (E och I mfl)1 IS1200 Datorteknik Föreläsning Processorkonstruktion 2. DMA, Direct Memory.
Välkommen Vahid Mosavat
Programmeringsteknik K och Media
Föreläsning 13 Allt om tentan. Sistaminutenhjälp: På fredag 17 december kl 12 sitter Linda i kemi-fiket och svarar på frågor.
Att programmera i språket Java
Föreläsning 2 Datalogi för E1 2D1343
Föreläsning 4 Python: Definiering av egna funktioner Parametrar
Föreläsning 2 Primitiva datatyper Variabler och konstanter Tilldelning Inläsning Operatorer Villkorssatsen if Slingor: while och for.
Karolinska Institutet, studentundersökning Studentundersökning på Karolinska Institutet HT 2013.
Bastugatan 2. Box S Stockholm. Blad 1 Läsarundersökning Maskinentreprenören 2007.
| Trycksår Kommun/Områdes-skillnader (inklusive könsdimensionen) Dennis Nordvall Statistiker/Datamanager,
Programmering B PHP Lektion 2
INFÖR NATIONELLA PROVET
Föreläsning 11 Arrayer.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 6 ( ) INNEHÅLL: -Mera om tabeller.
Pekare och speciell programstruktur i inbyggda system
Repetition inför slutprovet
Pointers. int a=5; int f(int b) { a--; b++; return b; } int main() { int a=3; printf("%d,",f(a)); printf("%d",a); return 0; }
Programmering B PHP Lektion 2
Enkätresultat för Grundskolan Elever 2014 Skola:Hällby skola.
Föreläsning 2 Kort Översikt Över Javaspråket. Källkodsformat Unicode används åäöμψζ tillåtna Inte alla miljöer klarar av det Källkod Bytekod Java VM för.
1 Vänsterskolan Debattartiklar. 2 Aktuell krok 3 Aktuella krokar 1. Direkt krok.
Hittarps IK Kartläggningspresentation år 3.
Från Gotland på kvällen (tågtider enligt 2007) 18:28 19:03 19:41 19:32 20:32 20:53 21:19 18:30 20:32 19:06 19:54 19:58 20:22 19:01 21:40 20:44 23:37 20:11.
TÄNK PÅ ETT HELTAL MELLAN 1-50
Kouzlo starých časů… Letadla Pár foteček pro vzpomínku na dávné doby, tak hezké snění… M.K. 1 I Norrköping får man inte.
OOP F3:1 Marie Olsson OOP Objekt-orienterad programmering Föreläsning 3 Iteration Många variabler av samma sort – Arrayer.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 7 ( ) INNEHÅLL: -Metoder -Lokala variabler -Mera om klasser: -Nyckelorden.
Arbetspensionssystemet i bilder Bildserie med centrala uppgifter om arbetspensionssystemet och dess funktion
1 Föreläsning 6 Programmeringsteknik och Matlab 2D1312/2D1305 Metoder & parametrar Array API och klassen ArrayList.
1 Föreläsning 5 Programmeringsteknik och Matlab 2D1312/2D1305 Repetition Metoder Array API och klassen ArrayList.
Föreläsning 1 Reserverade ord Javas API Identifierare Litteraler Variabler Kompilering och interpretering.
Programmering i C# 9. Pekare och osäker kod.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 2 ( ) INNEHÅLL: -Variabler och datatyper -Tilldelning av variabler -Aritmetiska.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 3 ( ) INNEHÅLL: -Tabeller -Villkorssatser -Repetitionssatser.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 5 ( ) INNEHÅLL: -Metoder.
F4 - Funktioner & parametrar 1 Programmeringsteknik, 4p vt-00 Modularisering ”svarta lådor” Väl definierade arbetsuppgifter Enklare validering Enklare.
31 March 2015IS1200 Datorteknik, förel 101 IS1200 Datorteknik Föreläsning Processorkonstruktion 2. DMA, Direct Memory Access 3. Byte-code i JAVA.
IS1200 Datorteknik Föreläsning CE F2 Vi bygger en processor Kursboken, delar av kapitel 7 31 March IS1200 Datorteknik föreläsning CE – F2.
Föreläsning 4 programmeringsteknik och Matlab 2D1312/ 2D1305
Föreläsning 1 Om kursen Reserverade ord Javas API Identifierare Litteraler Variabler Kompilering och interpretering.
Digitalteknik 7.5 hp distans: 4.6 Adderare 4.45 Adderare Addition av två tal innebär att samma förfarande upprepas för varje position i talet. För varje.
ITK:P1 Föreläsning 2 Introduktion till objektorientering DSV Marie Olsson.
INTRODUKTION TILL PROGRAMMERING
Förskoleenkät Föräldrar 2012 Förskoleenkät – Föräldrar Enhet:Hattmakarns förskola.
OOP F2:1 Stefan Möller OOP Objekt-orienterad programmering Föreläsning 2 Deklaration och tilldelning Programsatser Tilldelning Input/Output Selektion.
Föreläsning 17 Repetition. Källkodsformat Unicode används åäöμψζ tillåtna i namn på identifierare Inte alla miljöer klarar av det Källkod Bytekod Java.
F2 1 Programmeringsteknik, 4p vt-00 Kommentarer Allt mellan /* och */ Varje kommentar byts ut mot en blank av kompilatorn /* Exempel på uttryck, tilldelningsoperatorn.
Programmeringsteknik för K och Media
Kronljusströmställaren 0, 1, 2, 3
-Repetition -Variabler -Primitiva typer (+ boolean) -Operatörer +, ++, --, -Typ konvertering -Wrapper klasser -Jämförelse operatörer,(==, =,,!=, !) -String.
1 Föreläsning 2 Reserverade ord Javas API Identifierare Litteraler Variabler Kompilering och interpretering.
-Repetition -Variabler -Primitiva typer (+ boolean) -Operatörer +, ++, --, -Typ konvertering -Wrapper klasser -Jämförelse operatörer,(==, =,,!=, !) -String.
OOP&M - teori1 OOP – Föreläsning 7 (Sista oop I) Konstruktioner för att hantera upprepningar Kapitel 11.
Anders Sjögren Operatorer. Anders Sjögren Operand(er)
Anders Sjögren Programmering i ANSI-C Ett första program för att se vart vi ska...
Presentationens avskrift:

Maskinnära programmering i C Föreläsning 5 Mats Brorsson

IS1200 Datorteknik Assemblerprogram C In- och utmatning F1 F2 Ö1 F3 Ö2 F4 Ö3 lab nios2time Assemblerprogram C F5 Ö4 hemlab C In- och utmatning F6 Ö5 Ö6 lab nios2io Avbrott och "trap" F7 Ö7 lab nios2int Cacheminnen F8 Ö8 hemlab cache F9 Ö9 hemlab trådar Trådar, synkronisering F10 Ö10 tentamen

Hemlaboration 1: Maskinnära programmering i C Pekare, array, struct, malloc med mera Lab-PM + C-kod på webben, kompilera och kör med valfri C-kompilator Svara på alla frågor, tänk efter: "Varför?" Muntlig redovisning, 2 studenter med 1 lärare Läs http://www.ict.kth.se/courses/IS1200/bokade.txt Mejla till is1200@ict.kth.se och boka Ge alltid flera alternativa tider

C jämfört med andra språk Java objekt, referenser, garbage-collection, byte-code, starkt typsystem C inga objekt, pekare, malloc/free, maskinnära, stöd för enkla datatyper Assembler inga typer alls, adresser, ingen inbyggd felkontroll

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper (struct, array) Satser och block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap Alla exempel med handöversättning till assemblerkod använder Nios II assemblersyntax

Rekommenderad litteratur Häftet "C för den som kan Java" Kan hämtas som PDF, http://www.nada.kth.se/datorer/haften/java2c/ Tips för den som vill läsa ännu mer: Bilting, Skansholm: Vägen till C Kernighan, Ritchie: The C Programming Language Jonas Skeppstedt, Christian Söderberg, Writing efficient C code : a thorough introduction for Java programmers, http://writing-efficient-c-code.com/

C för dig som kan Java main(int argc, char *argv[]) { Datorsystemteknik torsdag den 6 april 2017 C för dig som kan Java Ditt första C-program main(int argc, char *argv[]) { printf(“hello, world\n”); } Samma program i Java: public class Hello { public static void main(String[] args) { System.out.println("Hello World!"); } }

Datatyper i C Mats Brorsson KTH

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Hexadecimala talsystemet Datorsystemteknik torsdag den 6 april 2017 Hexadecimala talsystemet Lär dig denna tabell utantill! Ex: 0110 1000 1010 0001 = 0x68A1 Ett tal som börjar med 0x är i hexadecimal notation

C – inledning Syntaxen liknar Java Körningen börjar med funktionen main Inga funktioner körs om man inte anropar dem "Metoderna" kallas funktioner i C en Java-metod tillhör en klass och modifierar objekt men C har inga klasser och inga objekt

C – inledning Inga referenser, men pekare en pekare är en minnesadress med viss typkontroll kraftfullt, men lätt att göra fel Inga objekt, men poster: struct som objekt utan metoder, innehåller bara data Ingen "new", ingen garbage-collection biblioteksfunktionen malloc reserverar minne reserverat minne måste återlämnas med free

Deklaration av variabeltyp Definition av variabelvärde Typ-deklaration, så att kompilatorn kan typkontrollera programmet Definition, en deklaration som medför att kompilatorn reserverar minnesutrymme Initiering, en definition där programmeraren anger variabelns startvärde int foo = 17;

Deklaration och definition int a; /* Deklaration och definition, kompilatorn reserverar plats i minnet för variabeln a */ int b = 17; /* Definition med initiering, kompilatorn reserverar plats och lägger in startvärdet */ int b; /* Deklaration igen, anger samma typ, tillåtet! */ int b = 85; /* Ny definition, förbjudet! */

Datatyper Kombinationstyper: Grundtyper: array heltal struct flyttal union (ej behandlat här) Grundtyper: heltal flyttal

Datatyper: heltal signed char short int long long long unsigned char unsigned short unsigned int unsigned long unsigned long long minst 8 bit minst 16 bit minst 16 bit (oftast 32 bit) minst 32 bit minst 64 bit C99 5.2.4.2.1 sida 21-23 Filen limits.h ger värden för aktuell kompilator #include <limits.h> Exempel: INT_MAX kan ha värdet 2147483647

Exempel: gcc 3.4.6 för Nios II (Nios II har 32-bits adresser) char short int long long long float double 8 bit (1 byte) 16 bit (2 byte) 32 bit (4 byte) 64 bit (8 byte) minst 8 bit minst 16 bit minst 32 bit minst 64 bit

Exempel: gcc 4.4.3 för amd64 (AMD64 har 64-bits adresser) char short int long long long float double 8 bit (1 byte) 16 bit (2 byte) 32 bit (4 byte) 64 bit (8 byte) minst 8 bit minst 16 bit minst 32 bit minst 64 bit

sizeof() Operatorn sizeof( någonting ) ersätts vid kompileringen med en konstant som är lika med storleken i bytes för den typ som någonting har Exempel long long fsize = sizeof( float ); Annat exempel double r; long long dsize = sizeof( r );

Heltal: unsigned 1001 1111 0101 0000 1111 0111 0111 0000 Hexadecimalt: 9f 50 f7 70 i C: 0x9f50f770 Tolkas som positivt heltal (2 672 883 568)

Heltal: signed 1001 1111 0101 0000 1111 0111 0111 0000 Hexadecimalt: 9f 50 f7 70 i C: 0x9f50f770 Teckenbiten (längst till vänster) är ettställd Tolkas som negativt heltal (-1 622 083 728)

Binärkod för värdet minus ett Koden för + 1 0000 0000 .... 0001 Bitvis invertering 1111 1111 .... 1110 Addition av ett + 0000 0000 .... 0001 Och vi får kod för -1 1111 1111 .... 1111 (Koden för -1 är alltid ”bara ettor” för alla ordlängder)

Värdet av kod för negativt tal Koden för negativt tal 1111 .... 1010 0101 Bitvis invertering 0000 .... 0101 1010 Addition av ett + 0000 .... 0000 0001 Och vi får kod 0000 .... 0101 1011 Som tolkas till värdet 64+16+8+2+1 = 91 Alltså -91

Snabbfrågor Omvandla följande decimala tal till 32-bitars tal i tvåkomplementrepresentation: 512 -1023 -4000000 Skriv talen i hexadecimalt format

Byte-ordning i minnet: little-endian, skrivning little-endian byte-order adress 0 1001 1111 0101 0000 1111 0111 0111 0000 . . . 0111 0000 1111 0111 0101 0000 1001 1111 (lilla änden först i minnet) . . . adress 2n-1

Byte-ordning i minnet: big-endian, läsning adress 0 big-endian byte-order . . . 0111 0000 1111 0111 0101 0000 1001 1111 0111 0000 1111 0111 0101 0000 1001 1111 (stora änden först i minnet) . . . adress 2n-1

Datatyper: flyttal: approximation av reella tal float double long double Oftast 32 bitar (IEEE 754 ) Oftast 64 bitar (IEEE 754 ) ”Mer än double” 80 bit eller (IEEE 754 quad precision) Filen float.h ger värden för aktuell kompilator #include <float.h> Exempel: FLT_MAX kan ha värdet 340282346638528859811704183484516925440.000000 C99 5.2.4.2.2 sida 23-28

Decimalt flyttal -047,120 decimalt fixtal -04,7120 * 101 samma flyttal tecken mantissa exponent

Binärt flyttal -0101.110 binärt fixtal -0101,110 * 20 binärt flyttal -01,01110 * 22 normaliserat flyttal exponent tecken mantissa

Binärt flyttal: float (32 bit) -0101,110 binärt fixtal -0101,110 * 20 binärt flyttal -01,01110 * 22 normaliserat flyttal exponenten lagras med 8 bit i excess-127-kod tecken: 1:a för negativa tal bara bråksiffrorna av mantissan lagras, men inte "1,"

Binärt flyttal: double (64 bit) -0101,110 binärt fixtal -0101,110 * 20 binärt flyttal -01,01110 * 22 normaliserat flyttal tecken: 1:a för negativa tal bara bråksiffrorna av mantissan lagras, men inte "1," exponenten lagras med 11 bit i excess-1023-kod

Flyttal IEEE 754, 32 bitar FLOAT: 1 10000011 00010000000000000000000 s exp mantissabitar värde = (–1)s * (1 + mantissabitar2 ) * 2 (exp–127) –17 (dec) = –1 0001 (bin) = – 1,0001 * 24 1 1000 0011 000 1000 0000 0000 0000 0000 1100 0001 1000 1000 0000 0000 0000 0000 0x C 1 8 8 0 0 0 0

Algoritm för omvandling till flyttal Antag ett decimalt flyttal: -4,7120 * 1023 = -0,47120 * 1024 Omvandla till -1t * 1.M2 * 2(e-127) Bestäm t, M och e så att följande villkor är uppfyllda: 1.M2* 2(e-127) = 4,712010 * 1023 M10 < 1,0 M2 < 1.0 e är ett heltal 1. Antag M = 0 och bestäm exponent, x = e-127 4,7120 *1023 = 2x log(4,7120 * 1023) = log(2x) log(4,7120) + 23 = x*log(2) x = (23+ log 4,712 ) /log⁡(2) =78 e = 78+127 = 205 = 0xcd = 0b1100 1101 Lös ut M från ekvationen: 1.M*278 = 4,712*1023 1.M = 4,712*1023/278 = 1,5590700185399465615976311028135 M = 1000 1111 0001 1111 0011 011 IEEE-talet är: 1 1100 1101 1000 1111 0001 1111 0011 011

Varför Excess-127/1023? För då kan man använda heltalsinstruktioner för att avgöra vilket tal som är störst

Information, 32 bitar adress / värde Little endian byte ordering FLOAT: 0xC1 0x88 0x00 0x00 - + 0x00 0x00 0x88 0xC1 -17 i float-format: 0x C1 88 00 00

Flyttal IEEE 754, 64 bitar DOUBLE: 1 10000000011 000100 ... 000000000 s exponent mantissabitar (-1)s * (1 + mantissabitar2 ) * 2 (exponent-1023) -17 (dec) = - 1 0001 (bin) = - 1.0001 * 24 1 100 0000 0011 000 1000 0000 ... 0000 1100 0000 0011 0001 0000 0000 ... 0000 0x C 0 3 1 0 0 0 0 0 0 0 0 0 0 0 0

Information, 64 bitar adress / värde Little endian byte ordering DOUBLE: 0x31 0xC0 0x00 0x00 - + 0x00 0x00 0x00 0x00 0x00 0x00 0x31 0xC0 -17 i double-format: 0x C0 31 00 00 00 00 00 00

Snabbfrågor Omvandla följande till 32-bitars binärkod i hexadecimalt format: Instruktionen add r12,r1,r3 Heltalet 147425338 Det reella talet 1,3092239146306080983655304890341 * 10-33

Addition/subtraktion av flyttal Datorsystemteknik torsdag den 6 april 2017 Addition/subtraktion av flyttal Algoritm: 1. Jämför de båda talens exponenter. Skifta det minsta talets signifikand (inkl. implicit etta) till höger så att de båda talens exponenter blir lika stora 2. Addera/subtrahera signifikanderna 3. Normalisera summan 4. Om det blir exponent overflow är det aritmetiskt fel 5. Avrunda signifikanden 6. Om avrundningen medför att talet blir onormaliserat, gå till steg 3

Multiplikation av flyttal Datorsystemteknik torsdag den 6 april 2017 Multiplikation av flyttal Algoritm: 1. Addera exponenterna och dra ifrån en excess 2. Multiplicera signifikanderna 3. Normalisera produkten 4. Om det blir exponent overflow är det aritmetiskt fel 5. Avrunda signifikanden 6. Om avrundningen medför att talet blir onormaliserat, gå till steg 3 7. Beräkna produktens tecken

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Mer komplicerade datatyper i C Mats Brorsson KTH

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Arrayer En array i C har alltid fix storlek Deklarationen int vektor[27]; reserverar plats för 27 heltal i en array Numreringen börjar på noll vektor[0] vektor[1] ... vektor[26] /* Nu är det slut! */

Array i minnet Heltals-vektor Resultat i minnet (little-endian) adress 0 Heltals-vektor int v[27]; v[0] = 1234; v[1] = 4711; Resultat i minnet (little-endian) 1 byte adress för v[0]: 0x800b70 0xd2 0x04 1234 (decimalt) = 0x000004d2 (hex) 0x00 0x00 och här kommer v[1]: 0x800b74 0x67 0x12 4711 (decimalt) = 0x00001267 (hex) 0x00 0x00 adress för v[2]: 0x800b78 . . . adress 0xffffffff

Matriser Matriser finns inte som egen typ, utan görs som arrayer av arrayer Deklarationen int matris[17][42]; ger plats för 17 rader med 42 heltal i varje rad Numreringen börjar på noll matris[0][0] matris[0][1] ... matris[16][41] /* Nu är det slut! */ För dynamiskt allokerade matriser är det lite mer krångligt.

Matriser, mera detaljer Lagring i minnet matris[0][0] matris[0][1] ... matris[0][41] matris[1][0] matris[1][1] ... matris[1][41] matris[2][0] ... och så vidare till matris[16][41] Först hela rad 0 Sedan hela rad 1 Och sen hela rad 2 ... Kallas radvis lagring Eng. Row major ordering Fortran har Column major ordering

Bokstäver och strängar Tecknet 'A' är ett litet heltal (65) En char använder 1 byte i minnet, och har plats för ett litet heltal (exempelvis 65) En array of char har plats för en sträng: char s[20]="Now you C a string."; Strängar slutar med en nollställd char (’\0’) som slutmarkör Exempel: "hej" == { 'h', 'e', 'j', '\0' }

Handöversättning till assembler C: char s[20]="Now you C a string."; Assembler: .data .global s s: .asciz "Now you C a string."

Obs! Exempel på adresser. I minnet (exempel) Exempel i C: char c = 'Q'; int x = 4711; Assembler: .data .global c c: .byte 'Q' .align 2 .global x x: .word 4711 adress 0 1 byte adress för c: 0x800b62 0x51 Obs! Exempel på adresser. adress för x: 0x800b64 0x67 0x800b65 0x12 0x800b66 0x00 0x800b67 0x00 4711 (decimalt) = 0x00001267 (hex) adress 0xffffffff

Snabbfrågor Följande sträng finns på adress 0x80740 i minnet: char s = ”Nu ska vi C!”; Vilken adress har nästa lediga plats? 0x8074D 0x8074E 0x80750 Om strängen omedelbart följs av nedanstående definition, vilken adress läggs den på? double d;

I stället för objekt: struct En struct liknar ett objekt, fast utan metoder Objektet innehåller del-variabler (oftast flera) Del-variablerna är ofta av olika typer Steg 1: deklarera en struct-typ Steg 2: deklarera en variabel av den typen Steg 3: tilldela en del-variabel ett värde

struct-exempel användning: struct threadinfo { int sp; int id }; deklarerar en ny typ, struct threadinfo denna struct-typ innehåller två heltal struct threadinfo thisthread; deklarerar en variabel av typ struct threadinfo användning: thisthread.id = 4711; tilldelar ena heltalet i variabeln thisthread

Handöversättning till assembler C: struct threadinfo thisthread; Assembler: .data .align 2 .global thisthread thisthread: .word 0 .word 0

Handöversättning till assembler C: thisthread.id = 4711; Assembler: .text .align 2 movia r8,thisthread movi r9,4711 stw r9,4(r8) # id finns efter sp som tar 4 byte

Obs! Exempel på adresser. I minnet (exempel) adress 0 1 byte De två del-variablerna i en struct ligger efter varandra i minnet Ordningen är alltid samma som i C-programmet thisthread: 0x800b90 0x00 sp 0x800b91 0x00 0x800b92 0x00 0x800b93 0x00 0x800b94 0x67 id 0x800b95 0x12 0x800b96 0x00 0x800b97 0x00 Obs! Exempel på adresser. adress 0xffffffff

Kopiering av hela structen struct threadinfo { int sp; int id }; struct threadinfo thisthread; struct threadinfo otherthread; användning: otherthread = thisthread; Hela variabeln thisthread (alla delar) kopieras till variabeln otherthread Fungerar bara med struct, inte med array!

Kopiering av hela structen struct threadinfo { int sp; int id }; struct threadinfo thisthread; struct threadinfo otherthread; användning: otherthread = thisthread; Hela variabeln thisthread (alla delar) kopieras till variabeln otherthread Fungerar bara med struct, inte med array! Hur många load- och storeinstruktioner behövs för att genomföra kopieringen till vänster? 1 load och 1 store 2 load och 2 store 4 load och 4 store

Men... finns det inga Boolean? Heltal i stället för Boolean Heltalet 0 tolkas som "falskt" Alla heltal ≠ 0 tolkas som "sant" if( heltalsuttryck ) statement1; else statement2;

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Uttryck, Satser och Block i C Mats Brorsson KTH

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Datorsystemteknik torsdag den 6 april 2017 If-satser

Datorsystemteknik torsdag den 6 april 2017 Relationsoperatorer

Datorsystemteknik torsdag den 6 april 2017 Repetitionsslingor

For-loopen Notera, for-loopen med följande struktur: for (i=0; i < N; i = i + 1) { … } Är detsamma som: i = 0; while (i < N) { i = i + 1;

Heltal i stället för Boolean if( heltalsuttryck ) statement1; else statement2; Exempel på heltalsuttryck: a < b Om a < b så är uttryckets värde 1, annars 0 Kan tilldelas variabler: int a_is_smaller_than_b = a < b; Motsvarande för while, for, ... while( heltalsuttryck ) statement2; for( init; heltalsuttryck; update ) statement3;

Ett komplett program #include <stdio.h> int n; p(int k) { Datorsystemteknik torsdag den 6 april 2017 Ett komplett program Genom direktivet include kan man göra sina program mer lättlästa. #include <stdio.h> int n; p(int k) { printf(“n = %d\n”, k) } int f(int a) { int b; b = a + 2; return b; /* Huvudprogram */ #define PARAMETER 10 main(){ n = f(10); p(n); } #define är ett sätt att definiera konstanter. Namnet main betyder huvudprogram Parametrar till funktioner och subrutiner deklareras på samma sätt som variabler Du har möjlighet att deklarera variabler inne i en funktion/subrutin return används för att avsluta en funktion och för att tala om vad som är returvärdet

Struktur C-programfil: #include #define deklaration av globala variabler funktioner Varje funktion: deklaration av namn, parametrar och returvärde en sats (statement) eller ett block vanligtvis ett block, förstås...

Stil: korthuggen programkod Utskrift av sträng int i; char s[20]; for( i = 0; s[i]; i = i + 1 ) putchar( s[i] ); Uttrycket s[i] är ett heltalsuttryck Alla heltal utom 0 räknas som "sant" Testet s[i] är sant när heltalet s[i] ≠ 0 men falskt när s[i] == 0 eftersom strängens slutmarkör är heltalet noll Svårläst och det är bättre att skriva villkoret som s[i] != NULL där NULL definierats till ’\0’.

Satser Satser kan vara if-satser etc, förstås En sats kan också bestå av ett uttryck En tilldelning är ett uttryck som ofta finns ensamt i en sats Exempel: x = 4711 är ett uttryck Sätt semikolon ; efter uttrycket så får vi en sats x = 4711;

Varning för oväntad tilldelning = betyder tilldelning == betyder test för likhet Satsen if( x == 4711 ) y = 32767; ändrar y, om x är lika med 4711 Satsen if( x = 4711 ) y = 32767; medför alltid att y ändrar värde. Varför?

Snabbfrågor Hur många repetitioner kommer följande slinga exekvera? char teckenstr = ”aaaaaaabbbbbcc”; i = 0; tecken = teckenstr[0]; while (tecken = ’a’) { // behandla tecknet a … tecken = teckenstr[i++]; } 1 gång 7 gånger Oändligt antal

Block En sats (statement) kan alltid bytas mot ett block Uttryck kan inte bytas mot block C99 och senare standarder kan blanda deklarationer och satser Block: { deklarationer först i varje block satser efter alla deklarationer }

Exempel: utskrift av sträng En kort funktion void printstring( char s[] ) { /* nytt block */ int i; /* deklarationer först i blocket */ for( i = 0; s[i]; i = i + 1 ) { putchar( s[i] ); } } nytt block omkring putchar, onödigt men mer lättläst

Bitvisa operationer i C Ettställ valda bitar med OR-operation tmp = tmp | 0x30 ; Nollställ valda bitar med AND-operation (maska fram utvalda bitar) tmp = status & 0x0F ; Invertera valda bitar med XOR-operation tmp = val ^ 0x80;

Bit Operations Assembly program (Nios-II) Skifta höger n steg (heltalsdivision med 2n) SRLI r2, r7, n # det finns även SRAI r2, r7, n Skifta vänster m steg (multiplikation med 2m) SLLI r9, r4, m # det finns ingen SLAI r9, r4, m Olika hantering av teckenbiten vid högerskift SRLI skiftar in 0 SRAI skiftar in teckenbiten

Bit Operations C-program Skifta höger n steg (heltalsdivision med 2n) tmp = tmp >> n ; Skifta vänster m steg (multiplikation med 2m) tmp = tmp << m ; Oftast implementeras högerskift som: unsigned int tmp => skifta in noll vid högerskift int tmp => skifta in teckenbiten vid högerskift

Bitwise operations Logical operations A & B bitvis AND A | B bitvis OR A ^ B bitvis XOR ~A bitvis NOT (invertering) A && B logisk AND A || B logisk OR !A logisk NOT Notera INGEN operator ^^ i C (INGEN logisk XOR)

Snabbfrågor Du har läst in ett tecken från en I/O-enhet genom att läsa in till en variabel med följande definition: int tecken; Hur ska du förbehandla det för att kunna göra följande? if (tecken == 0x41) Välj mellan tecken = tecken & 0xff; tecken = tecken && 0xff; tecken = tecken | 0xff; tecken = tecken || 0xff;

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Pekare och pekararitmetik i C Mats Brorsson KTH

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Obs! Bara exempel på adresser. Pekare En pekare är en sorts variabel Pekaren innehåller en adress Exempel int valle; int * pelle; pelle = &valle; *pelle = 17; adress 0 4 byte pelles adress 0x800b60 0x800b98 Obs! Bara exempel på adresser. valles adress 0x800b98 17 adress 0xffffffff

Pekar-operatorer Tilldela pekaren en adress pelle = &valle; Operatorn & (med en variabel som argument) betyder "minnesadressen till" variabeln Varning: genom att ta adressen till en variabel förindrar man att kompilatorn kan allokera den i ett register Följ pekaren och skriv *pelle = 17; Operatorn * (med en pekare som argument) betyder "pekarens innehåll är adressen till en plats i minnet där läsning/skrivning ska göras"

Exempel på handöversättning adress 0 int valle; int * pelle; Assembler .data .align 2 .global valle valle: .word 0 .data .align 2 .global pelle pelle: .word 0 4 byte pelles adress 0x800b60 valles adress 0x800b98 adress 0xffffffff

Handöversättning till assembler C pelle = &valle; Assembler .text .align 2 movia r8,valle movia r9,pelle stw r8,0(r9) adress 0 4 byte pelles adress 0x800b60 valles adress 0x800b98 adress 0xffffffff

Steg för steg: pelle = &valle; Assembler .text .align 2 movia r8,valle adress 0 4 byte pelles adress 0x800b60 valles adress 0x800b98 r8 r8 0x800b98 r9 adress 0xffffffff

Steg för steg: pelle = &valle; Assembler .text .align 2 movia r8,valle movia r9,pelle adress 0 4 byte pelles adress 0x800b60 valles adress 0x800b98 r8 r8 0x800b98 r9 0x800b60 adress 0xffffffff

Steg för steg: pelle = &valle; Assembler .text .align 2 movia r8,valle movia r9,pelle stw r8,0(r9) adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 r8 r8 0x800b98 r9 0x800b60 adress 0xffffffff

Handöversättning till assembler C *pelle = 17; Assembler .text .align 2 movia r8,17 movia r9,pelle ldw r10,0(r9) stw r8,0(r10) adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 adress 0xffffffff

Steg för steg: *pelle = 17; Assembler: .text .align 2 adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 r8 r8 r9 r10 adress 0xffffffff

Steg för steg: *pelle = 17; Assembler: .text .align 2 movia r8,17 adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 r8 r8 17 r9 r10 adress 0xffffffff

Steg för steg: *pelle = 17; Assembler: .text .align 2 movia r8,17 movia r9,pelle adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 r8 r8 17 r9 0x800b60 r10 adress 0xffffffff

Steg för steg: *pelle = 17; Assembler: .text .align 2 movia r8,17 movia r9,pelle ldw r10,0(r9) adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 r8 r8 17 r9 0x800b60 r10 0x800b98 adress 0xffffffff

Steg för steg: *pelle = 17; Assembler: .text .align 2 movia r8,17 movia r9,pelle ldw r10,0(r9) stw r8,0(r10) adress 0 4 byte pelles adress 0x800b60 0x800b98 valles adress 0x800b98 17 r8 r8 17 r9 0x800b60 r10 0x800b98 adress 0xffffffff

Pekartyper Exempel: pointer to char pointer to int pointer to double pointer to struct h men struct h ska förstås vara definierad tidigare char * cp; int * ip; double * dp; struct h * hp;

Storlekar Hur stor är pekarvariabeln? struct h { int v1; int v2; char s[20]; }; struct h * hp; printf( "hp: %ld \n", sizeof( hp ) ); En adress är alltid lika stor (som andra adresser) Hur stor är den typ som pekarvariabeln är deklarerad att peka på? printf( "*hp: %ld \n", sizeof( *hp ) ); Väldigt olika för olika typer

Test: sizeof( hp ) och sizeof( *hp ) C-program #include <stdio.h> int main() { struct h { int v1; int v2; char s[20]; }; struct h * hp; printf( "hp: %ld \n", sizeof( hp ) ); printf( "*hp: %ld \n", sizeof( *hp ) ); return( 0 ); } Utmatning hp: 8 *hp: 28

Void Typen void är speciell, betyder "inget värde" En funktion utan returvärde har returtypen void void puttime( int mytime ) En funktion utan parametrar kan skrivas med void (eller utlämnas) int getchar( void ) En voidpekare (pointer to void) får peka på objekt av vilken typ som helst En voidpekare får inte följas/avrefereras

Voidpekare int tal; int * ip; void * vp; vp = (void *) &tal; /* voidpekaren får adressen till tal */ (void *) kallas ”type cast” och gör att man kan göra om typer GÖR DETTA ENBART NÄR DU VET EXAKT VAD SOM HÄNDER! *vp = 17; /* avreferera voidpekare med tilldelning av heltal, fel! */ ip = (int *) vp; /* läs vp med type cast */ *ip = 17; /* avreferera int-pekare, går bra */ *( (int *) vp ) = 4711; /* krångligt men korrekt */

Snabbfrågor Antag följande definitioner: int *p; int i; int k; i = 42; k = i; p = &i; Vilka av följande kommer ändra på variabel i till 75? k = 75; *k = 75; p = 75; *p = 75; Två eller fler av svaren ovan kommer ändra i till 75

byte-vektor, textsträng, char [ ] En vektor av bytes char text[14] = "Hello, world!"; /* 14 bytes, kom ihåg nolltecknet på slutet! */ med index 0 – 13 &text[0] – adress till första tecknet, pointer to char text – också adress till första tecknet, pointer to char

bytevektor, pointer to char char text[14] = "Hello, world!"; /* 14 bytes, kom ihåg nolltecknet på slutet! */ char * cp1 = &text[0]; *cp1 = 'Y'; Nu är strängen "Yello, world!" char * cp2 = text; *cp2 = 'C'; Nu är strängen "Cello, world!"

Lagring av textsträng, char [ ] adress 0 1 byte text[0] 'H' C-kod: char text[] = ”Hello, world!”; Assemblerkod: .data text: .asciz ”Hello World!” 'e' 'l' 'l' 'o' ',' ' ' 'w' 'o' 'r' 'l' 'l' 'd' '!' text[13] 0x00 adress 0xffffffff

Pekar-aritmetik: char char text[14] = "Hello, world!"; /* 14 bytes, kom ihåg nolltecknet på slutet! */ char * cp1 = &text[0]; cp1 = cp1 + 1; Nu är cp1 adressen till 'e' *cp1 = 'u'; Nu är strängen "Hullo, world!"

Pekar-aritmetik: int (överkurs) int v[27]; v[0] = 1234; int * ip = &v[0]; ip = ip + 1; *ip = 65535; Ökas med 1 i C-kod, men ökas med 4 i assembler! Skalning med sizeof(int) adress 0 1 byte adress för v[0]: 0x800b70 0xd2 0x04 1234 (decimalt) = 0x000004d2 (hex) 0x00 0x00 och här kommer v[1]: 0x800b74 0xff 0xff 65535 (decimalt) = 0x0000ffff (hex) 0x00 0x00 adress för v[2]: 0x800b78 . . . adress 0xffffffff

memcpy i C-kod (block data transfer) void memcpy (void * dst, void * src, int num) { int i; char * localdst = (char *) dst; char * localsrc = (char *) src; for (i=0; i<num, i=i+1) { *localdst = *localsrc; localdst = localdst + 1; localsrc = localsrc + 1; } }

memcpy i C-kod (block data transfer) void memcpy (void * dst, void * src, int num) { int i; char * localdst = (char *) dst; char * localsrc = (char *) src; for (i=0; i<num, i=i+1) { *localdst++ = *localsrc++; /* Svårläst! Undvik operatorn ++ */ } }

Matriskopiering i C #define ROWSIZ 17 #define COLSIZ 27 int enamatrisen[ROWSIZ][COLSIZ]; int andramatrisen[ROWSIZ][COLSIZ]; void matcpy (int* dst, int* src) { int i, j; for (i=0; i<ROWSIZ, i=i+1) /* rad-nr */ for (j=0; j<COLSIZ, j=j+1) /* kolumn-nr */ dst[i][j] = src[i][j]; }

Omvänd ordning på rader och kolumner: blir det någon skillnad? #define ROWSIZ 17 #define COLSIZ 27 int enamatrisen[ROWSIZ][COLSIZ]; int andramatrisen[ROWSIZ][COLSIZ]; void matcpy (int* dst, int* src) { int i, j; for (j=0; j<COLSIZ, j=j+1) /* kolumn-nr */ for (i=0; i<ROWSIZ, i=i+1) /* rad-nr */ dst[i][j] = src[i][j]; }

Omvänd ordning på rader och kolumner Adressberäkning För att hitta dst[i][j] ska datorn beräkna (i * ROWSIZ + j) * elementstorleken och addera det till startadressen för matrisen Används matrisen radvis, i samma ordning som lagringen, så kan kompilatorn ta bort adressberäkningen Adderar elementstorleken sizeof(int) till adresserna inför varje ny iteration

Pekare för att komma åt I/O-enheter I/O-enheter är avbildade i adressrymden precis som variabler. De är speciella eftersom t.ex. en In-enhet kan ändra värde mellan två läsningar En Ut-enhet kan ta emot flera värden efter varandra Exempel: Ut-enhet som tänder/släcker lysdioder (LEDs) beroende på bitvärde In-enhet där man kan se hur ett antal strömbrytare är satta

Enkel I/O-programmering i C #define LED 0x4408 // fiktiv adress #define SWITCH 0x440C // också fiktiv adress unsigned int *switches = SWITCH; unsigned int *leds = LED; int swtch_temp; // Läs inporten och mata ut till LED swtch_temp = *switches; // läs switch swtch_temp = 0x3ff; // 18 minst signifikanta *leds = swtch_tmp; // tänd/släck leds

Snabbfrågor Antag följande kod: unsigned char *inport = PORT_ADDRESS; while ((*inport & 0x80) && (i<100)) { while (!(*inport & 0x80)) ; tecken[i++] = (*inport & 0x7f); } Hur många iterationer exekverar den yttre slingan? 0 gånger, villkoret kan aldrig vara sant 1 gång, den fastnar i den inre slingan Det går inte att fastställa men max 100 gånger 100 gånger

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Lagring av globala och lokala variabler Mats Brorsson KTH

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap

Variabler i minnet (register) Viktiga aspekter att ta med Allokering av minne vid kompilering at compile-time Allokering av minne vid exekvering at run-time global / lokal variabel code-area, data-area, heap-area, stack-area push och pop för stacken malloc() och free() för heapen

Statisk allokering av minne at compile time Vid kompilering+länkning reserveras minne för Programkoden – text Globala data initialized (.data) uninitialized (.bss) (Block Started by Symbol) Heap-area Stack-area

Minnesuppdelning program- kod data bss heap data bss stack adress 0 adress 2n-1 Exempel 1 Exempel 2 data bss PC SP

Programstart körbar fil minne header program- kod kopiering vid programstart program- kod data bss data symboltabell heap

Dynamisk allokering av minne at execution/run -time Vid exekvering allokeras minne på stack och används för Parametrar vid funktionsanrop Returadress vid funktionsanrop Lokala variabler i anropad funktion Skydd av register vid registerbrist (r16 – r23)

Dynamisk allokering av minne at execution/run time Vid exekvering allokeras minne på heap och används för Dynamiska data-strukturer

malloc() och free() dynamisk allokering på heap /* Tänkbar bakgrund */ struct elephant { char[13] name; /* 16 bytes ? ! */ int weight; /* 4 bytes */ double area; /* 8 bytes */ } ; struct elephant dumbo;

malloc() och free() dynamisk allokering på heap struct elephant * ep; ... ep = (struct elephant *) malloc (sizeof (struct elephant)); * ep = dumbo; free (ep); /* ep MÅSTE ha samma värde som från malloc */

Snabbfrågor Vilken eller vilka av följande allokeringar gör vad du troligen vill givet deklarationen? struct node { int key; struct node * next; }; struct node * x = malloc(sizeof(*x)); struct node * x = malloc(sizeof(* struct node )); struct node * x = malloc(sizeof(struct node));

Lokala variabler Deklareras i ett block Tillgänglig endast i samma block som deklarationen Startvärdet skrivs när funktionen anropats Anger man inget startvärde så blir startvärdet odefinierat Exempel #include <stdio.h> int main() { int g = 4711; printf( "g: %d \n", g ); g = 17; printf( "g: %d \n", g ); return( 0 ); } Utmatning g: 4711 g: 17

Globala variabler Deklareras utanför alla funktioner Tillgängliga i alla funktioner Startvärde lagras i körbar fil ("exe-filen") Anger man inget startvärde så blir startvärdet noll Utnyttja inte detta! Svårläst kod Exempel #include <stdio.h> int g = 4711; int main() { printf( "g: %d \n", g ); g = 17; printf( "g: %d \n", g ); return( 0 ); } Utmatning g: 4711 g: 17

Deklaration av global variabel: kompilering på riktigt C #include <stdio.h> int g = 4711; /* global */ int main() { printf( "g: %d \n", g ); g = 17; printf( "g: %d \n", g ); return( 0 ); } Förväntad kompilering .global g .data .align 2 g: .word 4711 Verklig kompilering .global g .section .sdata,"aws",@progbits .align 2 .type g, @object .size g, 4 g: .long 4711 Ger mer hjälpsam info till länkningen

Minnesdisposition (minnes-karta) Programkod .text Globala data .data (indelad i fler delar) Dynamiska data Stack PC program- kod adress 0 data heap SP stack adress 2n-1 Unix v7

Globala variabler: hur funkar det? Lagras i data-arean Global Pointer GP GP innehåller adress till första globala variabeln Exempel #include <stdio.h> int valle; int * pelle; int main() { pelle = &valle; *pelle = 17; printf( "valle: %d \n", valle ); return( 0 ); }

Handöversättning till assembler REPRIS Handöversättning till assembler int valle; int * pelle; Assembler .data .align 2 .global valle valle: .word 0 .data .align 2 .global pelle pelle: .word 0 adress 0 4 byte pelles adress 0x800b60 valles adress 0x800b98 adress 0xffffffff

Handöversättning till assembler int valle; int * pelle; Assembler .data .align 2 .global valle valle: .word 0 .data .align 2 .global pelle pelle: .word 0 adress 0 4 byte Obs! Realistiska exempel på adresser. gp innehåller 0x800b90 valles adress 0x800b94 pelles adress 0x800b98 r26/gp 0x800b90 adress 0xffffffff

Handöversättning till assembler int main() { Assembler .text .align 2 .global main main: adress 0 4 byte gp innehåller 0x800b90 valles adress 0x800b94 pelles adress 0x800b98 gp 0x800b90 adress 0xffffffff

Handöversättning till assembler C pelle = &valle; Assembler addi r2,gp,4 stw r2,8(gp) adress 0 4 byte gp innehåller 0x800b90 valles adress 0x800b94 pelles adress 0x800b98 gp 0x800b90 adress 0xffffffff

Steg för steg Assembler addi r2,gp,4 Resultat: r2 = 0x800b94 pelle = &valle; Assembler addi r2,gp,4 Resultat: r2 = 0x800b94 Assembler stw r2,8(gp) Skriver 0x800b94 till det minnesord som har adress gp+8 adress 0 gp 0x800b90 4 byte gp innehåller 0x800b90 valles adress 0x800b94 pelles adress 0x800b98 0x800b94 adress 0xffffffff

Kompilering på riktigt Handöversättningen av pelle = &valle är addi r2,gp,4 stw r2,8(gp) Kompilering ger addi r2, gp, %gprel(valle) Om valles adress är gp+4 så översätts %gprel(valle) till 4 stw r2, %gprel(pelle)(gp) Är pelles adress gp+8 så är %gprel(pelle) 8 och denna rad blir stw r2,8(gp)

Handöversättning till assembler C *pelle = 17; Assembler ldw r3,8(gp) movi r2,17 stw r2,0(r3) adress 0 4 byte gp innehåller 0x800b90 valles adress 0x800b94 pelles adress 0x800b98 0x800b94 gp 0x800b90 adress 0xffffffff

Steg för steg Läs pekarens värde (innehållet i pelle) ldw r3,8(gp) Lägg 17 i ett register movi r2,17 Skriv (följ pekaren) stw r2,0(r3) adress 0 4 byte r2 17 (2) r3 0x800b94 (1) gp innehåller 0x800b90 valles adress 0x800b94 17 (3) 0x800b94 pelles adress 0x800b98 r26 0x800b90 adress 0xffffffff

Kompilering på riktigt Handöversättningen av *pelle = 17 är ldw r3,8(gp) movi r2,17 stw r2,0(r3) Kompilering ger ldw r3, %gprel(pelle)(gp) movi r2, 17 stw r2, 0(r3) %gprel(pelle) är 8 i vårt exempel

Testkod med många parametrar Börjar här #include <stdio.h> int fun(int,int,int,int,int,int); int main() { int r; r = fun( 1, 2, 3, 4, 5, 6 ); printf( "result = %d\n", r ); return( 0 ); } Funktionen fun finns i en annan fil

Den här föreläsningen Enkla datatyper och datarepresentation: Heltal, flyttal, Mer komplicerade datatyper Uttryck, satser, block Pekare, pekar-aritmetik Lagring av globala och lokala variabler Stack Heap