31
IS1200 Datorteknik IS1500 Datorteknik och komponenter Hemlaboration C Maskinnära programmering med C 2015-01-09 Kursdeltagarens namn: ................................................................................................................. Datum: .............................. Godkänd av (assistentens signatur): ............................................... IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 1

Hemlaboration C Maskinnära programmering med C

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Hemlaboration C Maskinnära programmering med C

IS1200 DatorteknikIS1500 Datorteknik och komponenter

Hemlaboration C

Maskinnära programmering

med C2015-01-09

Kursdeltagarens namn: .................................................................................................................

Datum: .............................. Godkänd av (assistentens signatur): ...............................................

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 1

Page 2: Hemlaboration C Maskinnära programmering med C

Inledning

För att kunna skriva bra program i C och andra språk behöver programmeraren ha en klar bild av hur programmet översätts till assemblerkod, och av hur det använder minne och processor under körningen. I den här laborationen illustreras detta med C-kod, och med en del Nios-II-assembler.

Målsättning med hemlaborationen

Att få insikt i och djupare förståelse för

● hur enkla och sammansatta datatyper deklareras i C-kod.

● hur vektorer och matriser deklareras i C-kod.

● hur datorn räknar fram adresser till (indexerar) element i vektorer och matriser.

● hur sammansatta datatyper lagras i datorns minne.

● hur datorn räknar fram adresser till element i sammansatta datatyper.

● hur pekarvariabler fungerar och används i C-kod.

● hur användning av pekarvariabler kan översättas till assemblerkod.

● hur operationer på enstaka bitar utförs i C-kod.

● hur dynamisk minneshantering fungerar i C-kod.

Efter redovisad hemlaboration kommer du att kunna förklara

● hur elementen i vektorer och matriser placeras i datorns minne.

● hur elementen i sammansatta datatyper placeras i datorns minne.

● hur innehållet i en pekarvariabel ska tolkas.

● hur pekararitmetik påverkar innehållet i pekarvariabler, för pekare till olika datatyper, inklusive sammansatta datatyper.

● hur avreferering av olika slags pekarvariabler översätts till assemblerkod.

● hur Booleska operationer och bitvisa operationer fungerar och används i C-kod.

● hur malloc och free används för dynamisk minneshantering i C-kod.

Förkunskaper

Innan du börjar ska du kunna en del om datoraritmetik och binära tal, C-programmering och assemblerprogrammering. Lab-PM för lab nios2time behandlar Nios2-assembler. Läs i kursboken! Det finns också bra information i exempelsamlingen, och i bilderna från föreläsningen om maskinnära programmering med C.

Vi i kursteamet svarar gärna på frågor om du undrar över något när du arbetar med hemlabora-tionen! Använd kurswebben i KTH Social. Vi svarar så fort vi kan, och ibland kan någon annan student hinna svara före oss.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 2

Page 3: Hemlaboration C Maskinnära programmering med C

Redovisning av hemlaborationen

Sammanfattning: bokför allt, gör pappersutskrifter av allt som lab-PM säger att du ska skriva ut, tänk igenom motiveringar till alla dina svar på alla frågor, var väl förberedd vid redovisningen.

Bokför ändrade programfiler, kommandon, felutskrifter och resultat vid varje provkörning!

Vid redovisningen måste du kunna visa din dokumentation, berätta om resultaten och förklara. Saknas någon dokumentation så måste du redovisa igen.

Gör pappersutskrifter. Laborationsredovisningen genomförs utan dator.

Du får använda dina anteckningar under redovisningen. Se till att de går lätt att att hitta i. Ta gärna med frågorna i anteckningarna. Samla de utskrifter och anteckningar som hör till en uppgift, till exempel uppgift 1, på 1–2 papper. Gör inte ett enda långt dokument, det blir svårt att hitta i.

Ha dina papper väl organiserade, så att du hinner visa tillräckliga kunskaper på utsatt tid.

Vid redovisningen ställer läraren delvis andra frågor än dem som finns med här i lab-PM. En viktig fråga som läraren ställer ofta är "Varför?". Läraren kan också fråga "Hur mycket minnesplats är reserverat för variablerna ip och cp?" Anpassa dina anteckningar till det sättet att fråga.

Ingen lärare frågar "läs upp svaret på uppgift 2.2". Är dina anteckningar gjorda för såna frågor så kommer redovisningen att gå dåligt.

När du har visat tillräckliga kunskaper vid redovisningen bokförs din hemlabb som godkänd.

Har du inte utfört alla moment, eller inte visar tillräckliga kunskaper, så får du göra om hela redo-visningen senare. Orsaken spelar ingen roll. Du måste visa tillräckliga kunskaper för godkänt.

Till nästa redovisning kompletterar och uppdaterar du förstås dina provkörningar och kunskaper, och repeterar så att du har hela labben aktuell vid redovisningen.

Redovisning ska göras i grupp om 2 personer. Vid redovisningen bedöms kunskaperna individuellt. Om bara en person visar tillräckliga kunskaper så blir bara den personen godkänd.

Provkörningar

För den här hemlaborationen använder du valfri C-kompilator som följer Iso-standarden (valfri version: C90, C95, C99 eller C11). Eftersom du väljer kompilator så kan kommandona se olika ut. På nästa uppslag finns två förslag.

Använd samma dator och samma kompilator för alla uppgifter.

Se till att den du redovisar med också använder samma dator och samma kompilator.

Efter varje kompilering, kolla att programmet har kompilerats klart. Om C-filen (programfil.c eller annat namn som slutar på .c) är nyare än den körbara filen, så har programmet inte kompi-lerats färdigt. Startar du ändå programmet så körs en gammal version, och det var inte det du ville.

Spara alltid eventuella varningar och felutskrifter från kompilatorn genom att klippa ut dem och klistra in dem i en fil.

Du ska ha exakta kopior av alla varningar/felutskrifter med dig vid redovisningen.

I vissa fall kan fel inträffa som gör att körningen avbryts med ett felmeddelande, trots att kompileringen gått bra. Dokumentera i så fall både kompileringen och körningen, med exakta kopior av felmeddelanden med mera. Ta med all dokumentation till redovisningen. Läraren kommer att diskutera dina utskrifter med dig och vid behov förklara vad som hänt, och varför körningen avbröts.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 3

Page 4: Hemlaboration C Maskinnära programmering med C

Körning med Nios II Software Build Tools for Eclipse

Nios II Software Build Tools for Eclipse är lätt att komma igång med, men en del av utskrifterna kan vara svåra att hitta. Följ instruktionerna i Nios2-laborationerna.

Skapa nytt projekt för varje programversion.

För att kompilera, högerklicka på projektnamnet och välj "Build Project". Då kompileras programmet, men startas inte. På det sättet hinner du se eventuella felmeddelanden i konsolfönstret.

Observera att de här systemen inte kompilerar om filer om de inte ändrats sedan förra kompileringen. Därför är det lätt att missa varningsmeddelanden. Lägg till ett mellanslag i en kommentar i filen och spara innan du kör programmet, så är du säker på att filen kompileras.

Dialogrutan "Errors exist in required project. Continue launch?" visar att fel finns. Vid denna fråga ska du klicka på "No" (eller "Nej"). Klickar du på "Yes" (eller "Ja") så körs en gammal version av programmet, från senaste gången som kompileringen lyckades.

Viktigt: Det är lätt att missa att du har fått varningar vid kompileringen.Gör först "Clean Project" och sedan "Build Project". Använd sedanknappen "Display Selected Console" i konsolfönstrets högerkant – sebilden här till höger. Välj att visa "C-Build". Gör detta vid varje kompilering så att du ser om kompilatorn varnar för något i programmet.

Med Nios II Software Build Tools for Eclipse så kör du den kompilerade filen i simulatorn NIISim. Se instruktionerna i Nios2-laborationerna.

Spara varningar och felutskrifter så här i Nios II IDE och Nios II Software Build Tools for Eclipse: Markera och kopiera utskrifter ur konsolfönstren, och klistra in dem i ett textdokument som du skriver ut och tar med till redovisningen.

Spara både kompilatormeddelanden och programutskrifter.

Till vissa uppgifter ska du ta fram en namnlista för programmet. Så här kan du göra det i Nios II Build Tools for Eclipse.

Namnlista i Nios II Software Build Tools for Eclipse: Vid varje kompilering skapas en textfil sombland annat innehåller namnlistan. Om ditt projekt heter "areas", så heter filen med namnlistan "areas.objdump". Den filen innehåller mycket information om den körbara filen. Namnlistan finns några sidor in i filen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 4

Page 5: Hemlaboration C Maskinnära programmering med C

Körning med gcc från kommandoraden

Kompilatorn gcc är vanlig och effektiv. Om din dator har gcc installerad så kan kompilering och körning göras från kommandoraden. Vi antar att du har ett C-program i filen mittprogram.c.

Kommandot gcc startar flera olika programfiler som i tur och ordning utför kompilering, assemblering och länkning.

Kompilera, assemblera och länka filen med två flaggor:-o mittprogram för att ange att den kompilerade filen ska heta "mittprogram", och-O (stort O) för optimering. Såhär:

gcc -O -o mittprogram mittprogram.c

Skriv nu ./mittprogram för att starta ditt program. Obs! I Windows heter programfilen mittprogram.exe och då skriver du./mittprogram.exe istället.

Till redovisningen behöver du ha programutskrifterna i en fil. Använd kommandot./mittprogram > mittprogramutskrift.txt

