Presentation laddar. Vänta.

Presentation laddar. Vänta.

William Sandqvist Datorteknik övning 3 stackhantering subrutin som anropar subrutin programutveckling.

Liknande presentationer


En presentation över ämnet: "William Sandqvist Datorteknik övning 3 stackhantering subrutin som anropar subrutin programutveckling."— Presentationens avskrift:

1 William Sandqvist william@kth.se Datorteknik övning 3 stackhantering subrutin som anropar subrutin programutveckling

2 William Sandqvist william@kth.se Datorteknik övning 3

3 William Sandqvist william@kth.se Laborationerna

4 2.6 Hur anropas mul10() ? William Sandqvist william@kth.se tal = mul10(43); Anrop i C-program: movi r4, 43 # parameter i R4 call mul10 # call subrutin movia r8, tal # adressen till ”tal” i R8 stw r2,0(r8) # lagra resultat vid ”tal:”... mul10: slli r10,r4,3 # skifta tre steg (ggr 8) slli r11,r4,1 # skifta ett steg (ggr 2) add r2,r10,r11 # addera i returvärdesregistret R2 ret # returnera Assemblerprogram:

5 William Sandqvist william@kth.se 3.1 Stackoperationer a) Visa hur en stack fungerar. b) Ge exempel på hur man med befintliga instruktioner för Nios- II kan utföra stackoperationerna PUSH reg och POP reg. c) Skriv makron för operationerna PUSH reg och POP reg.

6 William Sandqvist william@kth.se Stack  En stack är en datastruktur  LIFO Last in – first out (som att lägga tallrikar på en tallrikstrave).  Hela stacken kan läsas, men bara det senast inlagda värdet kan tas bort. Stacken har den egenskapen att den vänder på ordningen på data.

7 William Sandqvist william@kth.se Stackpekare Ett register, stackpekaren, innehåller adressen till det senast inlagda värdet.

8 William Sandqvist william@kth.se push – inläggning på stack 1)Stackpekaren minskas med 4 Byteadresser – så att den pekar på lediga platsen 2)Skriv data på lediga platsen

9 William Sandqvist william@kth.se pop – borttagning från stack 1)Läs värdet 2)Öka stackpekaren med 4 Byteadresser. Värdet ligger kvar i minnet men kommer att ”skrivas över” vid nästa push på denna adress.

10 William Sandqvist william@kth.se Makron Med makron för push och pop är det mindre risk att man hanterar stackpekaren på ett inkonsekvent sätt..macro PUSH reg subi sp,sp,4 stw \reg, 0(sp).endm.macro POP reg ldw \reg, 0(sp) addi sp,sp,4.endm

11 William Sandqvist william@kth.se Behövs PUSH/POP ? Nios II kan använda indexerad operandutpekning och offset-värden för att nå alla data på stacken relativt stackpekaren. Då behövs det bara hälften så många instruktioner för att hantera stacken jämfört med push/pop, eftersom offset beräknas vid kompileringen. sp Medan en kompilator kan ”hålla reda på” var på stacken den lagrat olika data, så är det vi som laboranter som behöver ett enkelare system, det vill säga push/pop. Vid laborationerna väger den prestandaförlusten lätt!

12 William Sandqvist william@kth.se 3.2 Subrutinanrop i flera nivåer Vilka speciella åtgärder måste vidtagas om man gör ett subrutinanrop i en subrutin? Kallas även för inkapslad subrutin eller nested procedure.

13 William Sandqvist william@kth.se Returaddress Returadressen lagras i register R31

14 William Sandqvist william@kth.se Subrutin i flera nivåer Hur går det nu med första returadressen?

15 William Sandqvist william@kth.se Returadress på stacken En subrutin som anropar en annan subrutin måste lägga sin egen returadress på stacken före anropet.

16 William Sandqvist william@kth.se push r31 1)Minska stackpekarens värde med 4 -så att den pekar ut nästa lediga plats 2)Skriv data -innehållet i R31kopieras till nya platsen

17 William Sandqvist william@kth.se Subrutinstruktur

18 William Sandqvist william@kth.se 3.3 Subrutin med värdeanrop Skriv välkommenterad Nios-II assemblerkod för en subrutin sumv() som adderar två 32-bitars heltal vars värden lagrats i register R4 och R5 innan anropet av sumv(). Resultatet av beräkningarna skall finnas i register R2 efter returhopp från sumv(). Nedan visas hur motsvarande C programkod ser ut. Handkompilera denna kod till assemblerkod för Nios-II. int sumv(int x, int y) { return x+y; }

19 William Sandqvist william@kth.se värdeanrop.global sumv sumv: add r2,r4,r5 ret int sumv(int x, int y) { return x+y; } R2R4 R5 Värdeanrop. Det anropande programmet skickar med (kopior) av variabelvärden som parametrar i R4 och R5. Call-by value

