Ladda ner presentationen
Presentation laddar. Vänta.
Publicerades avHåkan Samuelsson
1
1 IS1200 Datorteknik, övning 4 Maskinnära programmering med C Förberedelser till hemlaboration 1
2
2 4.1 Little och big endian
3
3 4.2 Alignment.align 2 vanligt direktiv för instruktions-minnet, som har 32-bitars instruktioner. 2^2 = 4 bytes =32 bits. Detta är vanligt också för data-minnet, men följande förekommer också.align 02^0 = 1.align 12^1 = 2.align 32^3 = 8 etc Nios II –hårdvaran refererar alltid till.align 2 –minne. Vid simulering kan man ev. välja annorlunda.
4
4 ldw när effektivadressen inte är jämnt delbar med 4 40414243 adress 40 adress 44 44454647 * Hårdvaran skulle behöva hämta två ord och sätta ihop olika delar av orden * Exempel med effektivadress = 43 * Hårdvaran i Nios II kan inte göra detta
5
5 4.3 Minnesdispossition.data.bss.data (initialiserade data).bss (oinitialiserade data)
6
6 4.3 Adressrymd Programkoden, tex skapad i C-main, C-funktioner eller i assembler- programms.text-segment hamnar i kod-arean
7
7 4.3 Adressrymd Globala variabler, skapade i början av C- program eller i assemblers.data-segment, som sparas under compile-time, hamnar i data-arean. Oinitialiserade globala variabler hamnar i.bss-delen där.
8
8 4.3 Adressrymd Lokala variabler, skapade i C-main, C-funktion eller i assembler-programs.text-segment som sparas under run-time och hamnar på stacken.
9
9 4.3 Adressrymd Vet man inte i förväg hur mycket utrymme som behövs för data, kan man använda heapen istället för globala variabler. Då lägger man data där som tillkommer under körningen. Man allokerar då alltid utrymme med malloc och lägger tillbaka med free. Använder man heapen på det sättet, minskar man risken att skriva över information.
10
10 4.4 Värden, pekare, referenser, heltalsvariabler Skriv programrader i C som visar hur * och & används för att a) deklarera två heltalsvariabler: a och b C: int a,b; assembler för Nios II:.data # placera i.bss eller.data.align 2 # på adress delbar med 4 a:word 0 # ett ord = 4 bytes = 32 bitar med värdet 0 b:word 0 # ett ord = 4 bytes = 32 bitar med värdet 0
11
11 4.4 Värden, pekare, referenser, heltalsvariabler * och & b) initialisera heltalsvariabeln b till värdet 27 i samband med deklarationen enl (a). C: int a; int b = 27; assembler för Nios II:.data.align 2 a: word 0 b: word 27 # ett ord = 4 bytes = 32 bitar # med värdet 27 (dec)
12
12 4.4 Värden, pekare, referenser, heltalsvariabler * och & c) deklarera två pekarvariabler, som kan peka på a och b: ptr1 och ptr 2. C: int* ptr1; int* ptr2; /* int* ptr1, ptr2; är fel, men int *ptr1,*ptr2; är också OK */ Assembler för Nios II:.data.align 2 ptr1:.word 0 # ett ord = 4 bytes = 32 bitar med värdet 0 ptr2:.word 0 # ett ord = 4 bytes = 32 bitar med värdet 0
13
13 C: a = 4711; b = 47; Assembler för Nios II:.text # placera kod i.text-arean.align 2 # på adress delbar med 4 moviar8, a # r8 pekar nu på a moviar9, 4711 # r9 innehåller värdet 4711 stwr9, 0(r8) # värdet 4711 skrivs till a moviar8,b # r8 pekar nu på b moviar9,47 # r9 innehåller nu värdet 47 stwr9, 0(r8) # värdet 47 skrivs till b 4.4 Värden, pekare, referenser, heltalsvariabler * och & d) tilldela a värdet 4711 och b värdet 47.
14
14 C: ptr1 = &a; /* utläses som ”ptr1 tilldelas värdet av adressen till a” */ Assembler för Nios II:.text.align 2 moviar8, a # adressen till a skrivs till r8 movia r9, ptr1 # r9 pekar nu på ptr1 stw r8, 0(r9) # adressen till a skrivs nu till ptr1 4.4 Värden, pekare, referenser, heltalsvariabler * och & e) tilldela pekarvariabeln ett värde, så att den pekar på heltalsvariabeln a
15
15 C: b = *ptr1; /* b tilldelas det värde som ptr1 pekar på */ Assembler för Nios II:.text.align 2 moviar8, ptr1 # nu pekar r8 på ptr1 movia r9, b # nu pekar r9 på b ldwr10, 0(r8) # nu innehåller r10 värdet av ptr1, som pekar på a ldwr11, 0(r10) # nu innehåller r11 värdet som ptr1 pekar på, dvs a stw r11, 0(r9) # nu innehåller b det som ptr1 pekade på, dvs a 4.4 Värden, pekare, referenser, heltalsvariabler * och & f) tilldela heltalsvariabeln b samma värde som a, med hjälp av ptr1.
16
16 C: ptr2 = ptr1; /* variabeln ptr2 tilldelas samma värde som variabeln ptr1 */ Assembler för Nios II:.text.align 2 moviar8, ptr1 # nu pekar r8 på ptr1 movia r9, ptr2 # nu pekar r9 på ptr2 ldwr10, 0(r8) # nu finns värdet från ptr1 i r10 stw r10, 0(r9) # nu nu har ptr2 samma värde som ptr1. 4.4 Värden, pekare, referenser, heltalsvariabler * och & g) tilldela pekarvariabeln ptr2 ett värde, så att den pekar på samma variabel som ptr1.
17
17 C: char c, d; Assembler för Nios II:.data.align 2 c:.byte 0 # 1 byte = 8 bitar med värdet 0 d:.byte 0 # 1 byte = 8 bitar med värdet 0 Blir det någon skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler? Svar JA, bara en byte per variabel och tätt packat. 4.5 Värden, pekare, referenser, char-variabler Skriv programrader i C, som visar hur * och & används i nedanstående exempel. Översätt varje exempel för hand till Nios2-assembler. Skriv alltså först C och sedan Nios-II-assembler för att a) deklarera två globala variabler av typen char: c och d.
18
18 C: char c; char d = 65; Assembler för Nios II:.data.align 2 c:.byte 0 # 1 byte = 8 bitar med värdet 0 d:.byte 65 # 1 byte = 8 bitar med värdet 65 (dec) 4.5 Värden, pekare, referenser, char-variabler * och & b) initialisera variabeln d till värdet 65 i samband med deklarationen enl (a). Vad blir det för skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?.
19
19 C: char* ptr3; char* ptr4; Assembler för Nios II:.data.align 2 # på adress delbar med 4, # nödvändigt, pekare är 4 bytes ptr3:.word 0 # 1 ord = 4 bytes = 32 bitar med värdet 0 ptr4:.word 0 # 1 ord = 4 bytes = 32 bitar med värdet 0 Ingen kvalitets-skillnad mot heltal (förutom symboliska namn) 4.5 Värden, pekare, referenser, char-variabler * och & c) deklarera två globala pekarvariabler, som kan peka på c och d: ptr3 och ptr4. Blir det någon skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?.
20
20 C: c = ’M’; d = 97; Assembler för Nios II:.txt.align 2 moviar8, c # r8 pekar nu på c movir9, ’M’ # nu räcker det med movi (istf movia) stbr9, 0(r8) # ska vara stb, ej stw moviar8, d # r8 pekar nu på d movir9, 97 # misstänkt negativt ?! stb r9, 0(r8) # ska vara stb, ej stw 4.5 Värden, pekare, referenser, char-variabler * och & d) tilldela c värdet ’M’ och tilldela d värdet 97. Vad blir det för skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?.
21
21 C: ptr3 = &c; Assembler för Nios II:.txt.align 2 moviar8, c # nu pekar r8 på c moviar9, ptr3 # nu pekar r9 på ptr3 stwr8, 0(r9) # nu pekar ptr3 på c 4.5 Värden, pekare, referenser, char-variabler * och & e) tilldela pekarvariabeln ptr3 ett värde, så att den pekar på variabeln c. Blir det någon skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?
22
22 C: d = *ptr3; /* d tilldelas det värde som ptr3 pekar på */ Assembler för Nios II:.txt.align 2 moviar8, ptr3 # nu pekar r8 på ptr3 moviar9, d # nu pekar r9 på d ldwr10, 0(r8) # nu innehåller r10 värdet av # ptr3 som pekar på c ldbr11, 0(r10) # nu innehåller r11 värdet som # ptr3 pekar på, dvs c stbr11, 0(r9) # nu innehåller d det som # ptr3 pekade på, dvs c 4.5 Värden, pekare, referenser, char-variabler * och & f) tilldela variabeln d samma värde som c, med hjälp av ptr3. Vad blir det för skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?
23
23 C: ptr4 = ptr3; /* */ Assembler för Nios II:.txt.align 2 moviar8, ptr3 # nu pekar r8 på ptr3 moviar9, ptr4 # nu pekar r9 på ptr4 ldwr10, 0(r8) # nu finns värdet från ptr3 i r10 stwr10, 0(r9) # nu har ptr4 samma värde som ptr3 4.5 Värden, pekare, referenser, char-variabler * och & g) tilldela pekarvariabeln ptr4 ett värde, så att den pekar på samma variabel som ptr3. Blir det någon skillnad skillnad i Nios-II-assemblerkoden jämfört med motsvarande operation med heltalsvariabler?
24
24 (4.5) Enkel C-kod med pekare a) C-koden nedan ska kompileras för hand till assembler för Nios II b) Hur översätts raden a = *ptr ? c) Vilket värde returnerar programmet? C: int a; int b = 27; int * ptr; int main() { a = 17; ptr = &b; a = *ptr; return( a ); } assembler:.data.align 2 a:.word 0 a:.word 27 ptr.word 0.text.align 2 main: # a = 17; moviar8, a movir9, 17 stwr9, 0(r8) # ptr = &b; moviar8, ptr moviar9, b stwr9, 0(r8) # a = *ptr # lägg adressen till ptr i r8 moviar8, ptr # läs ptr:s värde ldwr9, 0(r8) # ptr innehåller en adress, # läs i minnet på den adressen ldwr10, 0(r9) # skriv till a movia r11, a stwr10, 0(r11) # return( a ); moviar8, a ldwr2, 0(r8) ret
25
25 Kompilera följande korta C-program till assemblerkod för Nios II int c = 47; int * ptr; int main() { int tmp; ptr = &tmp; *ptr = c; return( tmp ); } (4.5) Annan C-kod med pekare
26
26 (4.5) Annan C-kod med pekare.data.align 2 c:.word 47 ptr:.word 0.text.align 2 main: # int tmp; # gör plats för tmp på stack addi sp,sp,-4 # ptr = &tmp; movia r8,ptr stw r8, 0(sp) # nu pekar ptr på tmp # *ptr = c; # lägg adress till c i r9 movia r9,c # läs c ldw r10,0(r9) # lägg adress till ptr i r11 movia r11,ptr # läs ptr ldw r12,0(r11) # följ pekaren och skriv till minnet stw r10,0(r12) # return( tmp ); ldw r2,0(sp) # läs tmp addi sp,sp,4 # remove tmp ret
27
27 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcopy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcopy( &b [0] [0], &a [0] [0], sizeof( a ) ); a)Förklara vad en pointer to void är för något. Det är en pekare, som pekar på en plats i minnet, men det är odefinierat vilken typ som pekas ut. Det innebär, att kompilatorn inte vet hur många bytes, som eventuellt ska läsas eller skrivas på den platsen i minnet. Därför krävs av programmeraren att det görs type-cast av en void-pekare, innan den kan användas för en minnesreferens.
28
28 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcopy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcopy( &b [0] [0], &a [0] [0], sizeof( a ) ); b)Förklara de tre parametrarna till memcpy. Den första, dest, är en voidpekare, som anger första byte i minnet, till vilken kopieringen ska ske. Den andra, src, är en voidpekare, som anger första byte, från vilken kopiering ska ske. Den tredje parametern anger antal bytes, som ska kopieras.
29
29 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcpy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) ); c)Förklara returvärdet från memcpy. Returvärdet är en voidpekare (som ska returnera det ursprungliga värdet av dst)
30
30 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcpy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) ); d)Förklara opreratorn sizeof(). Operatorn sizeof() kommer (at compile time) att ta reda på storleken av a uttryckt i antal bytes.
31
31 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcpy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) ); e)Förklara texten (void) vid anropet till memcpy. På returvärdet, vilken typ det än är, görs type-cast till en void för att därefter ignoreras.
32
32 4.6 Funktionen memcpy Bland biblioteksfunktionerna finns en, som heter memcpy, med följande deklaration: void * memcpy( void * dest, const void *src, size_t len ); Ett anrop kan se ut så här: int a[4711] [4711]; int b[4711] [4711]; /* här emellan finns mera kod, som bland annat initialiserar matrisen a */ (void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) ); f)Visa hur funktionen memcpy kan översättas till assembler för Nios II. Kortare och bättre version: memcpy:movr2,r4 loop:beqr6, r0,out# kolla om klart ldbr12, 0(r5)# läs en byte addir5, r5, 1# öka src-pekare stbr12, 0(r4)# skriv en byte addir4, r4, 1# öka dst-pekare subir6, r6, 1# minska counter br loop# loopa out:ret
33
33 4,7 Matriser Visa med en tydlig figur hur de 15 elementen i nedanstående matriser lagras i minnet vid körning av C-program Svar: C-kompilatorn lagrar matriser radvis. a)int matris[3][5] [0][0] [0][1] [0][2] [0][3] [0][4] [1][0] [1][1] [1][2] [1][3] [1][4] [2][0] [2][1] [2][2] [2][3] [2][4] b)int [5][3] [0][0] [0][1] [0][2] [1][0] [1][1] [1][2] [2][0] [2][1] [2][2] [3][0] [3][1] [3][2] [4][0] [4][1] [4][2]
34
34 4.8 C-version av puttime Skriv en version av funktionen puttime i C-kod. Deklarationen är void puttime( int * timeloc ); Förslag som kanske kan förbättras: void puttime( int * timeloc ); { register int time = *timeloc; register int ctmp; putchar (0xA);/* ny rad */ putchar (0xD);/* vagnretur */ ctmp = (time & 0xF000) >> 12; ctmp = hexasc (ctmp); putchar (ctmp); ctmp = (time & 0x 0F00) >> 8; ctmp = hexasc (ctmp); putchar (ctmp); putchar (’:’);/* kolon*/ ctmp = (time & 0x00F0) >> 4; ctmp = hexasc (ctmp); putchar (ctmp); ctmp = (time & 0x000F); ctmp = hexasc (ctmp); putchar (ctmp); }
35
35 register = typmodifierare vid deklaration av automatiska variabler. begäran att (om möjligt) få använda register i CPU istället för stacken vid hantering av viss variabel. CPU:n hanterar ju sina register mycket snabbare än stacken i minnet.
36
36 4.9 Struct a) Skriv en C-kod som definierar lagring av en struct ”tiger” med de ingående delvariablerna : namn, 13 tecken, tex tiger (från NallePuh) vikt, avrundat till hela kilogram, tex 245 (som int, dvs 4 bytes) snabbaste fart i kilometer per timme (som float, dvs 4 byte) längd över allt, angiven i meter (som float, dvs 4 byte) struct tiger { charnamn[13]; intvikt; floatfart; floatlangd; } c) Vilket resultat erhålls som returvärde från operationerna sizeof (struct tiger); troligen 13(+3) + 4 + 4 + 4 = 28 sizeof (int); troligen 4
37
37 4.9 Struct a) Skriv en C-kod som definierar lagring av en struct ”elephant” med de ingående delvariablerna : namn, 13 tecken, tex Dumbo (från sagorna) vikt, avrundat till hela kilogram, tex 1243 (som int, dvs 4 bytes) öronyta uppdelat på vänster och höger öra angivet i kvadratmeter (som float, dvs 4 byte) struct oron { floatleft; floatright; }; struct elephant { charnamn[13]; intvikt; struct oron oronarea; }; c) Vilket resultat erhålls som returvärde från operationerna sizeof (struct elephant); troligen 13(+3) + 4 + 4 + 4 = 28
38
38 4.10 Dynamisk minnesallokering med malloc och free Beskriv med ord eller rita en figur, som illustrerar hur minne kan allokeras, avallokeras och återanvändas vid följande tänkvärda operationer i ett C-program. /*1*/struct elephant * dumbo = malloc(sizeof elephant)); /*2*/struct tiger * tiger1 = malloc(sizeof(struct tiger); /*3*/free(dumbo); /*4*/struct tiger * tiger2 = malloc(sizeof(struct tiger)); /*5*/struct tiger * tiger3 = malloc(sizeof(struct tiger)); /*6*/free(tiger1); 28 byte överallt, jämnt delbart med 4 123456 Heap lägsta adress här; ökar uppåt i bilden ee t1 t3 t2
Liknande presentationer
© 2024 SlidePlayer.se Inc.
All rights reserved.