Du kan köra på alla datorer med gcc, till exempel KTHs Gnu/Linux-arbetsstationer. Har du egen dator med Windows så kan du installera Cygwin (www.cygwin.com). För att få med gcc, se till att paketgruppen "Devel" är satt till "Install" när du installerar Cygwin. Du kan ändra inställningen med pilsymbolen: Varje gång du klickar på symbolen kan ändringen ta några sekunder.

Efter kompilering, ge kommandot nm, som läser information om lägen och variabelnamn ur den binära ("oläsbara" men) körbara filen och översätter informationen till en läsbar lista:

nm mittprogram > mittprogram.nm

På vissa system kan kommandona vara lite annorlunda.Windows med Cygwin: nm mittprogram.exe > mittprogram.nmVissa Solaris-system: /usr/ccs/bin/nm mittprogram > mittprogram.nm

Tips! De flesta kommandotolkar har filnamnskomplettering. Skriv början på filnamnet och tryck påTab-tangenten så fylls fortsättningen i så långt den är unik. Sedan får du skriva lite till.

Obs! Ibland kan kompilatorn ge varnings- och felmeddelanden. Ibland är felen så allvarliga att programmet inte gick att kompilera färdigt. Med kommandot ls -ltr (i Unix/Linux/Cygwin) visasfilernas tidsstämpel. De senaste filerna kommer längst ned i denna lista.

Om din C-fil (programfil.c eller annat namn som slutar på .c) är nyare än den körbara filen, så har programmet inte kompilerats färdigt. Skulle du ändå starta programmet så körs en gammal version, från senaste gången kompileringen lyckades, och det var ju inte det du ville.

Spara alltid eventuella varningar och felutskrifter från kompilatorn genom att klippa ut dem och klistra in dem i en fil. Du ska ha exakta kopior av samtliga varningar/felutskrifter med dig vid redovisningen.

Tips! Använder du Cygwin så kan du högerklicka på fönstrets namnlist för att få fram en meny. Därkan du välja Redigera – Markera. Sedan markerar du med musen. För att kopiera, klicka på namnlisten igen och välj Redigera – Kopiera.

I vissa fall kan fel inträffa som gör att körningen avbryts med ett felmeddelande, trots att kompileringen gått bra. Dokumentera i så fall både kompileringen och körningen, med exakta kopior av felmeddelanden med mera. Ta med all dokumentation till redovisningen. Läraren kommer att diskutera dina utskrifter med dig och vid behov förklara vad som hänt, och varför körningen avbröts.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 5

Page 6: Hemlaboration C Maskinnära programmering med C

Laborationsuppgifter —läs igenom hela lab-PM innan du börjar!

Uppgift 1. Minnesområden.

Kompilera och kör följande program och studera resultatet.Du kan hämta programmet på kurswebben: areas.c

1 /* areas.c - Find addresses of memory areas 2 * 3 * Written 2012 by F Lundevall. 4 * Copyright abandoned. This file is in the public domain. 5 * 6 * To make this program work on as many systems as possible, 7 * addresses are converted to unsigned long when printed. 8 * The 'l' in formatting-codes %ld and %lx means a long operand. */ 910 #include <malloc.h> 11 #include <stdio.h> 12 #include <stdlib.h> 1314 int gi; /* Global variable. */ 15 int in = 4711; /* Global variable, initialized to 4711. */ 1617 int fun( int parm ) 18 { 19 /* Local variable, initialized every time fun is called. */ 20 int loc1 = parm + 17; 2122 printf( "AF.1: loc1 stored at %lx (hex); value is %d (dec), %x (hex)\n", 23 (long) &loc1, loc1, loc1 ); 24 printf( "AF.2: parm stored at %lx (hex); value is %d (dec), %x (hex)\n", 25 (long) &parm, parm, parm ); 2627 gi = parm; /* Change the value of a global variable. */ 28 printf( "AF.3: Executed gi = parm;\n" ); 29 return( loc1 ); 30 } 3132 /* Main function. */ 33 int main() 34 { 35 /* Local variables. */ 36 int m; 37 int n; 38 int * p; /* Declare p as pointer, so that p can hold an address. */ 39 /* Do some calculation. */ 40 gi = 12345; 41 m = gi + 11111; 42 n = 17; 4344 printf( "Message AM.01 from areas.c: Hello, World!\n" ); 4546 printf( "AM.02: m: stored at %lx (hex); value is %d (dec), %x (hex)\n", 47 (long) &m, m, m ); 48 printf( "AM.03: n: stored at %lx (hex); value is %d (dec), %x (hex)\n", 49 (long) &n, n, n ); 50 printf( "AM.04: gi: stored at %lx (hex); value is %d (dec), %x (hex)\n",

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 6

Page 7: Hemlaboration C Maskinnära programmering med C

