Esercizi traduzione da C ad Assembly IA32 (A.A. 2016-17)
Si vedano le discussioni e le soluzioni sul
forum. Alcuni esercizi sono risolti
qui.
Esercizio 1 (Assegnamento e calcolo di espressioni)
Tradurre in IA32 il seguente frammento C, mantenendo la variabile x nel registro A:
short x=(20-2)*(7+3)+2*(10-7);
Se si ritiene che servano registri di appoggio per il calcolo dell'espressione, usare preferibilmente i registri C e/o D.
- Suggerimento: come visto a lezione, strutturare la traduzione C -> IA32 in due passi: prima riformulare il programma C in una forma equivalente in cui ogni istruzione ha al più due operandi, e poi effettuare la traduzione in IA32. Ad esempio, riscrivere int x=2+5 (che ha tre operandi x, 2 e 5) come: int x=2; x=x+5, che può essere poi immediatamente tradotto nelle due istruzioni: movl $2, %eax e addl $5, %eax.
Esercizio 2 (Invocazione funzione IA32 da programma C)
Provare il funzionamento della soluzione dell'Esercizio 1 considerandola parte di una funzione:
short es2() {
short x=(20-2)*(7+3)+2*(10-7);
return x;
}
Scrivere un file
es2.s che contiene la traduzione IA32 della funzione C
es2. Compilare il programma insieme al main di prova, ricordando che il valore restituito da una funzione per convenzione è contenuto nel registro A:
#include <stdio.h>
short es2
();
// prototipo per la funzione definita nel modulo es2.s
int main
() {
short z = es2
();
printf("es2() -> %hd\n", z
);
// stampa contenuto variabile z
return 0;
}
Per compilare il programma, usare
gcc es2_main.x es2.s -o es2, che genera un eseguibile
es2.
Esercizio 3 (Accesso a parametri interi di una funzione)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
quadrato.s:
int quadrato(int x) {
return x*x;
}
Usare il seguente programma di prova:
#include <stdio.h>
int quadrato
(int x
);
int main
() {
printf("quadrato(8)=%d\n", quadrato
(8));
// deve stampare 64
return 0;
}
Esercizio 4 (Costrutto if: valore assoluto)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
abs.s:
int abs(int x) {
if (x<0) x = -x;
return x;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui l'
if (...) istruzione viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 5 (Costrutto if...else: valore assoluto)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
abs2.s:
int abs2(int x) {
if (x>=0) return x;
else return -x;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui l'
if (...) istruzione viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 6 (Costrutto if..else: differenza in valore assoluto)
Si traduca in Assembly IA32 la seguente funzione C che calcola il valore assoluto della differenza dei parametri, scrivendo un modulo
mod.s:
int mod(int x, int y) {
if (x>=y) return x-y;
else return y-x;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui l'
if (...) istruzione viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 7 (Accesso a parametri puntatore di una funzione)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
raddoppia.s:
void raddoppia(int* p) {
*p = *p * 2;
}
Si tenga presente che l'istruzione
imul deve avere come operando destinazione necessariamente un registro. Usare il seguente programma di prova:
#include <stdio.h>
void raddoppia
(int* p
);
int main
() {
int x =
15;
raddoppia
(&x
);
printf("x=%d\n", x
);
// deve stampare 30
return 0;
}
Esercizio 8 (Array con indice costante)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
get_second.s:
short get_second(short* v, int n) { // v è un array, n è la lunghezza dell'array
short a = -1;
if (n>=2) a=v[1];
return a;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui l'
if (...) istruzione viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 9 (Costrutto while: azzeramento di un array)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
clear.s:
void clear(char* v, unsigned n) { // v è un array, n è la lunghezza dell'array
unsigned i=0;
while (i<n) v[i++]=0;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui il
while viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 10 (Costrutto while: azzeramento di un array - variante)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
clear2.s:
void clear2(char* v, unsigned n) { // v è un array, n è la lunghezza dell'array
char* p=v+n;
while (v<p) *v++=0;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui il
while viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 11 (Calcolo lunghezza di una stringa)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
mystrlen.s:
unsigned mystrlen(const char* s) { // s è una stringa terminata da un terminatore a zero
unsigned n = 0;
while (*s++) n++;
return n;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui il
while viene rimpiazzato da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 12 (Costrutto for)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
sum.s:
short sum(short* v, unsigned n) {
unsigned i;
short s = 0;
for (i=0; i<n; ++i) s += v[i];
return s;
}
Si ricordi che il valore di ritorno di una funzione è sempre a 32 bit per gli interi (
char e
short vengono quindi promossi a
int) e viene passato in
eax. Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui il
for viene rimpiazzato da un
while, e poi il
while da un
if (...) goto. Scrivere un programma di prova per testare la funzione IA32.
Esercizio 13 (Somma di matrice)
Si traduca in Assembly IA32 la seguente funzione C, scrivendo un modulo
matsum.s:
int matsum(int** v, int n) {
int i, j, s = 0;
for (i=0; i<n; ++i)
for (j=0; j<n; ++j)
s += v[i][j];
return s;
}
Si suggerisce di riscrivere dapprima il programma in una forma C equivalente in cui il
for viene rimpiazzato da un
while, e poi il
while da un
if (...) goto. Usare il seguente programma di prova:
#include <stdio.h>
#include <stdlib.h>
#define N 10
int matsum
(int** v,
int n
);
int main
() {
int i, j, **v = malloc
(N*
sizeof(int*
));
for (i=
0; i<N; ++i
) {
v
[i
] = malloc
(N*
sizeof(int));
for (j=
0; j<N; ++j
) v
[i
][j
] =
2;
}
int s = matsum
(v, N
);
printf("somma=%d (corretto: 200)\n", s
);
for (i=
0; i<N; ++i
) free
(v
[i
]);
return 0;
}
Esercizio 14 (Frequenza caratteri)
Scrivere una funzione C
void charfreq(const char* text, unsigned* freq) che calcola per ogni carattere ASCII il suo numero di occorrenze nella stringa
text. Il risultato va scritto nell'array
freq, che si assume abbia 256 celle. Tradurre poi la funzione scritta in assembly IA32, scrivendo un modulo
charfreq.s. Si usi il seguente programma di prova:
#include <stdio.h>