Esame di Calcolatori Elettronici Appello del 12/2/'03 (Telecomunicazioni) Esercizio 1) Realizzare in Assembler GNU la seguente funzione (scrivere sul file es1.s ed eseguire): struct st { int v[4]; char c[4]; }; extern "C" st f(st s, int v[4], char c[4]) { int i; st temp=s; for (i = 0; i < 4; i++) { if (s.v[i] > v[i]) v[i] =(int) (s.c[i]-c[i]); else temp.v[i] = (int) s.c[i]; c[i] = s.c[i]+(char)s.v[i]; temp.c[i]=c[i/2]; } return temp;} Esercizio 2) Realizzare quanto richiesto in C++ (scrivere sul file es2.cc ed eseguire). Siano date le seguenti dichiarazioni, contenute nel file cc.h: const int N = 4;const int C = 4;const int LUNG = 20; struct operazione { float importo; int data;}; struct conto { char nome [LUNG]; operazione oper [N]; int numOp; float totale;}; class gestcont { conto conti[C]; int primo; void stampaConto(const conto&); public: gestcont() { primo=0;} int apri(const char nome[]); bool oper(int numConto, float importo, int data); void build(const char nome[]); void interessi(); void stampa(); }; La classe gestcont realizza un sistema di gestione, molto semplificato, dei conto correnti di una banca. I campi importo e data della struttura operazione indicano, rispettivamente, l'importo prelevato o versato sul conto corrente, e la data dell'operazione (la data è espressa come numero di giorni trascorsi dall'inizio dell'anno e l'anno si considera composto da 365 giorni). I campi numOp e totale della struttura conto indicano, rispettivamente, il numero di operazioni effettuate durante un anno ed il denaro totale contenuto nel conto corrente. Il campo primo della classe gestcont individua l'indice del primo elemento vuoto del vettore conti. Realizzare: 1) la funzione membro apri() che apre un conto corrente al cliente il cui nome è passato come parametro (si faccia attenzione ad inizializzare correttamente i campi numOp e totale della struttura conto del conto corrente appena aperto). La funzione restituisce l'indice dell'elemento dell'array conti riservato a contenere il conto corrente; 2) la funzione membro oper() che effettua in data data l'operazione di importo importo sul conto corrente numero numConto. La funzione restituisce false se il numero del conto corrente non è valido; altrimenti restituisce true (si faccia attenzione ad aggiornare il campo totale); 3) la funzione membro build() che apre in lettura il file in cui nome è passato come parametro e ripete fino a raggiungere la fine del file le azioni seguenti: a) legge il nome del proprietario ed apre un conto corrente; b) legge un numero intero che indica il numero di operazioni numOp effettuate dal proprietario, c) legge numOp coppie di interi che indicano l'importo e la data di ognuna delle numOp operazioni e, per ogni coppia, invoca la funzione oper() sul conto appena aperto; 4) la funzione interessi() che, a fine anno, calcola per ogni conto corrente gli interessi maturati e li somma al totale. Si consideri un tasso di interesse pari al 3% annuo. La funzione membro stampa() stampa su uscita standard tutte le informazioni riguardanti i conti correnti. La funzione stampa() è implementata nel file ccob.o. Esercizio 3) Realizzare quanto richiesto in C++ (scrivere sul file es3.cc ed eseguire). Scrivere un programma che: 1. dichiara una struttura s1 di tipo st inizializzando i campi v e c con rispettivamente gli interi da 0 a 3 ed i caratteri da 'a' a 'd'; 2. dichiara una struttura s2 di tipo st; 3. dichiara un vettore v di quattro interi inizializzandolo con gli interi da 4 a 1; 4. dichiara un vettore c di quattro caratteri inizializzandolo con i caratteri da '0' a '3'; 5. chiama la funzione f() passandole nell'ordine s1, v e c ed assegnando la struttura restituita a s2; 6. stampa su uscita standard la struttura s2 ed i vettori v e c; 6. dichiara un oggetto g di tipo gestcont; 7. chiama la funzione build() sull'oggetto passandole la stringa "ingr"; 8. stampa su uscita standard l'oggetto g; 9. calcola gli interessi di tutti i conto correnti; 10. stampa su uscita standard l'oggetto g. Esame di Calcolatori Elettronici Appello del 12/2/2003 - Soluzioni .text .globl _f _f: pushl %ebp movl %esp,%ebp subl $24,%esp pushl %edi pushl %esi pushl %ebx pushl %edx pushl %ecx leal -24(%ebp),%edi leal 12(%ebp),%esi cld movl $5,%ecx rep movsl movl $0,-4(%ebp) for: cmpl $4,-4(%ebp) jl corpo jmp finefor corpo: movl -4(%ebp),%ecx movl 32(%ebp),%ebx #v in ebx movl 12(%ebp,%ecx,4),%edx cmpl %edx,(%ebx,%ecx,4) #if (s.v[i]>v[i]) jge else movl 36(%ebp),%esi #c in %esi movb 28(%ebp,%ecx),%dl #s1.c[i] in dl subb (%esi,%ecx),%dl movsbl %dl,%edx movl %edx, (%ebx,%ecx,4) jmp fineif else: movb 28(%ebp,%ecx),%dl movsbl %dl,%edx movl %edx, -24(%ebp,%ecx,4) fineif: movl 36(%ebp),%esi #c in %esi movb 28(%ebp,%ecx),%dl addb 12(%ebp,%ecx,4), %dl movb %dl,(%esi,%ecx) movl %ecx,%eax sarl $1,%eax movb (%esi,%eax),%dl movb %dl,-8(%ebp,%ecx) incl -4(%ebp) jmp for finefor:movl 8(%ebp),%eax movl %eax,%edi leal -24(%ebp),%esi cld movl $5,%ecx rep movsl pushl %ecx pushl %edx popl %ebx popl %esi popl %edi leave ret Esercizio 2 // file cc.h esistente const int N = 4; const int C = 4; const int LUNG = 20; struct operazione { float importo; int data; }; struct conto { char nome [LUNG]; operazione oper [N]; int numOp; float totale; }; class gestcont { conto conti[C]; int primo; void stampaConto(const conto&); public: gestcont() { primo=0;} int apri(const char nome[]); bool oper(int numConto, float importo, int data); void build(const char nome[]); void interessi(); void stampa(); }; //file ccob.cc esistente #include "cc.h" #include void gestcont::stampaConto(const conto& c) { cout << "Nome\tNum.Oper.\tTotale " << endl; cout << c.nome << '\t' << c.numOp << '\t' << c.totale << endl; cout << "Operazioni " << endl; cout << "Importo\tData" << endl; for (int i=0; i int gestcont::apri(const char nome[]) { if (primo==C) cerr << "Impossibile aprire il conto " << endl; strcpy(conti[primo].nome,nome); conti[primo].numOp=0; conti[primo++].totale=0; return primo -1; } bool gestcont::oper(int numConto, float importo, int data) { if (numConto >= primo && conti[numConto].numOp>=N) return false; conti[numConto].oper[conti[numConto].numOp].importo=importo; conti[numConto].oper[conti[numConto].numOp++].data=data; conti[numConto].totale+=importo; return true; } void gestcont::build(const char nome[]) { ifstream in(nome); if (!in) { cerr << "Errore nell'apertura del file " << nome << endl; exit(1); } int data,numOp,conto; float importo; char inNome[LUNG]; while (in >> inNome && in >> numOp) { conto=apri(inNome); for (int i=0;i> importo >> data; oper(conto, importo, data); } } } void gestcont::interessi() { float interessi=0, totale; for (int i=0; i #include "cc.h" struct st { int v[4]; char c[4]; }; extern "C" st f(st s1, int v[4], char c[4]); void stampa(const st& s) { for (int i=0; i<4; i++) cout << s.v[i] << ' '; cout << endl; for (int i=0; i<4; i++) cout << s.c[i] << ' '; cout << endl; } void main() { st s1={{0,1,2,3},{'a','b','c','d'}},s2; int v[]={4,3,2,1}; char c[]={'0','1','2','3'}; s2=f(s1,v,c); cout << "Stampa della struttura s2 dopo la chiamata alla funzione " << endl; stampa(s2); cout << "Stampa del vettore v" << endl; for (int i=0; i<4; i++) cout <