51 (long) &gi, gi, gi ); 52 printf( "AM.05: in: stored at %lx (hex); value is %d (dec), %x (hex)\n", 53 (long) &in, in, in ); 54 55 printf( "AM.06: fun: address is %lx (hex)\n", (long) fun ); 56 printf( "AM.07: main: address is %lx (hex)\n", (long) main ); 57 58 p = (int *) malloc( sizeof( int ) ); 59 printf( "AM.08: Executed p = (int *) malloc( sizeof( int ) );\n" ); 60 printf( "AM.09: p: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 61 (long) &p, (long) p, (long) p ); 6263 printf( "AM.10: Will soon execute n = fun( m );\n" ); 64 n = fun( m ); 65 printf( "AM.11: Has now returned from n = fun( m );\n" ); 66 67 printf( "AM.12: n: stored at %lx (hex); value is %d (dec), %x (hex)\n", 68 (long) &n, n, n ); 69 printf( "AM.13: gi: stored at %lx (hex); value is %d (dec), %x (hex)\n", 70 (long) &gi, gi, gi ); 7172 free( p ); 73 exit( 0 ); 74 }75

För att du lätt ska kunna hänvisa till rätt rad när du redovisar, så är programraderna numrerade här ovanför. De textrader som programmet matar ut är också numrerade, från AM.01 till AM.13 (i funktionen main) oc från AF.1 till AF.3 (i funktionen fun).

Kompilera och länka programmet enligt instruktionerna i början av lab-PM.Kör programmet och spara programutskrifterna på en fil enligt instruktionerna tidigare i lab-PM.

Utskrifter som ska vara med vid redovisningen av areas.c

● utskrift av eventuella felmeddelanden vid kompilering av areas.c

● utskrift från körning av areas.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

Fråga 1.1. I vilken minnesarea lagras variabeln gi: kod, data, bss, heap eller stack?

Fråga 1.2. I vilken minnesarea lagras variabeln in: kod, data, bss, heap eller stack?

Fråga 1.3. I vilken minnesarea lagras variabeln m: kod, data, bss, heap eller stack?

Fråga 1.4. I vilken minnesarea lagras variabeln p: kod, data, bss, heap eller stack?

Fråga 1.5. Variabeln p är en pekare (nästa uppgift har en kort förklaring av pekare). I vilken minnesarea pekar p vid utskriften AM.09: kod, data, bss, heap eller stack?

Fråga 1.6. Vad finns på den adress som skrivs ut i AM.06: en instruktion, data, eller något annat?

Fråga 1.7. Använd utskrifterna från körning av areas.c för att avgöra hur minnet delas upp i din dator. Fyll i figuren på nästa sida, eller rita egen figur på separat papper.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 7

Page 8: Hemlaboration C Maskinnära programmering med C

Bilden här ovanför visar hur minnet kan vara uppdelat i olika områden. Två exempel finns med.

Programkoden lagras i den körbara filen och kopieras till datorns minne när programmet ska startas.

I den körbara filen lagras också initialiserade globala data, så att de initialiserade globala variablerna får sina startvärden redan innan programmet börjar köra.

Minnesområdet "bss" används för oinitialiserade globala data. De lagras inte i den körbara filen. I stället nollställs rätt minnesområde innan programmet startas.

Lokala variabler (som hör till en viss funktion/subrutin) lagras på stacken.

Heap hanteras av C-funktionerna malloc och free.

Bilden här nedanför visar hur programkod och initialiserade globala data kopieras från den körbara filen till datorns minne när programmet ska startas.

Header-delen av den körbara filen innehåller bland annat information om hur stor programkods- och data-områdena är, och om hur stort minnesområdet "bss" ska vara. Alla bytes i bss-området nollställs vid programstarten.

Symboltabellen innehåller information om lägen och variabelnamn. Det är den informationen som nm-kommandot skriver ut.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 8

program-kod

databss

heap

stack

program-kod

heap

stack

Exempel 1 Exempel 2

databss

PC

SP

adress 0

adress 2n-1

adress 0

adress 2n-1

adress 0

adress 2n-1

PC

SP

Din dator (fyll i)

header

program-kod

data

symboltabell

program-kod

heap

databss

kopiering vid program-start

körbar fil minne

Page 9: Hemlaboration C Maskinnära programmering med C

Uppgift 2. Pekare

Kort och enkel repetition av pekare, * och & i programspråket C:

En pekare är en variabel som kan innehålla en minnesadress.

För att deklarera en pekare skrivs * före namnet vid deklarationen.

För att använda innehållet i en pekarvariabel som minnesadress skrivs * före variabelnamnet.

För att vid körning få adressen till en variabel vilken som helst skrivs & före variabelnamnet.

En pekare kan innehålla minnesadressen till programkoden för en C-funktion, men deklaration och användning av en sån pekare brukar vara svårlästa.

Prova gärna http://cdecl.org/ och skriv in:declare fp as pointer to function (int) returning intSkrivsättet function (int) betyder att funktionen har en parameter av typen int.

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: pointers.c

1 /* pointers.c - Test pointers2 * Written 2012 by F Lundevall 3 * Copyright abandoned. This file is in the public domain. 4 * 5 * This file must be used with PDF instructions dated 2012-12-14 or 2013-06-28. 6 * 7 * To make this program work on as many systems as possible, 8 * addresses are converted to unsigned long when printed. 9 * The 'l' in formatting-codes %ld and %lx means a long operand. */ 1011 #include <stdio.h> 12 #include <stdlib.h> 1314 int * ip; /* Declare a pointer to int, a.k.a. int pointer. */ 15 char * cp; /* Pointer to char, a.k.a. char pointer. */ 1617 /* Declare fp as a pointer to function, where that function 18 * has one parameter of type int and returns an int. 19 * Use cdecl to get the syntax right, http://cdecl.org/ */ 20 int ( *fp )( int ); 2122 int val1 = 111111; 2324 int ia[ 17 ]; /* Declare an array of 17 ints, numbered 0 through 16. */ 25 char ca[ 17 ]; /* Declare an array of 17 chars. */ 2627 int fun( int parm ) 28 { 29 printf( "Function fun called with parameter %d\n", parm ); 30 return( parm + 1 ); 31 } 3233 /* Main function. */ 34 int main() 35 { 36 int val2 = 2222222; 3738 printf( "Message PT.01 from pointers.c: Hello, pointy World!\n" ); 3940 /* Do some assignments. */

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 9

Page 10: Hemlaboration C Maskinnära programmering med C

41 ip = &val1; 42 cp = &val2; /* The compiler should warn you about this. */ 43 fp = fun; 4445 ia[ 0 ] = 11; /* First element. */ 46 ia[ 1 ] = 17; 47 ia[ 2 ] = 3; 48 ia[ 16 ] = 58; /* Last element. */ 4950 ca[ 0 ] = 11; /* First element. */ 51 ca[ 1 ] = 17; 52 ca[ 2 ] = 3; 53 ca[ 16 ] = 58; /* Last element. */ 5455 printf( "PT.02: val1: stored at %lx (hex); value is %d (dec), %x (hex)\n", 56 (long) &val1, val1, val1 ); 57 printf( "PT.03: val2: stored at %lx (hex); value is %d (dec), %x (hex)\n", 58 (long) &val2, val2, val2 ); 59 printf( "PT.04: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 60 (long) &ip, (long) ip, (long) ip ); 61 printf( "PT.05: sizeof(ip) == %d\n", (int) sizeof( ip ) ); 62 printf( "PT.06: Dereference pointer ip and we find: %d \n", *ip ); 63 printf( "PT.07: sizeof(*ip) == %d\n", (int) sizeof( *ip ) ); 64 printf( "PT.08: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 65 (long) &cp, (long) cp, (long) cp ); 66 printf( "PT.09: sizeof(cp) == %d\n", (int) sizeof( cp ) ); 67 printf( "PT.10: Dereference pointer cp and we find: %d \n", *cp ); 68 printf( "PT.11: sizeof(*cp) == %d\n", (int) sizeof( *cp ) ); 6970 *ip = 1234; 71 printf( "\nPT.12: Executed *ip = 1234; \n" ); 72 printf( "PT.13: val1: stored at %lx (hex); value is %d (dec), %x (hex)\n", 73 (long) &val1, val1, val1 ); 74 printf( "PT.14: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 75 (long) &ip, (long) ip, (long) ip ); 76 printf( "PT.15: Dereference pointer ip and we find: %d \n", *ip ); 7778 *cp = 1234; /* The compiler should warn you about this. */ 79 printf( "\nPT.16: Executed *cp = 1234; \n" ); 80 printf( "PT.17: val2: stored at %lx (hex); value is %d (dec), %x (hex)\n", 81 (long) &val2, val2, val2 ); 82 printf( "PT.18: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 83 (long) &cp, (long) cp, (long) cp ); 84 printf( "PT.19: Dereference pointer cp and we find: %d \n", *cp ); 8586 ip = ia; 87 printf( "\nPT.20: Executed ip = ia; \n" ); 88 printf( "PT.21: ia[0]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 89 (long) &ia[0], ia[0], ia[0] ); 90 printf( "PT.22: ia[1]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 91 (long) &ia[1], ia[1], ia[1] ); 92 printf( "PT.23: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 93 (long) &ip, (long) ip, (long) ip ); 94 printf( "PT.24: Dereference pointer ip and we find: %d \n", *ip ); 9596 ip = ip + 1; /* add 1 to pointer */ 97 printf( "\nPT.25: Executed ip = ip + 1; \n" ); 98 printf( "PT.26: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 99 (long) &ip, (long) ip, (long) ip ); 100 printf( "PT.27: Dereference pointer ip and we find: %d \n", *ip ); 101

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 10

Page 11: Hemlaboration C Maskinnära programmering med C

102 cp = ca; 103 printf( "\nPT.28: Executed cp = ca; \n" ); 104 printf( "PT.29: ca[0]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 105 (long) &ca[0], ca[0], ca[0] ); 106 printf( "PT.30: ca[1]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 107 (long) &ca[1], ca[1], ca[1] ); 108 printf( "PT.31: ca[2]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 109 (long) &ca[2], ca[2], ca[2] ); 110 printf( "PT.32: ca[3]: stored at %lx (hex); value is %d (dec), %x (hex)\n", 111 (long) &ca[3], ca[3], ca[3] ); 112 printf( "PT.33: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 113 (long) &cp, (long) cp, (long) cp ); 114 printf( "PT.34: Dereference pointer cp and we find: %d \n", *cp ); 115116 cp = cp + 1; /* add 1 to pointer */ 117 printf( "\nPT.35: Executed cp = cp + 1; \n" ); 118 printf( "PT.36: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 119 (long) &cp, (long) cp, (long) cp ); 120 printf( "PT.37: Dereference pointer cp and we find: %d \n", *cp ); 121122 ip = ca; /* The compiler should warn you about this. */ 123 printf( "\nPT.38: Executed ip = ca; \n" ); 124 printf( "PT.39: Dereference pointer ip and we find: %d \n", *ip ); 125126 ip = ip + 1; /* add 1 to pointer */ 127 printf( "\nPT.40: Executed ip = ip + 1; \n" ); 128 printf( "PT.41: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 129 (long) &ip, (long) ip, (long) ip ); 130 printf( "PT.42: Dereference pointer ip and we find: %d \n", *ip ); 131132 cp = ia; /* The compiler should warn you about this. */ 133 printf( "\nPT.43: Executed cp = ia; \n" ); 134 printf( "PT.44: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 135 (long) &cp, (long) cp, (long) cp ); 136 printf( "PT.45: Dereference pointer cp and we find: %d \n", *cp ); 137138 printf( "\nPT.46: fp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n", 139 (long) &fp, (long) fp, (long) fp ); 140 printf( "PT.47: Dereference fp and see what happens.\n" ); 141142 val1 = (*fp)(42); 143 printf( "PT.48: Executed val1 = (*fp)(42); \n" ); 144 printf( "PT.49: val1: stored at %lx (hex); value is %d (dec), %x (hex)\n", 145 (long) &val1, val1, val1 ); 146147 return( 0 ); 148 }149

För att du lätt ska kunna hänvisa till rätt rad när du redovisar, så är programraderna numrerade här ovanför. De textrader som programmet matar ut är också numrerade, från PT.01 till PT.49.

Utskrifter som ska vara med vid redovisningen av pointers.c

● utskrift av eventuella felmeddelanden vid kompilering av pointers.c

● utskrift från körning av pointers.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

Frågorna finns på nästa sida.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 11

Page 12: Hemlaboration C Maskinnära programmering med C

Fråga 2.1. Vad händer vid kompilering? Förklara varje varningsmeddelande.

Fråga 2.2. Hur stor minnesplats reserveras för variabeln ip ?

Fråga 2.3. Hur ska innehållet i variabeln ip tolkas?

Fråga 2.4. Vad händer när satsen *ip = 1234; utförs?

Fråga 2.5. Översätt satsen *ip = 1234; till Nios-II-assembler.

Fråga 2.6. Hur ändras innehållet i variabeln ip när satsen ip = ip + 1; utförs? Varför?

Fråga 2.7. Hur stor minnesplats reserveras för variabeln cp ?

Fråga 2.8. Hur ska innehållet i variabeln cp tolkas?

Fråga 2.9. Vad händer när satsen *cp = 1234; utförs?

Fråga 2.10. Översätt satsen *cp = 1234; till Nios-II-assembler.

Fråga 2.11. Hur ändras innehållet i variabeln cp när satsen cp = cp + 1; utförs? Varför?

Fråga 2.12. Hur många byte stor är en char?

Fråga 2.13. Är din dator big-endian eller little-endian? Motivera med hjälp av utskrift från körning av pointers.c och figuren här nedanför. Se helst till att hitta två olika motiveringar som är oberoende av varandra. Observera att utskriften PT.19 inte ger någon information om huruvida datorn är big-endian eller little-endian.

När heltal, flyttal och adresser ska lagras i datorns minne så behövs flera bytes för varje värde. Då finns två alternativ för byte-ordningen.

En möjlighet är att börja med den byte som innehåller värdets mest signifikanta bitar, och placera denna byte närmast adress 0. Övriga bytes som ingår i värdet kommer i ordning, med mindre signifikanta bitar ju längre från adress 0 man kommer. Denna byte-ordning kallas big-endian.

Den andra möjligheten är att börja med den byte som innehåller värdets minst signifikanta bitar, ochden ordningen kallas little-endian.

Figuren här intill visar ett 32-bits heltali ett register, samt i minnet på en datormed little-endian byte-ordning (tillvänster), och med big-endianbyte-ordning (till höger).

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 12

address 0

0001 0010 0011 0100 0101 0110 0111 1000

address 0

0101 0110

0001 0010

0011 0100

0111 1000

1 byte

(8 bits)

. . .

305419896 (decimal)

Copying a 4-byte number from register to memory.

little-endian byte-order(stores the least significant byte first)

big-endian byte-order (stores the most

significant byte first)

0101 0110

0001 0010

0011 0100

0111 1000

1 byte

(8 bits)

. . .

Page 13: Hemlaboration C Maskinnära programmering med C

Bilden här nedanför visar hur 4 bytes i minnet kombineras till 32-bitars heltal, dels i en 32-bits datormed little-endian byte-ordning och dels i en 32-bits dator med big-endian byte-ordning.

Uppgift 3. Void

Typen void används för att markera att ett värde inte ska användas. En funktion kan ha returtypen void, och det betyder att funktionen inte har något returvärde.

En pekare av typen void * (vilket utläses pointer to void, eller void-pekare) kan innehålla en adressav valfri sort. Det går inte att avreferera (dereference) en void-pekare, men pekarvärdet kan kopieras till valfri annan pekare. Sedan kan den andra pekaren avrefereras.

Programmeraren måste se till att använda rätt pekartyper i kombination med void-pekare. Språket Ctillåter både meningsfulla och meningslösa kombinationer.

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: void.c

Tips 1. En del kompilatorer vägrar kompilera programmet på grund av rad 56:vp = vp + 1;

Om det händer dig, kopiera felmeddelandet ord för ord så att du kan visa läraren vid redovisningen. Kommentera sedan bort rad 56 och försök igen

Tips 2. Om du använder gcc från kommandoraden, prova följande kompilering av detta program: gcc -std=c99 -pedantic -O -o void void.c

Jämför meddelandena från kompilatorn vid den här kompileringen, och meddelandena vid den vanliga (utan -std=c99 -pedantic).

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 13

01010111

01011001

00000000

00000000

adress 0

adress 2n-1. . .

. . .

01010111010110010000000000000000 01010111 01011001 00000000 00000000

(lilla änden först i minnet) (stora änden först i minnet)

little-endian byte-order big-endian byte-order

Hur 4 bytes kopieras till ett register när en instruktion av typen Load Word utförs.

Page 14: Hemlaboration C Maskinnära programmering med C

1 /* void.c - Test pointers to void2 * Written 2012 by F Lundevall3 * Copyright abandoned. This file is in the public domain.4 *5 * To make this program work on as many systems as possible,6 * addresses are converted to unsigned long when printed.7 * The 'l' in formatting-codes %ld and %lx means a long operand. */89 #include <stdio.h>10 #include <stdlib.h>1112 int * ip; /* Declare a pointer to int, a.k.a. int pointer. */13 void * vp; /* Pointer to void, a.k.a. void pointer. */14 int ia[ 17 ]; /* Declare an array of 17 ints, numbered 0 through 16. */1516 /* Main function. */17 int main()18 {19 char * cp;2021 printf( "Message VO.01 from void.c: Hello Void!\n" );2223 /* Do some assignments. */24 ip = &ia[2];25 vp = ia;2627 ia[ 0 ] = 111111; /* First element. */28 ia[ 1 ] = 17;29 ia[ 2 ] = 123456;30 ia[ 16 ] = 66; /* Last element. */3132 printf( "VO.02: ia[0]: stored at %lx (hex); value is %d (dec), %x (hex)\n",33 (long) &ia[0], ia[0], ia[0] );34 printf( "VO.03: ia[1]: stored at %lx (hex); value is %d (dec), %x (hex)\n",35 (long) &ia[1], ia[1], ia[1] );36 printf( "VO.04: ia[2]: stored at %lx (hex); value is %d (dec), %x (hex)\n",37 (long) &ia[2], ia[2], ia[2] );38 printf( "VO.05: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",39 (long) &ip, (long) ip, (long) ip );40 printf( "VO.06: Dereference pointer ip and we find: %d \n", *ip );41 printf( "VO.07: vp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",42 (long) &vp, (long) vp, (long) vp );4344 cp = vp;45 printf( "\nVO.08: Executed cp = vp; \n" );46 printf( "VO.09: cp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",47 (long) &cp, (long) cp, (long) cp );48 printf( "VO.10: Dereference pointer cp and we find: %d \n", *cp );4950 ip = vp;51 printf( "\nVO.11: Executed ip = vp; \n" );52 printf( "VO.12: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",53 (long) &ip, (long) ip, (long) ip );54 printf( "VO.13: Dereference pointer ip and we find: %d \n", *ip );5556 vp = vp + 1; /* Add 1 to pointer. The compiler may warn you about this. */57 printf( "\nVO.14: Executed vp = vp + 1; \n" );58 printf( "VO.15: vp: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",59 (long) &vp, (long) vp, (long) vp );6061 *ip = 4711;

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 14

Page 15: Hemlaboration C Maskinnära programmering med C

62 printf( "\nVO.16: Executed *ip = 4711; \n" );63 printf( "VO.17: ip: stored at %lx (hex); value is %ld (dec), %lx (hex)\n",64 (long) &ip, (long) ip, (long) ip );65 printf( "VO.18: Dereference pointer ip and we find: %d \n", *ip );66 printf( "VO.19: ia[0]: stored at %lx (hex); value is %d (dec), %x (hex)\n",67 (long) &ia[0], ia[0], ia[0] );6869 /* The compiler should complain about the following line. */ 70 /* *vp = 1234; */ 71 printf( "\nVO.20: After /* *vp = 1234; */\n" );7273 return( 0 );74 }75

Utskrifter som ska vara med vid redovisningen av void.c:

● utskrift av varningar och felmeddelanden vid kompilering av void.c● utskrift från körningar av void.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

Fråga 3.1. Varnar din kompilator för någon av tilldelningarna cp = vp; eller ip = vp; ?

Fråga 3.2. Varnar din kompilator för tilldelningen vp = vp + 1; ? I så fall, varför?

Skapa en ny fil govoid.c med samma innehåll som filen void.c Ändra filen govoid.c och ta bort kommentartecknen /* och */ före och efter satsen *vp = 1234;Kompilera och kör govoid.c. Utskrifter som ska vara med vid redovisningen av den ändrade govoid.c

● utskrift av varningar och felmeddelanden vid kompilering av den ändrade govoid.c● om möjligt, utskrift från körning av den ändrade govoid.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

Fråga 3.3. Förklara kompilatorns beteende.Fråga 3.4. Ge förslag på meningsfulla sätt att använda pekare av typen void * för att skriva en

C-funktion som kopierar en array eller matris från en plats till en annan.Tips! Dra nytta av ditt arbete med nästa uppgift, som handlar om matriser.

Fråga 3.5. Ge förslag på andra meningsfulla sätt att använda pekare av typen void *.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 15

Page 16: Hemlaboration C Maskinnära programmering med C

Uppgift 4. Matriser

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: matrix.c

1 /* matrix.c - test rows and columns of a matrix2 * Written 2004-2012 by F Lundevall and J Wennlund3 * Copyright abandoned. This file is in the public domain. */45 #include <stdio.h>6 #define ROWCOUNT (3)7 #define COLUMNCOUNT (4)89 int imat[ ROWCOUNT ][ COLUMNCOUNT ]; 10 char cmat[ ROWCOUNT ][ COLUMNCOUNT ];11 double dmat[ ROWCOUNT ][ COLUMNCOUNT ];12 int rmat[ ROWCOUNT ][ COLUMNCOUNT ]; 1314 int main()15 {16 int i; int j;17 int * ip; char * cp; double * dp;1819 for( i = 0; i < ROWCOUNT; i = i + 1 )20 for( j = 0; j < COLUMNCOUNT; j = j + 1 )21 {22 imat[ i ][ j ] = 10000 + 100*i + j;23 cmat[ i ][ j ] = 10*i + j;24 dmat[ i ][ j ] = 1.0 + i/100.0 + j/10000.0;25 rmat[ i ][ j ] = 0;26 };2728 printf( "\n Examining imat:\n" );29 for( ip = &imat[ 0 ][ 0 ];30 ip <= &imat[ ROWCOUNT - 1 ][ COLUMNCOUNT - 1 ];31 ip = ip + 1 )32 printf( "memory at: %lx contains value: %d\n", (unsigned long) ip, *ip );3334 printf( "\n Examining cmat:\n" );35 for( cp = &cmat[ 0 ][ 0 ];36 cp <= &cmat[ ROWCOUNT - 1 ][ COLUMNCOUNT - 1 ];37 cp = cp + 1 )38 printf( "memory at: %lx contains value: %d\n", (unsigned long) cp, *cp );3940 printf( "\n Examining dmat:\n" );41 for( dp = &dmat[ 0 ][ 0 ];42 dp <= &dmat[ ROWCOUNT - 1 ][ COLUMNCOUNT - 1 ];43 dp = dp + 1 )44 printf( "memory at: %lx contains value: %f\n", (unsigned long) dp, *dp );45 46 /* Add a statement here to call your matriscopy function. */47 48 printf( "\n Examining rmat:\n" );49 for( ip = &rmat[ 0 ][ 0 ];50 ip <= &rmat[ ROWCOUNT - 1 ][ COLUMNCOUNT - 1 ];51 ip = ip + 1 )52 printf( "memory at: %lx contains value: %d\n", (unsigned long) ip, *ip );5354 return( 0 );55 }56

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 16

Page 17: Hemlaboration C Maskinnära programmering med C

Kompilera och länka programmet enligt instruktionerna i början av lab-PM.Kör programmet och spara programutskrifterna på en fil enligt instruktionerna tidigare i lab-PM

Fråga 4.1. Har startadresserna för imat, cmat, dmat och rmat samma ordning i minnet som deras deklarationer har i programmet?

Fråga 4.2. Matriselementen imat[1][2] och imat[1][3] ligger nära varandra om man betraktar matrisen ur matematisk synvinkel. Ligger dessa två matriselement nära varandra i datorns minne också?

Fråga 4.3. Matriselementen imat[1][2] och imat[2][2] ligger nära varandra om man betraktar matrisen ur matematisk synvinkel. Ligger dessa två matriselement nära varandra i datorns minne också?

Fråga 4.4. Kompilatorn placerar ut matriselementen inom varje matris i en viss ordning i minnet. Vilken ordning?

Fråga 4.5. Skriv en matematisk formel som anger hur man kan beräkna adressen till ett element i en heltalsmatris, om man känner till matrisens startadress, matrisens storlek och elementetsrad och kolumnindex. Alla variabler i formeln ska vara tydligt definierade.

Fråga 4.6. Skriv C-kod för en funktion matriscopy som kopierar en int-matris från en plats i minnet till en ny plats i minnet. Utnyttja dina erfarenheter för att skriva kod som går igenom kompilatorn utan problem, och som exekverar snabbt. Din funktion ska ha fyra parametrar, i följande ordning:destmat – adressen till den plats där första elementet i matrisen ska skrivas;srcmat – adressen till första elementet i matrisen som ska kopieras;rowcount – antalet rader i matrisen;columncount – antalet kolumner i matrisen.Förslag på anrop av matriscopy framgår av nedanstående mall.

int a[11][17]; int b[11][17];...matriscopy (a, b, 11, 17); /* a = &a[0] för alla arraytyper */

Du får göra anropet med andra uttryck i stället för a och b. Vid redovisningen ska du kunnaförklara hur du har kommit fram till det anrop du visar upp.Skapa en ny fil minmatrix.c med samma innehåll som i matrix.c och ändra i minmatrix.c: lägg in din funktion matriscopy, och lägg också in ett anrop till funktionenså att den kopierar innehållet i imat till rmat. Rätt plats för anropet finns markerad med en kommentar i filen.Kompilera och provkör minmatrix.c. Se till att du inte får några fel- eller varnings-meddelanden vid kompileringen. Kontrollera att programmet fungerar som det ska. Du behöver inte ta med utskrifter från körningen (men du måste förstås göra körningen ochkontrollera att resultatet blir rätt).

Matrisberäkning – utskrifter som ska vara med vid redovisningen

● Formel (och variabeldefinitioner) som anger hur man kan beräkna adressen till ett element i en heltalsmatris.

● Hela C-programfilen minmatrix.c, innehållande funktionen matriscopy. Observera att du måste ha med hela filen minmatrix.c! Urklippta delar räcker inte.

När du har gjort klart dessa utskrifter, sätt kryss i rutan i marginalen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 17

Page 18: Hemlaboration C Maskinnära programmering med C

Uppgift 5. Bitar, bytes och bokstäver

Antag att a och b är två variabler av typen int med värdena a=17 och b=5.

Förklara innebörden av C-raderna i tabellen. Ange också vilket heltalsvärde som varje rad returnerar, och varför. Använd eget papper vid behov.

Tips: Du kan få hjälp med svaren genom att skriva små C-program som utför en eller flera av C-raderna och visar resultatet. Se till att a=17 och b=5 innan varje C-rad körs.

C-rad Returnerar heltalet Förklaring: vad gör raden, vad innebär värdet?

&bundantag: vilket heltal

som returneras skainte besvaras för &b

a & b

a | b

a ^ b

a && b

a || b

-b

~b

~(~a)

!b

!(!a)

a = b

a == b

a = 'A'

a | '@'

När du har fyllt i hela tabellen, sätt kryss i rutan i marginalen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 18

Page 19: Hemlaboration C Maskinnära programmering med C

Uppgift 6. Sammansatta datatyper

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: struct.c

1 /*2 * struct.c - Program to test struct3 * Written 2009-2012 by F Lundevall4 * Copyright abandoned. This file is in the public domain.5 */6 #include <stdio.h> /* Defines printf. */7 #define ARRAYSIZE 389 /* Declare structured types (but not variables). */10 struct ipair11 {12 int v1;13 int v2;14 };1516 struct nested17 {18 int val;19 char c1;20 char c2;21 struct ipair z;22 char str1[7];23 char str2[11];24 };2526 /* Declare global variable ipa - an array of struct ipair. */27 struct ipair ipa[ ARRAYSIZE ]; /* Array of ipairs. */2829 /* Declare global variable na - an array of struct nested. */30 struct nested na[ ARRAYSIZE ]; /* Array of ipairs. */3132 /* Declare some structured variables. */33 struct ipair s1;34 struct nested nes = { 17, 'Q', 'Z', { 117, 217 }, "Hello!", "Goodbye!" };3536 int main () /* Called as a method/function/subroutine. */37 {38 int i; /* Loop index variable. */39 int * ip; /* Temporary pointer to int for printouts. */40 struct ipair * ipp; /* Declare a pointer to struct ipair. */41 struct nested * nesp; /* Declare a pointer to struct nested. */4243 s1.v1 = 11; /* Assign a value to val in s1. */44 s1.v2 = 17; /* Assign a value to v2 in s1. */4546 printf( "Message ST.01 from struct.c: Hello, structured World!\n");47 printf( "ST.02: s1: stored at %lx (hex), sizeof(s1) is %d (dec)\n",48 (unsigned long) &s1, (int) sizeof(s1) );49 printf( "ST.03: s1.v1 at %lx (hex) contains %d (dec), %x (hex)\n",50 (unsigned long) &(s1.v1), s1.v1, s1.v1);51 printf( "ST.04: s1.v2 at %lx (hex) contains %d (dec), %x (hex)\n",52 (unsigned long) &(s1.v2), s1.v2, s1.v2);5354 ipp = &s1; /* Pointer ipp now points to a struct ipair. */55 printf( "\nST.05: Executed ipp = &s1;\n");56 printf( "ST.06: ipp: stored at %lx (hex), contains %ld (dec), %lx (hex)\n",57 (unsigned long) &ipp, (unsigned long) ipp, (unsigned long) ipp );

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 19

Page 20: Hemlaboration C Maskinnära programmering med C

58 printf( "ST.07: Dereference pointer ipp and we find: (*ipp).v1=%d, (*ipp).v2=%d\n",59 (*ipp).v1, (*ipp).v2 );60 printf( "ST.08: Dereference with different syntax: ipp->v1=%d, ipp->v2=%d\n",61 ipp->v1, ipp->v2 );62 63 (*ipp).v1 = nes.val; /* Copy a value using dot-syntax. */64 printf( "\nST.09: Executed (*ipp).v1 = nes.val;\n");6566 ipp -> v2 = 4711; /* Assign a value using arrow syntax. */67 printf( "ST.10: Executed ipp -> v2 = 4711;\n");68 printf( "ST.11: Dereference pointer ipp and we find: (*ipp).v1=%d, (*ipp).v2=%d\n",69 (*ipp).v1, (*ipp).v2 );7071 for( i = 0; i < ARRAYSIZE; i += 1 )72 {73 ipa[ i ].v1 = 1000 + i;74 ipa[ i ].v2 = 2000 + i;75 }76 printf( "\nST.12: Initialized ipa.\n");7778 ip = (int *) ipa;79 for( i = 0; i < ARRAYSIZE * 2; i += 1 )80 {81 printf("ST.%.2d: Memory at %lx (hex) contains %d\n",82 i+13, (unsigned long) ip, *ip);83 ip += 1;84 }8586 ipp = ipa;87 printf( "\nST.23: Executed ipp = ipa;\n");88 printf( "ST.24: ipp: stored at %lx (hex), contains %ld (dec), %lx (hex)\n",89 (unsigned long) &ipp, (unsigned long) ipp, (unsigned long) ipp ); 90 printf( "ST.25: Dereference pointer ipp and we find: ipp->v1=%d, ipp->v2=%d\n",91 ipp->v1, ipp->v2 );9293 ipp = ipp + 1;94 printf( "\nST.26: Executed ipp = ipp + 1;\n");95 printf( "ST.27: ipp: stored at %lx (hex), contains %ld (dec), %lx (hex)\n",96 (unsigned long) &ipp, (unsigned long) ipp, (unsigned long) ipp );97 printf( "ST.28: Dereference pointer ipp and we find: ipp->v1=%d, ipp->v2=%d\n",98 ipp->v1, ipp->v2 );99100 printf( "\nST.29: nes: stored at %lx (hex), sizeof(nes) is %d (dec)\n",101 (unsigned long) &nes, (int) sizeof(nes) );102 printf( "ST.30: nes.val at %lx (hex) contains %d (dec), %x (hex)\n",103 (unsigned long) &(nes.val), nes.val, nes.val);104 printf( "ST.31: nes.c1 at %lx (hex) contains '%c', %d (dec), %x (hex)\n",105 (unsigned long) &(nes.c1), nes.c1, nes.c1, nes.c1);106 printf( "ST.32: nes.c2 at %lx (hex) contains '%c', %d (dec), %x (hex)\n",107 (unsigned long) &(nes.c2), nes.c2, nes.c2, nes.c2);108 printf( "ST.33: nes.z: stored at %lx (hex)\n", (unsigned long) &(nes.z));109 printf( "ST.34: (nes.z).v1 at %lx (hex) contains %d (dec), %x (hex)\n",110 (unsigned long) &((nes.z).v1), (nes.z).v1, (nes.z).v1);111 printf( "ST.35: (nes.z).v2 at %lx (hex) contains %d (dec), %x (hex)\n",112 (unsigned long) &((nes.z).v2), (nes.z).v2, (nes.z).v2);113 printf( "ST.36: nes.str1 at %lx (hex) contains: %s\n",114 (unsigned long) &(nes.str1), nes.str1 );115 printf( "ST.37: nes.str2 at %lx (hex) contains: %s\n",116 (unsigned long) &(nes.str2), nes.str2 );117118 na[0] = nes; /* Copy the complete structure. */

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 20

Page 21: Hemlaboration C Maskinnära programmering med C

119 printf( "\nST.38: Executed na[0] = nes;\n" );120121 nesp = na ; /* Let nesp point to the copy. */122 printf( "\nST.39: Executed nesp = &na;\n" );123 printf( "ST.40: nesp: stored at %lx (hex); contains %ld (dec), %lx (hex)\n",124 (unsigned long) &nesp, (unsigned long) nesp, (unsigned long) nesp);125 printf( "ST.41: Dereference pointer nesp and we find: nesp->val=%d, and...\n",126 nesp->val );127 printf( "ST.42: nesp->c1='%c', (*nesp).c2='%c', and...\n",128 nesp->c1, (*nesp).c2 );129 printf( "ST.43: (nesp->z).v1=%d,(nesp->z).v2=%d, and...\n",130 (nesp->z).v1, (nesp->z).v2 );131 printf( "ST.44: nesp->str1=\"%s\" (*nesp).str2=\"%s\"\n",132 nesp->str1, (*nesp).str2 );133134 nesp = nesp + 1;135 printf( "\nST.43: Executed nesp = nesp + 1;\n" );136 printf( "ST.44: nesp: stored at %lx (hex); contains %ld (dec), %lx (hex)\n",137 (unsigned long) &nesp, (unsigned long) nesp, (unsigned long) nesp);138139 return( 0 ); /* exit from program by returning from main() */140 }141

