INF2270 L?sningsforslag oppgaver uke 11 (9.-13.3.2009) Oppgave 1 void strrev (char *s) { char *t = s + strlen(s)-1; while (s < t) { char temp = *s; *s = *t; *t = temp; ++s; --t; } } Oppgave 2 Det er lurt ? dele problemet i to: 1. Finn slutten av teksten. 2. Bytt om tegnene. .globl strrev # Navn: strrev. # Synopsis: Snur en tekst. # C-signatur: void strrev (char *s). strrev: push %ebp # Standard funksjonsstart movl %esp,%ebp movl 8(%ebp),%eax # %eax = s. movl %eax,%edx # %eax = s. # Finn slutten av teksten: scan: cmpb $0,(%edx) # while (*s jz found # != 0) { incl %edx # ++s. jmp scan # } found: decl %edx # --s. # Snu teksten: rev: cmpl %eax,%edx # while (s < t jbe ret # ) { movb (%eax),%cl # Bytt *s movb (%edx),%ch # og *t (med %cl og movb %ch,(%eax) # %ch som mellomlager). movb %cl,(%edx) # incl %eax # ++s. decl %edx # --t. jmp rev # } ret: pop %ebp # Standard retur. ret Oppgave 3 .globl summany # Navn: summany. # Synopsis: Summerer diverse heltall. Verdien 0 avslutter. # C-signatur: int summany (int a, ...). # Registre: %eax: sum (resultatet) # %edx: sp (peker til parametrene p? stakken) summany: push %ebp # Standard funksjonsstart movl %esp,%ebp movl $0,%eax # sum = 0. leal 8(%ebp),%edx # sp = %ebp+8 (f?rste parameter) # while ( loop: cmpl $0,(%edx) # *sp jz ret # != 0) { addl (%edx),%eax # sum += *sp. addl $4,%edx # sp = sp+4. (Neste parameter) jmp loop # } ret: pop %ebp # Standard retur. ret Oppgave 4 Feilen er at de to parametrene har omvendt rekkef?lge i funksjonen og testprogrammet. Oppgave 5 .globl arrayadd # Navn: arrayadd. # Synopsis: Summerer verdiene i en vektor. # C-signatur: int arrayadd (int a[], int n). # Registre: %eax: summen s? langt # %ecx: indeks til a (teller ned) # %edx: adressen til a arrayadd: pushl %ebp # Standard movl %esp,%ebp # funksjonsstart. movl $0,%eax # sum = 0. movl 12(%ebp),%ecx # ix = n. cmpl $0,%ecx # if (n == 0) je a_exit # goto a_exit. movl 8(%ebp),%edx # a. # for (ix=n; ix>0; --ix) { a_loop: addl -4(%edx,%ecx,4),%eax # sum += a[ix]. loop a_loop # } a_exit: popl %ebp # return sum. ret # Et par ting er verdt ? merke seg: 1) Siden loop avslutter n?r ECX er null, m? registeret ha verdiene n, n-1, ..., 1 gjennom l?kken (og ikke n-1, n-2, ..., 0 som versjonen p? forelesningen). Dette m? vi kompensere ved ? sette p? en ?-4? n?r vi skal ha tak i array-elementet. 2) Vi m? n? teste p? n==0 f?r vi starter l?kken; hvorfor? Oppgave 6 En C-l?sning: static short v = 1; int littleendian (void) { return *(char*)&v; } /* En alternativ l?sning: */ static union { short s; char c[2]; } v2; int littleendian2 (void) { v2.s = 1; return v2.c[0]; } ... og en i assembler: .globl littleendian # Navn: littleendian # Synopsis: Er denne maskinen ?little-endian?? # C-signatur: int littleendian (void). # Teknikk: Ser hvilken byte som er 1 i en short med verdi 1. littleendian: pushl %ebp # Standard movl %esp,%ebp # funksjonsstart. movl $0,%eax # Sett EAX til 0. movb v,%al # Hent venstre byte av v. popl %ebp # Standard ret # retur. .data v: .short 1