INF2270 L?sningsforslag oppgaver uke 14 (5.-9.4.2010) Oppgave 1 Forklaring: Vi kan l?se oppgaven ved ? dekode teksten tegn for tegn, men det finnes en enklere metode: Tell alle byte-ene men hopp over alle ?forlengelses-bytene? som alle er 10xxxxxx. int utf8_len (unsigned char *utf) { unsigned char *u = utf; int len = 0; while (*u != 0) { if ((*u & 0xc0) != 0x80) ++len; ++u; } return len; } .globl utf8_len # Name: utf8_len. # Synopsis: Finner lengden av en UTF8-tekst. # C-signatur: int utf8_len (unsigned char *utf) # Teknikk: Teller antall byte unntatt 10xxxxxx-byte. # Registre: EAX: Teller antall tegn # CL: Hver enkelt-byte i teksten # EDX: Peker til byte i teksten (?kes etterhvert) utf8_len: pushl %ebp # Standard movl %esp,%ebp # funksjonsstart. movl $0,%eax # Initi¨¦r EAX movl 8(%ebp),%edx # og EDX. ulen_l: movb (%edx),%cl # while ((CL = *(EDX incl %edx # ++)) cmpb $0,%cl # != 0) je ulen_x # { andb $0xc0,%cl # if ((CL & 0xc0) cmpb $0x80,%cl # != 0x80) je ulen_l # incl %eax # ++EAX; jmp ulen_l # } ulen_x: popl %ebp # Standard ret # retur. Oppgave 2 void rlcopy (char *to, char *from) { while (*from) { if (isdigit(*from)) { int n = *from-'0', i, c = *(from+1); for (i = 1; i <= n; ++i) *(to++) = c; from += 2; } else { *(to++) = *(from++); } } *to = 0; } .globl rlcopy # Navn: rlcopy # Synopsis: Kopiering med ekspansjon av run-length-koding # C-signatur: void rlcopy (char *to, char *from) # Registre: AL - arbeidsregister # CL - teller (ved ekspansjon) # DL - tegnet som ekspanderes # EDI - to (?kes etterhvert) # ESI - from (?kes etterhvert) rlcopy: pushl %ebp # Standard movl %esp,%ebp # funksjonsstart. pushl %esi # Gjem ogs? ESI pushl %edi # og EDI. movl 12(%ebp),%esi # Initi¨¦r ESI movl 8(%ebp),%edi # og EDI. rlc_l: cmpb $0,(%esi) # Kommer vi til 0-byten, jz rlc_done # er vi ferdige. cmpb $'0',(%esi) # Hvis neste tegn jb rlc_cp # ikke er et siffer cmpb $'9',(%esi) # (dvs '0'-'9'), ja rlc_cp # s? hopp til rlc_cp. # Ekspandering movb (%esi),%cl # Hent antallet. subb $'0',%cl # Konvert¨¦r til verdi. movb 1(%esi),%dl # Hent ogs? tegnet som skal kopieres. addl $2,%esi # rlc_exp: cmpb $0,%cl # S? lenge CL > 0: jle rlc_l # movb %dl,(%edi) # Kopi¨¦r tegnet. incl %edi # Oppdat¨¦r pekeren og decb %cl # telleren. jmp rlc_exp # G? i l?kke. # Kopiering rlc_cp: movb (%esi),%al # Hent neste tegn movb %al,(%edi) # og flytt det. incl %esi # Oppdat¨¦r incl %edi # pekerne. jmp rlc_l # Gjenta hovedl?kken. # Ferdig rlc_done: movb $0,(%edi) # Husk 0-byten! popl %edi # Hent tilbake EDI, popl %esi # ESI og popl %ebp # EBP. ret # Retur. Oppgave 3 # EAX = a EDX = b xorl %eax,%edx # EAX = a EDX = b^a = a^b xorl %edx,%eax # EAX = a^(a^b) = b EDX = a^b xorl %eax,%edx # EAX = b EDX = (a^b)^b = a Husk: ^ er XOR (i C-notasjon). Forklaring: N?r vi bruker XOR to ganger med samme maske, er vi tilbake der vi startet.