20 William Sandqvist william@kth.se 3.4 Huvudprogram med värdeanrop Skriv välkommenterad Nios-II assemblerkod för ett huvudprogram som använder subrutinen sumv(), se föregående uppgift, för att addera två heltal. Nedan visas ett exempel på hur ett sådant C-program kan se ut. Handkompilera denna kod till assemblerkod för Nios-II int a, b, res; extern int sumv(int, int); int main(void) { a = 3; b = 4;... res = sumv(a, b);... return 0; }

21 William Sandqvist william@kth.se assembler.data.align 2 a:.word 0 b:.word 0 res:.word 0.text.align 2.include ”../mymacro.s” Kompilering sker i en undermapp därför måste sökvägen till filen med makron (tex PUSH och POP) anges med../

22 William Sandqvist william@kth.se assembler … main skall returnera till startup-koden här returneras till startup-koden sumv får använda r8 (titta efter om den gör det?).global main main: PUSH r31 # spara mains returadress movia r8,a # basadress till variabler movi r9,3 stw r9,0(r8) # global a=3 movi r9,4 stw r9,4(r8) # global b=4... ldw r4,0(r8) # a i R4 ldw r5,4(r8) # b i R5 PUSH r8 # caller-save R8 call sumv POP r8 # restore R8 stw r2,8(r8) # returvärde till global res mov r2,r0 # main skall returnera 0 POP r31 # återställ mains returadress ret

23 William Sandqvist william@kth.se Denna gång använde subrutinen bara R4 R5 och R2, så det var onödigt att spara R8 på stacken. Sådant kan man bara veta om man skrivit alla program själv.

24 William Sandqvist william@kth.se 3.5 Subrutin med referensanrop Skriv välkommenterad Nios-II assemblerkod för en subrutin suma() som adderar två 32-bitars heltal vars adresser lagrats i register R4 och R5 före anropet av suma(). Resultatet av beräkningen skall finnas i register R2 efter returhopp från suma(). Nedan visas hur motsvarande C-programkod ser ut Handkompilera denna kod till assemblerkod för Nios-II int suma(int* x, int* y) { return (*x + *y); }

25 William Sandqvist william@kth.se pekare * adress & och avreferering * int b; Deklaration av heltalsvariabeln b. Plats reserveras. b = 18; Definition av variabeln b. Nu innehåller den talet 18. &b Adressoperatorn. Adressen till variabeln b. int * c; Deklaration av int-pekarvariabeln c. c = &b; Nu pekar c på b. *c Avrefereringsoperatorn. Det som c pekar på. *c = 19; Talet 19 lagras på den plats som c pekar ut. Nu innehåller b = 19. Kort om C-språkets pekare 18 ( ) 18 ( ) 19 ( )

26 William Sandqvist william@kth.se referensanrop.global suma suma: ldw r8,0(r4) ldw r9,0(r5) add r2,r8,r9 ret int suma(int* x, int* y) { return (*x + *y); } R2R4R5 ( )

27 William Sandqvist william@kth.se 3.6 Huvudprogram med referensanrop Skriv välkommenterad Nios-II assemblerkod för ett huvudprogram som använder subrutinen suma(), se föregående uppgift, för att addera två heltal. Nedan visas ett exempel på hur ett sådant C-program kan se ut. Handkompilera denna kod till assemblerkod för Nios-II int a, b, res; extern int suma(int*, int* ); int main(void) { a = 3; b = 4;... res = suma(&a, &b);... return 0; } 3 4

28 William Sandqvist william@kth.se assembler.data.align 2 a:.word 0 b:.word 0 res:.word 0.text.align 2.include ”../mymacro.s” Precis som tidigare …

29 William Sandqvist william@kth.se assembler ….global main main: PUSH r31 # spara mains returadress movia r8,a # basadress till variabler movi r9,3 stw r9,0(r8) # global a=3 movi r9,4 stw r9,4(r8) # global b=4... mov r4,r8 # adress till a i R4 addi r5,r8,4 # adress till b i R5 PUSH r8 # caller-save R8 call suma POP r8 # restore R8 stw r2,8(r8) # returvärde till global res mov r2,r0 # main skall returnera 0 POP r31 # återställ mains returadress ret Tur att vi sparar R8, suma använder både R8 och R9 !

30 William Sandqvist william@kth.se Varför värdeöverföring?  Undvika sidoeffekter (som globala variabler kan ha) Om man i ett stort projekt upptäcker att en global variabel plötsligt har ett oväntat värde, så är alla misstänkta. Vilken funktion som helst når den globala variabeln och kan ha utfört ändringen. Det hade aldrig varit möjligt att skriva UNIX i C om globala variabler hade använts annat än undantagsvis.

31 William Sandqvist william@kth.se Varför referensöverföring?  Undvika sidoeffekter (som globala variabler kan ha)  Flera returvärden än ett enda är möjligt (retur genom parameterlistan)  Överföring av dataposter som inte rymms i register ( arrayer, strängar, struct )  Möjligt att skriva generella funktioner som opererar på valfria datatyper.