I den här uppgiften studerar du C-kod med sammansatta datatyper. En sammansatt datatyp kallas struct i C. En struct definieras alltid av programmeraren, och innehåller en eller flera delvariabler med valfria typer.

Utvikning: En del andra programmeringsspråk har så kallade objekt. Ett objekt består av delvariabler, plus funktioner för att manipulera delvariablerna. Funktionerna brukar kallas metoder. Om du vill kan du tänka dig en struct som ett objekt utan metoder. Det går inte att ha metoder i en struct i C.

En ny struct-variabel deklareras i två steg. Först definieras hur datatypen ska sammansättas. Man kan se det som att man ger en mall för vad just den här sortens struct ska innehålla. I nästa steg kan man deklarera variabler som följer mallen.

För att referera innehållet i en struct används operatorn . (punkt), se rad 43 och rad 44.

Om programmet har en pekare till en struct måste man ha parenteser om avrefereringen av pekaren, se rad 63. Eftersom detta är en ganska vanlig operation så finns en alternativ syntax med pil, se rad 66. Skrivsätten x->y och (*x).y är ekvivalenta i C.

Storleken på en struct kan undersökas med hjälp av operatorn sizeof(). Programmet struct.c skriver bland annat ut vad kompilatorn returnerar när operatorn sizeof() används på variablerna s1 och nes.

