Università degli Studi di Firenze, Scuola di Ingegneria – Corso di Laurea in Ingegneria Informatica – Prof.
Stefano Berretti
Fondamenti di Informatica
PRIMA PROVA IN ITINERE – testo C – 23 novembre 2022
Esercizio 1. (6 punti) (codifica operandi 2pt ciascuno, somma 1 pt, discussione 1pt)
Data la dichiarazione float x; e le istruzioni x=4.0 e x+=2; scrivere la codifica IEEE 754 di x e della costante
2 ed il risultato dell’istruzione di somma. Discutere il risultato ottenuto.
Esercizio 2. (5 punti) (operazioni da e verso la memoria 2pt, logica 3pt)
Tradurre in codice assembler MIPS la seguente istruzione C: min = A[j] < B[j]+1 ? A[j] : 0;
nell’ambito delle seguenti dichiarazioni:
int min, A[20], B[20], j;
Ipotizzare che le variabili siano allocate in memoria a partire dall'indirizzo 200.
Esercizio 3. (9 punti) (verifica legalità 5pt, produzioni 2 pt, semantica 2pt)
Data la seguente istruzione:
do B[i]+=A[i]+3; while( ++i<20 );
nell’ambito delle seguenti dichiarazioni:
int A[20], B[20], i=0; (ipotizzare tutti gli elementi di A e B inizializzati a 0)
verificarne la legalità riportando anche le produzioni della grammatica C utilizzate nella riduzione. Discutere la
semantica dell’istruzione riportando il valore delle variabili dopo l’esecuzione dell’istruzione.
Esercizio 4. (10 punti) (prototipo e parametri formali 3 pt, logica 7 pt)
Scrivere la funzione C che riceve in ingresso un array A di valori interi, di dimensione N, ed un valore target,
ed opera nel modo seguente:
• Ridispone gli elementi di A in modo che prima ci siano gli elementi minori o uguali a target e poi
quelli maggiori;
• Alloca un array V e copia gli elementi di A minori o uguali a target in V;
• Ritorna l’array V tra i parametri formali.
(Esempio: A={9,5,8,7,3,1,4,2}, target=3, N=8 --> A={2,1,3,7,8,5,4,9}, V={2,1,3})
Università degli Studi di Firenze, Scuola di Ingegneria – Corso di Laurea in Ingegneria Informatica – Prof. Stefano Berretti
Soluzione
Esercizio 1. (6 punti)
La variabile float x=4.0 è codificata su 32 bit in formato IEEE 754.
Forma esponenziale binaria del numero 4.0: 100.0 * 2^0
Forma normalizzata: 1.00 * 2^2
Codifica della caratteristica c=2 come esponente in eccesso +127: e = 2+127 = 129 → 10000001
Codifica IEEE 754: 0 10000001 00000000000000000000000
La costante +2 è codificata su 32 bit in formato IEEE 754.
Forma esponenziale binaria del numero 2: 10.0 * 2^0
Forma normalizzata: 1.0 * 2^1
Codifica della caratteristica c=1 come esponente in eccesso +127: e = 1+127 = 128 → 10000000
Codifica IEEE 754: 0 10000000 00000000000000000000000
Per eseguire la somma la caratteristica del minore è allineata a quella del maggiore ed un numero di bit doppio (46) è
usato per la somma delle mantisse (qui non sono mostrati per brevità)
(1.00000000000000000000000 + 0.10000000000000000000000) * 2^2 = (1.10000000000000000000000) * 2^2
La mantissa è troncata a 23 ed il numero rinormalizzato se necessario. In questo caso è già normalizzato e la
rappresentazione finale risulta: 0 10000001 10000000000000000000000
Esercizio 2. (5 punti)
Istruzione C: min = A[j] < B[j]+1 ? A[j] : 0
addi $1, $0, 0 // $1 usato per indice j
….
lw $2, 204[$1] // carica A[j] nel registro $2
lw $3, 284[$1] // carica B[j] nel registro $3
addi $3, $3, 1 // somma 1 al registro $3
slt $4, $2, $3 // pone $4 ad 1 se $2 < $3
beq $4, $0, min0 // se $4 è 0 la min è assegnato con 0, altrimenti con A[j]
sw $2, 200[$0] // memorizza A[j] nella variabile min
j cont // continua dall’istruzione successiva
min0: sw $0, 200[$0] // memorizza il valore 0 nella variabile min
cont: ….
Esercizio 3. (9 punti)
Albero sintattico:
do B[i] += A[i]+3; while( ++i<20 );
do <id>[<id>] += <id>[<id>] + <const>; while( ++<id> < <const> );
do <var>[<var>] += <var>[<var>] + <expr>; while( ++<var> <op2><expr> );
do <expr>[<expr>] <op2>= <expr>[<expr>] <op2><expr>; while( <expr><op2><expr> );
do <var><op2>= <var><op2><expr>; while( <expr> );
do <var><op2>= <expr><op2><expr>; while( <expr> );
do <var><op2>=<expr>; while( <expr> );
do <expr>; while( <expr> );
do <statement> while( <expr> );
<statement>
Università degli Studi di Firenze, Scuola di Ingegneria – Corso di Laurea in Ingegneria Informatica – Prof. Stefano Berretti
L'istruzione è legale dato che è possibile passare dai simboli terminali al simbolo iniziale della categoria sintattica delle
istruzioni <statement>.
Produzioni della grammatica usate nella derivazione dell’albero sintattico:
<var> ::= <id> | <expr>[<expr>]
<expr> ::= <const> | <var> | <expr><op2><expr> | ++<var> | <var><op2>=<expr>
<op2> ::= + | <
<statement> ::= <expr>; | do <statement> while( <expr> );
La semantica dell’istruzione do <statement> while( <expr> ); consiste nel calcolo dell’istruzione <statement>,
nella successiva verifica dell’espressione di guardia e nell’applicazione dei suoi eventuali side effect: se l’espressione
restituisce un valore vero (!=0) allora il controllo è trasferito all’istruzione <statement>; altrimenti il controllo è trasferito
all’istruzione che segue while. Nel caso particolare, ci sono due side effect: alla variabile B[i] è assegnato il valore 3, ed
alla variabile i il valore 1
Esercizio 4.
#define TRUE 1
#define FALSE 0
typedef unsigned short int Boolean;
Boolean array_divide(int * A, int N, int target, int ** V) {
int l, r, tmp;
l=0, r=N-1;
while( l < r ) {
while( l < r && A[l] <= target )
l++;
while( r > l && A[r] > target )
r--;
if( r != l) { // swap
tmp = A[l];
A[l] = A[r];
A[r] = tmp;
}
}
// allocazione array V
*V = (int *) malloc(sizeof(int)*l);
if( *V == NULL )
return FALSE;
for(r=0; r<l; r++)
(*V)[r] = A[r];
return TRUE;
}