Presentation laddar. Vänta.

Presentation laddar. Vänta.

Maskinnära programmering i C

Liknande presentationer


En presentation över ämnet: "Maskinnära programmering i C"— Presentationens avskrift:

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

2 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

3 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 Mejla till och boka Ge alltid flera alternativa tider

4 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

5 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

6 Rekommenderad litteratur
Häftet "C för den som kan Java" Kan hämtas som PDF, 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,

7 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!"); } }

8 Datatyper i C Mats Brorsson KTH

9 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

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

11 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

12 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

13 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;

14 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! */

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

16 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 C sida 21-23 Filen limits.h ger värden för aktuell kompilator #include <limits.h> Exempel: INT_MAX kan ha värdet

17 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

18 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

19 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 );

20 Heltal: unsigned Hexadecimalt: 9f 50 f7 70 i C: 0x9f50f770 Tolkas som positivt heltal ( )

21 Heltal: signed Hexadecimalt: 9f 50 f7 70 i C: 0x9f50f770 Teckenbiten (längst till vänster) är ettställd Tolkas som negativt heltal ( )

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

23 Värdet av kod för negativt tal
Koden för negativt tal Bitvis invertering Addition av ett Och vi får kod Som tolkas till värdet = 91 Alltså -91

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

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

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

27 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 C sida 23-28

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

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

30 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,"

31 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

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

33 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, * 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 = = 205 = 0xcd = 0b Lös ut M från ekvationen: 1.M*278 = 4,712*1023 1.M = 4,712*1023/278 = 1, M = IEEE-talet är:

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

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

36 Flyttal IEEE 754, 64 bitar DOUBLE: s exponent mantissabitar (-1)s * (1 + mantissabitar2 ) * 2 (exponent-1023) -17 (dec) = (bin) = * 24 0x C

37 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 C

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

39 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

40 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

41 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

42 Mer komplicerade datatyper i C
Mats Brorsson KTH

43 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

44 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! */

45 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) = 0x (hex) 0x00 0x00 adress för v[2]: 0x800b78 . . . adress 0xffffffff

46 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.

47 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

48 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' }

49 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."

50 Obs! Exempel på adresser.
I minnet (exempel) Exempel i C: char c = 'Q'; int x = 4711; Assembler: .data .global c c: .byte 'Q' .align 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) = 0x (hex) adress 0xffffffff

51 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;

52 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

53 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

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

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

56 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

57 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!

58 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

59 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;

60 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

61 Uttryck, Satser och Block i C
Mats Brorsson KTH

62 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

63 Datorsystemteknik torsdag den 6 april 2017 If-satser

64 Datorsystemteknik torsdag den 6 april 2017 Relationsoperatorer

65 Datorsystemteknik torsdag den 6 april 2017 Repetitionsslingor

66 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;

67 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;

68 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

69 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...

70 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’.

71 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 = är ett uttryck Sätt semikolon ; efter uttrycket så får vi en sats x = 4711;

72 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?

73 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

74 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 }

75 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

76 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;

77 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

78 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

79 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)

80 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;

81 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

82 Pekare och pekararitmetik i C
Mats Brorsson KTH

83 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

84 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

85 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"

86 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

87 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

88 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

89 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

90 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

91 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

92 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

93 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

94 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

95 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

96 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

97 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;

98 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

99 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

100 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

101 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 */

102 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

103 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

104 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!"

105 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

106 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!"

107 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

108 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; } }

109 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 ++ */ } }

110 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]; }

111 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]; }

112 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

113 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

114 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

115 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

116 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

117 Lagring av globala och lokala variabler
Mats Brorsson KTH

118 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

119 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

120 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

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

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

123 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)

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

125 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;

126 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 */

127 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));

128 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: g: 17

129 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: g: 17

130 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 .align type .size g, 4 g: .long Ger mer hjälpsam info till länkningen

131 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

132 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 ); }

133 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

134 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

135 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

136 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

137 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

138 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)

139 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

140 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

141 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

142 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

143 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


Ladda ner ppt "Maskinnära programmering i C"

Liknande presentationer


Google-annonser