Obs! Operatorn sizeof() beräknas alltid vid kompileringen!

Utskrifter som ska vara med vid redovisningen av struct.c

● utskrift av eventuella felmeddelanden vid kompilering av struct.c

● utskrift från körning av struct.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 21

Page 22: Hemlaboration C Maskinnära programmering med C

Fråga 6.1. Din provkörning visar var i minnet denstrukturerade variabeln s1, med delvariablerna s1.v1och s1.v2, placeras. Var i minnet finns s1.v2 iförhållande till s1.v1 ?

Fråga 6.2. Din provkörning visar var i minnet denstrukturerade variabeln nes placeras, och ocksåadresserna till delvariablerna i nes. Fyll i adressernatill vänster i figuren på denna sida, och skriv nes.val,nes.c1, nes.c2, (nes.z).v1, (nes.z).v2, nes.str1 och nes.str2 i rutorna bredvid. Observeraatt varje rad motsvarar 4 byte.

Fråga 6.3. När en variabel av typen struct nestedkompileras, placerar många C-kompilatorer oanvändabytes mellan vissa delvariabler. Undersök om dinkompilator har gjort något sådant för struct nes.Om kompilatorn har lagt in oanvända bytes på ett ellerflera ställen, ge förslag på varför detta kan behövas.

Fråga 6.4. Din provkörning visar var i minnet som elementeni arrayen ipa placeras. Fyll i adresserna i figuren, ochskriv ipa[0].v1 och så vidare i rutan intill. Observeraatt varje rad motsvarar 4 byte.

