Lunedì 23 e giovedì 26 ottobre 2017 (Lezione 7 - 150 min) - Demetrescu/Coppa
Esercizio 1
Scrivere una funzione
void cancspazi(char* s) che elimina tutti gli spazi da una stringa
s e tradurla poi in IA32. Scrivere la soluzione nel file
es2.s.
Usare il seguente programma di prova:
#include <stdio.h>
void cancspazi
(char* s
);
int main
() {
char s1
[] =
"obi wan kenobi ";
char s2
[] =
"obiwankenobi";
char s3
[] =
" leila luke ";
char s4
[] =
"";
cancspazi
(s1
);
cancspazi
(s2
);
cancspazi
(s3
);
cancspazi
(s4
);
printf("\"%s\" (corretto: \"obiwankenobi\")\n", s1
);
printf("\"%s\" (corretto: \"obiwankenobi\")\n", s2
);
printf("\"%s\" (corretto: \"leilaluke\")\n", s3
);
printf("\"%s\" (corretto: \"\")\n", s4
);
return 0;
}
Compilare come al solito con
gcc -m32 -g es2.s es2-main.c -o es2. In caso di problemi debuggare con gdb.
Soluzione:
# void cancspazi(char* s) {
# char* p = s;
# do if (*s!=' ') *p++ = *s;
# while (*s++!=0);
# }
.globl cancspazi
cancspazi: # s <-> eax, p <-> ecx
movl 4(%esp), %eax # eax = s
movl %eax, %ecx # ecx = p = s
jmp S # goto S
L: incl %eax # s++
S: movb (%eax), %dl # dl = *s
cmpb $32, %dl # if (dl == ' ')
je L # goto L
movb %dl, (%ecx) # *p = dl
incl %ecx # p++
testb %dl, %dl # if (dl!=0)
jne L # goto L
ret
Esercizio 2 (compito C, esonero 2016/2017)
void arrayCrossMean(unsigned* x, unsigned* y, unsigned* z, unsigned n) {
unsigned* end = x+n;
y = y+n-1;
while (x < end) {
*z = *x + *y;
if (*z) *z = (*z) >> 1;
x++, z++, y--;
}
}
#include <stdio.h>
void arrayCrossMean
(unsigned* x,
unsigned* y,
unsigned* z,
unsigned n
);
void printArray
(unsigned* v,
unsigned n
) {
printf("{");
int i =
0;
for (i=
0; i<n
-1; ++i
)
printf("%u, ", v
[i
]);
printf("%u", v
[i
]);
printf("}");
}
int main
() {
unsigned z
[5];
unsigned x1
[4] =
{1,
2,
0,
4};
unsigned y1
[4] =
{2,
0,
3,
5};
printf("Test 1:\nx: ");
printArray
(x1,
4);
printf("\ny: ");
printArray
(y1,
4);
arrayCrossMean
(x1, y1, z,
4);
printf("\nz: ");
printArray
(z,
4);
printf("\nRisultato atteso:\nz: {3, 2, 0, 3}\n");
unsigned x2
[5] =
{0,
7,
1,
0,
3};
unsigned y2
[5] =
{2,
0,
1,
2,
1};
printf("\nTest 2:\nx: ");
printArray
(x2,
5);
printf("\ny: ");
printArray
(y2,
5);
arrayCrossMean
(x2, y2, z,
5);
printf("\nz: ");
printArray
(z,
5);
printf("\nRisultato atteso:\nz: {0, 4, 1, 0, 2}\n");
return 0;
}
Soluzione:
void arrayCrossMean(unsigned* x, // x <-> eax
unsigned* y, // y <-> ebx
unsigned* z, // z <-> ecx
unsigned n) {
unsigned temp; // temp <-> esi
unsigned* end = x; // end <-> edx
end += n;
y += n;
y--;
L: if (x >= end) goto E;
temp = *x;
temp += *y;
*z = temp; // *x + *y
if (temp == 0) goto F;
*z >>= 1; // *z = (*z) >> 1
F: x++;
z++;
y--;
goto L;
E: ;
}
.globl arrayCrossMean
arrayCrossMean:
# void arrayCrossMean(unsigned* x, // x <-> eax
# unsigned* y, // y <-> ebx
# unsigned* z, // z <-> ecx
# unsigned n) {
pushl %ebx # prologo
pushl %esi
movl 12(%esp), %eax # carico x
movl 16(%esp), %ebx # carico y
movl 20(%esp), %ecx # carico z
# unsigned temp; // temp <-> esi
movl %eax, %edx # unsigned* end = x; // end <-> edx
movl 24(%esp), %esi
imull $4, %esi # esi == 4*n
addl %esi, %edx # end += n;
addl %esi, %ebx # y += n;
subl $4, %ebx # y--;
L: cmpl %edx, %eax # if (x >= end)
jae E # goto E;
movl (%eax), %esi # temp = *x;
addl (%ebx), %esi # temp += *y;
movl %esi, (%ecx) # *z = temp; // *x + *y
testl %esi, %esi # if (temp == 0)
je F # goto F;
shrl (%ecx) # *z >>= 1; // *z = (*z) >> 1
F: addl $4, %eax # x++;
addl $4, %ecx # z++;
subl $4, %ebx # y--;
jmp L # goto L;
E: popl %esi # epilogo
popl %ebx
ret
Suggerimento: semplificare la soluzione sopra usando l'istruzione LEA.