32 William Sandqvist william@kth.se 3.7 programutveckling

33 William Sandqvist william@kth.se 3.8 Minnesdisposition Gles adressrymd Endast en liten del av minnet är utbyggt. (vanligt för inbyggda system) Stackpekaren initieras av startup- koden så det behöver inte (=ska inte) Du göra code motsvarar.text Mellan adresserna 0x800 till 0xA20 finns I/O- kretsar – med allt det roliga på DE2-kortet

34 William Sandqvist william@kth.se 3.10 Labprogram Funktionsprototyper i C beskriver vad funktionerna heter och hur de används. int hexasc(int digit); void puttime(int* timeloc); void tick(int* timeloc); void delay(int millisec);

35 William Sandqvist william@kth.se hexasc() int hexasc(int digit); Inparameter ett tal mellan 0 och 15 (om inte, ”maska” till rätt storlek) Returvärde ett 7-bitarstal motsvarande ASCII-koden för tecknet 0…9...A...F Tips: siffrorna 0..9 har ASCII-koder i nummerordning därför är: ’3’ = ’0’ + 3; /* kompilatorn kan ”slå upp” ASCII-koderna */

36 William Sandqvist william@kth.se ASCII-tabellen http://ascii-table.com/ Ett tecken lagras i en Byte. Hej! 48 65 6A 21 01001000 01100101 01101010 00100001

37 William Sandqvist william@kth.se timeloc global variabel för tiden

38 William Sandqvist william@kth.se tick() räkna upp med ett (klockmässigt)

39 William Sandqvist william@kth.se tick()

40 William Sandqvist william@kth.se tick() klockmässighet

41 William Sandqvist william@kth.se void tick( unsigned int * timep ) { /* Get current value, store locally */ register unsigned int t = * timep; t += 1; /* Increment local copy */ /* If result was not a valid BCD-coded time, adjust now */ if( (t & 0x0000000f) == 0x0000000a ) t += 0x00000006; if( (t & 0x000000f0) == 0x00000060 ) t += 0x000000a0; /* Seconds are now OK */ if( (t & 0x00000f00) == 0x00000a00 ) t += 0x00000600; if( (t & 0x0000f000) == 0x00006000 ) t += 0x0000a000; /* Minutes are now OK */ if( (t & 0x000f0000) == 0x000a0000 ) t += 0x00060000; if( (t & 0x00ff0000) == 0x00240000 ) t += 0x00dc0000; /* Hours are now OK */ if( (t & 0x0f000000) == 0x0a000000 ) t += 0x06000000; if( (t & 0xf0000000) == 0xa0000000 ) t = 0; /* Days are now OK */ * timep = t; /* Store new value */ } Vid lab1 kan Du använda given funktion tick() skriven i C. Förstår Du koden?

42 William Sandqvist william@kth.se tick() Strukturdiagram Strukturdiagram för tick() till en ”minut:sekund” -klocka

43 William Sandqvist william@kth.se 3.11 Biblioteksrutiner int putchar(int ch); Ett tecken i R4 sänds ut på jtag_uart och visas i Nios-II IDE Consol fönster. Om allt gick bra returneras i R2 samma tecken som sändes. Detta är ”statusinformation”, men man behöver inte ta hand om detta returvärde.

44 William Sandqvist william@kth.se 3.12 Fördröjningsrutin Det behövs en subrutin wait() som medför att instruktionen call wait tar cirka 100 ms att exekvera. Nios II har klockfrekvensen 50 MHz. Körtiden approximeras genom att varje instruktion antas ta en klockcykel. wait() måste återlämna alla register oförändrade.

45 William Sandqvist william@kth.se exekveringstid

46 William Sandqvist william@kth.se 3.13 Varierbar fördröjningstid void waitx(int n); R4 R2 Onödigt! vi vet att vår wait inte använder R4, utan bara R8.

47 William Sandqvist william@kth.se 3.14 Assemblerdirektiv.include ”fil.ext” # infogar fil.ext.data # nu kommer datareservationer.text # programkod.global main # main blir synlig globalt (”public”).align 3 # nästa adress ska vara delbar med 2 3 B:.string ”hej 17” # lagra ASCII-sträng C:.ascii”tjoho” # lagra ASCII D:.asciz ”plusnul” # ASCII avslutad med NUL TAL:.byte 0x01 # reservera 1 byte med värde 0x01.equ ExcBase,0x20020# def. symbol namn TIME:.word 0x5957 # 32 bitar med värde KOLON:.byte ’:’#ascii för kolon lagras


Ladda ner ppt "William Sandqvist Datorteknik övning 3 stackhantering subrutin som anropar subrutin programutveckling."

Liknande presentationer


Google-annonser