Fråga 6.5. Hur ändras innehållet i variabeln ipp när satsen ipp = ipp + 1; utförs? Varför?

Fråga 6.6. Hur ändras innehållet i variabeln nesp när satsen nesp = nesp + 1; utförs? Varför?

Fråga 6.7. Har startadresserna för s1, nes och ipa sammaordning i minnet som deras deklarationer har iprogrammet?

När du har fyllt i figurerna på papper, sätt kryss i rutan imarginalen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 22

Figur till uppgift 6.4. Varje rad motsvarar 4 byte.

adress 0

1 ord

(4 byte)

...

________

________

________

________

________

________

________

________

________

________

________

________

________

...

adress______

Figur till uppgift 6.2. Varje rad motsvarar 4 byte.

adress 0

1 ord

(4 byte)

...

________

________

________

________

________

________

________

________

________

________

________

________

________

...

adress______

Page 23: Hemlaboration C Maskinnära programmering med C

Uppgift 7. Buffer overflow

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: smash.c

1 /*2 * smash.c - do bad things with a local array 3 * 4 * Written 2012 by F Lundevall 5 * Copyright abandoned. This program is in the public domain. 6 */ 78 #include <stdio.h> 910 /* Define an array of bytes, simulating a carefully planned input string. */ 11 unsigned char magicbytes[] = 12 { 13 'A', 'n', 'y', 'b', 'y', 't', 'e', 's', 14 32, 'g', 'o', 32, 'h', 'e', 'r', 'e', 15 4, 2, 128, 0, 16 'a', 'n', 'd', 32, 'h', 'e', 'r', 'e', 32, 't', 'o', 'o', 17 4, 2, 128, 0 18 }; 1920 void fun( void ) 21 { 22 printf( "SM.07: Function fun is never called in this program.\n" ); 23 printf( "SM.08: So if you see this message, what happened?\n" ); 24 } 2526 void smashup( unsigned char * bytes, int count ) 27 { 28 #define BUFFERSIZE (12) 29 int i; 30 char buf[ BUFFERSIZE ]; 3132 printf( "SM.03: Will now copy %d bytes into buffer of size %d\n", 33 count, BUFFERSIZE ); 34 /* Sloppy programming: this copy-loop does not stop at BUFFERSIZE. */ 35 printf( "SM.04: Showing old and new contents of memory during copy.\n" ); 36 for( i = 0; i < count; i += 1 ) 37 { 38 if( BUFFERSIZE == i ) printf( "Uh-oh, going beyond buffer now:\n" ); 39 printf( "buf[ %d ] at address %lx contained %d, ", 40 i, (long) &buf[ i ], buf[ i ] ); 41 buf[ i ] = bytes[ i ]; 42 printf( "new value is %d\n", buf[ i ] ); 43 } 44 printf( "SM.05: Finished copying, will now return from smashup\n" ); 45 } 4647 int main() 48 { 49 printf( "Message SM.01 from smash.c: Hello, smashing world!\n" ); 50 printf( "SM.02: Will now call function smashup with simulated input.\n" ); 51 smashup( magicbytes, (int) sizeof( magicbytes ) ); 52 printf( "SM.06: Successfully returned from function smashup\n" ); 53 return( 0 ); 54 }55

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 23

Page 24: Hemlaboration C Maskinnära programmering med C

Många program tar emot indata i form av en teckensträng, somkan ha varierande längd. Det program som tar emot en sådanteckensträng använder ofta en lokal array, där tecknen placerasvartefter de tas emot.

Varje gång ett tecken placeras in i arrayen ska arraystorlekenkollas, så att tecknet inte skrivs till en plats utanför arrayen.I språket C måste programmeraren skriva all programkod föratt göra kontrollen, och det är lätt att förbise detta.

Om ett program skriver indata till en array utan att kontrolleraantalet mottagna tecken mot arraystorleken, så kan variableroch annan information intill arrayen skrivas sönder. Det kanutnyttjas av personer som vill få programmet att göra andrasaker än vad programmeraren har tänkt.

När en C-funktion börjar köra efter att ha anropats, såreserverar funktionen plats på stacken. I det reserveradeutrymmet placeras återhoppsadressen, lokala variabler ochkopior av parametervärdena som funktionen anropades med.Dessutom finns en frame pointer, som förenklar arbetet i en delav kompilatorn.

Både frame pointer och kopior av parametervärden kanutelämnas, om kompileringen görs med hög optimeringsgrad.

Bilden till höger visar hur stacken kan se ut när funktionensmashup i filen smash.c har startat. Olika kompilatoreranvänder stacken på olika sätt. Det kan också finnas skillnaderberoende på vilken optimeringsgrad som använts vid kompileringen.

På nästa sida visas utmatning från en körning av programmet smash i simulatorn NIISim. Kompileringen gjordes med version 12.0 av Altera Nios II Software Build Tools for Eclipse. Optimering vid kompilering var inställd på "On". Jämför utmatningen från den körningen med de resultat du fick med din egen dator och kompilator.

Utskrifter som ska vara med vid redovisningen av smash.c

● utskrift av eventuella felmeddelanden vid kompilering av smash.c

● utskrift från körning av smash.c

När du har skrivit ut dessa utskrifter, sätt kryss i rutan i marginalen.

Fråga 7.1. Kompilerade du med eller utan optimering? Om du inte vet vilket, skriv ner exakt hur du gjorde för att kompilera programfilen smash.c.

Fråga 7.2. Fick du se utskriften SM.06? Varför/varför inte?

Fråga 7.3. Fick du se utskrifterna SM.07 och SM.08? Varför/varför inte?

Fråga 7.4. Fick du några felmeddelanden vid körningen? Varför/varför inte?

Fråga 7.5. Om det fanns skillnader mellan dina resultat och dem på nästa sida: försök förklara varför.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 24

Möjligt utseende för stacken när funktionen smashup har startat.

adress 0

1 ord

(4 byte)

...

________

________

________

stack top

________

________

________

________

________

________

________

________

________

copy of arg 1

i

buf[0]...

copy of arg 2

...buf[11]

frame pointer

return address

...

Page 25: Hemlaboration C Maskinnära programmering med C

Följande utmatning visades när programmet smash kördes i simulatorn NIISim. Kompileringen gjordes med version 12.0 av Altera Nios II Software Build Tools for Eclipse. Optimering vid kompilering var inställd på "On".

Message SM.01 from smash.c: Hello, smashing world!SM.02: Will now call function smashup with simulated input.SM.03: Will now copy 36 bytes into buffer of size 12SM.04: Showing old and new contents of memory during copy.buf[ 0 ] at address ffffcc contained 2, new value is 65buf[ 1 ] at address ffffcd contained 0, new value is 110buf[ 2 ] at address ffffce contained 0, new value is 121buf[ 3 ] at address ffffcf contained 0, new value is 98buf[ 4 ] at address ffffd0 contained 0, new value is 121buf[ 5 ] at address ffffd1 contained 0, new value is 116buf[ 6 ] at address ffffd2 contained 0, new value is 101buf[ 7 ] at address ffffd3 contained 0, new value is 115buf[ 8 ] at address ffffd4 contained 12, new value is 32buf[ 9 ] at address ffffd5 contained -47, new value is 103buf[ 10 ] at address ffffd6 contained -128, new value is 111buf[ 11 ] at address ffffd7 contained 0, new value is 32Uh-oh, going beyond buffer now:buf[ 12 ] at address ffffd8 contained 0, new value is 104buf[ 13 ] at address ffffd9 contained 0, new value is 101buf[ 14 ] at address ffffda contained 0, new value is 114buf[ 15 ] at address ffffdb contained 0, new value is 101buf[ 16 ] at address ffffdc contained 0, new value is -16buf[ 17 ] at address ffffdd contained 0, new value is 1buf[ 18 ] at address ffffde contained 0, new value is -128buf[ 19 ] at address ffffdf contained 0, new value is 0buf[ 20 ] at address ffffe0 contained 0, new value is 97buf[ 21 ] at address ffffe1 contained 0, new value is 110buf[ 22 ] at address ffffe2 contained 0, new value is 100buf[ 23 ] at address ffffe3 contained 0, new value is 32buf[ 24 ] at address ffffe4 contained 0, new value is 104buf[ 25 ] at address ffffe5 contained 0, new value is 101buf[ 26 ] at address ffffe6 contained 0, new value is 114buf[ 27 ] at address ffffe7 contained 0, new value is 101buf[ 28 ] at address ffffe8 contained 0, new value is 32buf[ 29 ] at address ffffe9 contained 0, new value is 116buf[ 30 ] at address ffffea contained 0, new value is 111buf[ 31 ] at address ffffeb contained 0, new value is 111buf[ 32 ] at address ffffec contained 36, new value is -16buf[ 33 ] at address ffffed contained 3, new value is 1buf[ 34 ] at address ffffee contained -128, new value is -128buf[ 35 ] at address ffffef contained 0, new value is 0SM.05: Finished copying, will now return from smashupSM.07: Function fun is never called in this program.SM.08: So if you see this message, what happened?SM.07: Function fun is never called in this program.SM.08: So if you see this message, what happened?SM.07: Function fun is never called in this program.SM.08: So if you see this message, what happened?SM.07: Function fun is never called in this program.SM.08: So if you see this message, what happened?SM.07: Function fun is never called in this program.SM.08: So if you see this message, what happened?(utmatningen upprepas tills användaren avbryter simuleringen)

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 25

Page 26: Hemlaboration C Maskinnära programmering med C

Uppgift 8. Dynamisk minneshantering

För dynamisk minneshantering i C används biblioteksfunktionerna malloc och free.

Biblioteksfunktionen malloc har en parameter, som anger hur många bytes man vill reservera. Funktionen returnerar en adress till ett tillräckligt stort minnesområde. Om det inte gick att reservera önskat antal bytes, så returnerar malloc värdet noll (egentligen: en nollpekare, det vill säga adressen 0).

För varje anrop till malloc måste programmet utföra exakt ett anrop till free. Parametern till free måste vara den adress som malloc returnerat.

Skulle malloc anropas tre gånger så kommer malloc att returnera tre olika adresser. Det medför att free måste anropas tre gånger: en gång med den första adressen som malloc returnerade, en gång med den andra adressen som malloc returnerade, och en gång med den tredje adressen som mallocreturnerade. De tre adresserna kan free-as i valfri ordning, men var och en av dem måste vara med i exakt ett anrop till free exakt en gång.

Om programmeraren glömmer att anropa free, så kommer programmet att förbruka minne som aldrig kan återanvändas. Detta kallas för en minnesläcka (memory leak).

Biblioteksfunktionerna malloc och free använder en del minne för administrativ information. Den administrativa informationen hjälper programkoden i biblioteksfunktionen att hålla reda på vilka delar av minnet som är lediga och vilka som är upptagna.

Det finns en minsta möjlig storlek, som till exempel kan vara 8 bytes. Om minimistorleken är 8 bytes så kommer anropet malloc(1) att förbruka 8 bytes minne, och dessutom lite plats för administrativ information.

Funktionerna malloc och free är biblioteksfunktioner. De anropar normalt inte operativsystemet. Det är bara om programmets minne är slut, som malloc gör ett systemanrop för att få använda meraminne.

Operativsystemet hanterar minnet i så kallade sidor, som exempelvis kan vara 8192 byte stora. Det är ganska mycket, vilket gör att malloc inte behöver göra systemanrop särskilt ofta.

Nios II har inget operativsystem, och inte heller något extra minne att använda. I andra datorsystem brukar det gå bra för ett program att öka sitt tillgängliga minne.

I den här uppgiften provkör du malloc och free. Programmet skriver ut vilka adresser malloc returnerar, så att du kan se hur biblioteksrutinerna arbetar.

Olika C-kompilatorer använder olika biblioteksfunktioner. De malloc och free som din kompilatoranvänder kan vara annorlunda än dem vi har använt när vi skrev lab-PM.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 26

Page 27: Hemlaboration C Maskinnära programmering med C

Kompilera och kör följande program och studera resultatet. Du kan hämta programmet på kurswebben: malloc.c

1 /*2 /* 3 * malloc.c - An exercise with malloc 4 * 5 * Written 2009-2010 by F Lundevall 6 * 7 * Copyright abandoned. This file is in the public domain. 8 */ 910 #include <stdio.h> /* Declares printf. */ 11 #include <stdlib.h> /* Declares malloc and free. */ 12 #include <string.h> /* Declares strlen and strncpy */ 1314 /* Note: on some weird systems, you may need to 15 * #include malloc.h - but ONLY do this if you otherwise 16 * get warnings for implicit declarations of malloc and free. */ 1718 #define SIZE (48) /* Size of array. Change here if you 19 want to try a different size. */ 2021 char cowabunga[] = "Cowabunga!"; 2223 /* gcount - count and print number of g's in a string. */ 24 void gcount( char * inputstring, int stringsize ) 25 { 26 register int * gcountp; /* Pointer to mallocated g-count. */ 27 register int i; /* For-loop index variable. */ 2829 /* Use malloc to allocate room for an int. */ 30 gcountp = (int *) malloc( sizeof( int ) ); 31 32 if( gcountp == (int *) 0 ) /* Check for malloc failure. */ 33 perror( "g-count malloc failed" ); 34 else 35 { 36 printf( "g-count successfully allocated, with size %d bytes.\n", 37 (int) sizeof( int ) ); 38 printf( "g-count malloc returned address %ld (dec), %lx (hex).\n", 39 (unsigned long) gcountp, (unsigned long) gcountp ); 4041 *gcountp = 0; /* Clear counter, then count. */ 42 for( i = 0; i < stringsize; i += 1 ) 43 if( 'g' == inputstring[ i ] ) *gcountp += 1; 44 printf( "Number of g's in array is %d.\n", *gcountp ); 45 46 free( gcountp ); /* Free mallocated memory, so it can be re-used. */ 47 printf( "Executed free( gcountp );\n" ); 48 } 49 } 5051 int main() 52 { 5354 register char * arrayp = (char *) 0; /* Will point to a mallocated array. */ 55 register int i; /* For-loop control variable. */ 56 register char * extrap; /* Pointer to another mallocated array. */ 57 register int alpha; /* Counter for alphabet. */ 5859 printf( "Message MA01 from malloc.c: Hello, memory-allocating World!\n" );

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 27

Page 28: Hemlaboration C Maskinnära programmering med C

60 61 /* Use malloc to allocate space for array */ 62 arrayp = (char *) malloc( SIZE * sizeof( char ) ); 63 /* Return values from library calls must always be checked. */ 64 if( arrayp == (char *) 0 ) 65 { /* If malloc fails, it returns a null pointer. */ 66 perror( "malloc for array failed" ); 67 exit( 1 ); 68 } /* End of return-value check for malloc */ 6970 /* Print info about our mallocated array. */ 71 printf( "MA02: Main array successfully allocated, with size %d bytes.\n", 72 SIZE ); 73 printf( "MA03: Main array malloc returned address %ld (dec), %lx (hex).\n", 74 (unsigned long) arrayp, (unsigned long) arrayp ); 7576 /* Initialize array with an alphabet, repeated if necessary. */ 77 alpha = 'a'; 78 for( i = 0; i < (SIZE - 1); i += 1 ) 79 { 80 arrayp[ i ] = alpha; 81 alpha += 1; 82 if( alpha > 'z' ) alpha = 'a'; 83 } 84 /* Add null char at the end, to make array contain a valid C string. */ 85 arrayp[ SIZE - 1 ] = 0; 8687 printf( "MA04: Main array now contains the following string:\n%s\n", arrayp ); 8889 gcount( arrayp, SIZE ); /* Call gcount, which uses malloc. */ 90 91 /* Now mallocate room for a copy of Cowabunga! */ 92 extrap = (char *) malloc( sizeof( cowabunga ) ); 93 /* Return values from library calls must always be checked */ 94 if( extrap == (char *) 0 ) 95 { 96 /* malloc returned null pointer, print error message. */ 97 perror( "malloc for cowabunga failed" ); 98 exit( 2 ); 99 } 100101 printf( "MA05: Cowabunga array successfully allocated, with size %d bytes.\n", 102 (int) sizeof( cowabunga ) ); 103 printf( "MA06: Cowabunga array malloc returned address %ld (dec), %lx (hex).\n", 104 (unsigned long) extrap, (unsigned long) extrap ); 105106 if( extrap != (char *) 0 ) 107 { 108 strcpy( extrap, cowabunga ); 109 printf( "MA07: Cowabunga array now contains the following string: %s\n", 110 extrap ); 111112 /* Copy extrap to array, but stop if array is too small. */ 113 strncpy( arrayp, extrap, SIZE ); 114 /* Put null char at the end, in case strncpy had to stop early. */ 115 arrayp[ SIZE - 1 ] = 0; 116 } 117 118 printf( "MA08: Main array now contains the following string:\n%s\n", arrayp ); 119120 gcount( arrayp, SIZE ); /* Call gcount, which uses malloc. */

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 28

Page 29: Hemlaboration C Maskinnära programmering med C

121 122 /* Free mallocated memory. */ 123 free( arrayp ); /* Free memory allocated to original array. */ 124 printf( "MA09: Executed free( arrayp );\n" ); 125 126 gcount( extrap, sizeof( cowabunga ) ); /* Call gcount, which uses malloc. */ 127 128 free( extrap ); /* Free memory allocated to new array. */ 129 printf( "MA10: Executed free( extrap );\n" ); 130131 return( 0 ); /* exit from program by returning from main() */ 132 }

Fråga 8.1. När du kört programmet, fyll i den stora figuren på nästa sida. Första grå rutan är redan ifylld med minnesanvändningen efter programraden arrayp = (char *) malloc( SIZE * sizeof( char ) );Fyll i rätt adress. Fyll också i de andra grå rutorna så att de visarminnesanvändningen efter varje steg. Rita in de minnesområdensom malloc returnerat, och som inte återlämnats med free. Varje litet delstreck i de grå rutorna motsvarar 1 byte, se figurenhär till höger. Om utrymmet inte räcker till i figuren, använd ett separat papper.Här nedanför visas ett exempel på hur det kan se ut. Kom ihåg att det finns många olika implementationer av malloc. Din körning behöver inte alls likna den i exemplet här nedanför. Se till att fylla i figuren så att den stämmer exakt med din körning.

Fråga 8.2. Kan du se något fall där malloc har återanvänt ett minnesutrymme som programmet har återlämnat med free?

Fråga 8.3. De flesta versioner av malloc avrundar den adress som ska returneras, så att adressen blir jämnt delbar med någon viss tvåpotens: 4, 8, 16, 32 eller liknande. Har malloc avrundat adressen vid din provkörning?

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 29

another byte

1 byte

etcetera ...

MA03: Main array malloc

g-count malloc

free( gcountp );

Write address here: _0x401a20____

main array, size = 48 bytes

main array, size = 48 bytes (still there) 4bytes

0x401a58

0x401a4f

main array, size = 48 bytes (still there)

main array, size = 48 bytes (still there)

0x401a50

Exempel på hur du fyller i figuren på nästa sida. Obs! Den malloc som finns i din dator kan vara helt annorlunda än den som exemplet visar. Din teckning ska stämma med din dator.

Page 30: Hemlaboration C Maskinnära programmering med C

Dynamisk minneshantering – utskrifter som ska vara med vid redovisningen

● ifylld figur (här ovanför), eller motsvarande figur på separat papper

● utskrift från körning av filen malloc.c

När du har gjort klart dessa utskrifter, sätt kryss i rutan i marginalen.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 30

MA03: Main array malloc

g-count malloc

free( gcountp );

MA06: Cowabunga array malloc

g-count malloc

free( gcountp );

MA09: free( arrayp );

g-count malloc

free( gcountp );

MA10: free( extrap );

Write address here: ______________

main array, size = 48 bytes

main array, size = 48 bytes (still there)

Page 31: Hemlaboration C Maskinnära programmering med C

ASCII-tabell – hexadecimala värden och motsvarande ASCII-tecken0x00 NUL

0x01 SOH

0x02 STX

0x03 ETX

0x04 EOT

0x05 ENQ

0x06 ACK

0x07 BEL

0x08....BS

0x09....HT

0x0A. . .LF

0x0B...VT

0x0C....FF

0x0D...CR

0x0E. . .SO

0x0F.....SI

0x10 DLE

0x11 DC1

0x12 DC2

0x13 DC3

0x14 DC4

0x15 NAK

0x16 SYN

0x17 ETB

0x18 CAN

0x19...EM

0x1a SUB

0x1b ESC

0x1c.....FS

0x1d....GS

0x1e....RS

0x1f... .US

0x20... .SP

0x21.......!

0x22......."

0x23.......#

0x24.......$

0x25.....%

0x26......&

0x27........'

0x28.......(

0x29.......)

0x2a.......*

0x2b.......+

0x2c........,

0x2d.......-

0x2e....... .

0x2F......./

0x30.......0

0x31.......1

0x32.......2

0x33.......3

0x34.......4

0x35.......5

0x36.......6

0x37.......7

0x38.......8

0x39.......9

0x3a........:

0x3b........;

0x3c.......<

0x3d.......=

0x3e.......>

0x3f........?

0x40.....@

0x41......A

0x42......B

0x43......C

0x44......D

0x45......E

0x46.......F

0x47......G

0x48......H

0x49.......I

0x4a.......J

0x4b......K

0x4c.......L

0x4d.....M

0x4e......N

0x4f.......O

0x50.......P

0x51......Q

0x52......R

0x53.......S

0x54......T

0x55......U

0x56......V

0x57.....W

0x58......X

0x59......Y

0x5a.......Z

0x5b.......[

0x5c........\

0x5d.......]

0x5e.......^

0x5f......._

0x60.......`

0x61.......a

0x62.......b

0x63.......c

0x64.......d

0x65.......e

0x66.......f

0x67.......g

0x68.......h

0x69........i

0x6a........j

0x6b.......k

0x6c........l

0x6d......m

0x6e.......n

0x6f.......o

0x70.......p

0x71.......q

0x72.......r

0x73.......s

0x74........t

0x75.......u

0x76.......v

0x77......w

0x78.......x

0x79.......y

0x7a.......z

0x7b.......{

0x7c........|

0x7d.......}

0x7e.......~

0x7f DEL

NUL = nolltecken, används som utfyllnad.BEL = bell, får datorn att pipa när det skrivs ut.BS = backspace, stegar markören vänster ett steg.LF = line feed, stegar markören rakt nedåt till nästa rad (utan att gå till vänsterkanten).FF = form feed, börjar på ny sida vid utskrift (fungerar på äldre skrivare, ibland också på skärmen).CR = carriage return, stegar markören till början på raden (utan att byta rad).ESC = escape, inleder en sekvens av speciella styrkommandon.DEL = delete, kan ibland användas för att sudda ett teckenSP = space, mellanslag.

SOH, STX, ETX, EOT, ENQ, ACK, HT, VT, SO, SI, DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, FS, GS, RS, US är styrtecken som inte används i denna laboration.

När du har läst hela detta lab-PM, sätt kryss i rutan i marginalen.

Tidigare i lab-PM finns rutor att kryssa i som påminnelser om att ta med dokumentation till redovisningen. Om någon dokumentation saknas vid redovisningen så krävs komplettering av dokumentationen och kunskaperna, följt av ny redovisning.

Om det saknas kryss i någon ruta, så har du alltså glömt någon dokumentation som behövs för att du ska kunna redovisa.

IS1200/IS1500 Hemlab C: Maskinnära programmering med C sida 31