Sistemi di Calcolo

Corso di Laurea in Ingegneria Informatica e Automatica - A.A. 2017-2018

HomePage | Avvisi | Diario lezioni | Programma | Materiale didattico | Esami | Forum | Login

Esercitazione 3 - 17 novembre 2015 (90 min)


Aprire Linux LXLE nella VM Oracle Virtualbox BIAR.

Creare una directory di lavoro sc1516 sulla scrivania e posizionarsi nella directory creata come segue:

$ mkdir /home/biar/Desktop/sc1516
$ cd /home/biar/Desktop/sc1516



Esercizio 1 (istruzione SETcc)

Tradurre in IA32 la seguente funzione C in un modulo es1.s, usando l'istruzione SETcc:

es1.c
int testcc(short x, short y) {
    return 0<=x && x<y;
}


Testare il funzionamento della funzione scritta con il seguente programma di prova:

es1-main.c
#include <stdio.h>

int testcc(short x, short y);

int main() {
    int res;
    res = testcc(10,20);
    printf("testcc(10,20)=%d\n", res);
    res = testcc(-10,20);
    printf("testcc(-10,20)=%d\n", res);
    res = testcc(15,10);
    printf("testcc(15,10)=%d\n", res);
    res = testcc(-15,-20);
    printf("testcc(-15,-20)=%d\n", res);
    return 0;
}


Nota bene: compilare a 32 bit con gcc -m32 (gcc -m32 es1-main.c es1.s -o es1).

Esercizio 2 (istruzione CMOVcc)

Tradurre in IA32 la seguente funzione C in un modulo es2.s, usando l'istruzione CMOVcc, senza usare istruzioni di salto (Jcc o JMP):

es2.c
int myabs(int x) {
    return x<0 ? -x : x;
}


Testare il funzionamento della funzione scritta con il seguente programma di prova:

es2-main.c
#include <stdio.h>

int myabs(int x);

int main() {
    int res;
    res = myabs(10);
    printf("myabs(10)=%d\n", res);
    res = myabs(-10);
    printf("myabs(-10)=%d\n", res);
    res = myabs(0);
    printf("myabs(0)=%d\n", res);
    return 0;
}


Nota bene: compilare a 32 bit con gcc -m32.

Esercizio 3 (chiamata a funzione senza parametri)

Tradurre in IA32 la seguente funzione C in un modulo es3.s:

es3.c
int uno();
int somma_uno_a(int x) {
    return x+uno();
}


Testare il funzionamento della funzione scritta con il seguente programma di prova:

es3-main.c
#include <stdio.h>

int somma_uno_a(int x);

int uno() { return 1; }

int main() {
    int res;
    res = somma_uno_a(20);
    printf("somma_uno_a(20)=%d\n", res);
    return 0;
}


Nota bene: compilare a 32 bit con gcc -m32.

Esercizio 4 (chiamata a funzione con parametri)

Tradurre in IA32 la seguente funzione C in un modulo es4.s:

es4.c
int prod(int x, int y, int z);
int f(int x, int y, int z, int w) {
    return prod(x,y,z)+w;
}


Nota importante: fare attenzione che i registri A, C e D (i registri caller-save) potrebbero essere sovrascritti da una chiamata a funzione, quindi il loro valore potrebbe andare perso dopo la chiamata. Si suggerisce pertanto di usare registri callee-save: B, SI, DI, BP (es. ebx, esi, edi, ebp).

Testare il funzionamento della funzione scritta con il seguente programma di prova es4-main.c e il modulo es4-prod.s che fornisce il codice della funzione prod:

es4-prod.s
# int prod(int x, int y, int z) {
#    return x*y*z;
# }

.globl prod
prod:
    movl 4(%esp), %eax
    movl 8(%esp), %ecx
    movl 12(%esp), %edx
    imull %ecx, %eax
    imull %edx, %eax
    ret


es4-main.c
#include <stdio.h>

int f(int x, int y, int z, int w); // calcola x*y*z+w

int main() {
    int res;
    res = f(2,3,4,6);
    printf("f(2,3,4,6)=%d\n", res);
    return 0;
}


Nota bene: compilare a 32 bit con gcc -m32.

Esercizio 5 (chiamata a funzione con parametri in un ciclo)

Tradurre in IA32 la seguente funzione C in un modulo es5.s:

es5.c
int doppio(int x);
int raddoppia(int* v, unsigned n) {
    unsigned i = 0;
    while (i<n) {
        v[i] = doppio(v[i]);
        i++;
    }
}


Nota importante: fare attenzione che i registri A, C e D (i registri caller-save) potrebbero essere sovrascritti da una chiamata a funzione, quindi il loro valore potrebbe andare perso dopo la chiamata. Si suggerisce pertanto di usare registri callee-save: B, SI, DI, BP (es. ebx, esi, edi, ebp).

Testare il funzionamento della funzione scritta con il seguente programma di prova es5-main.c e il modulo es5-doppio.s che fornisce il codice della funzione doppio:

es4-doppio.s
# int doppio(int x) {
#    return x+x;
# }

.globl doppio
doppio:
    movl 4(%esp), %eax
    addl %eax, %eax
    movl $-1, %ecx # sovrascrive C (a scopi di test)
    movl $-1, %edx # sovrascrive D (a scopi di test)
    ret


es5-main.c
#include <stdio.h>

int raddoppia(int* v, unsigned n);

int main() {
    int i, v[] = {10, 20, 30, 40, 50};
    raddoppia(v, 5);
    for (i=0; i<5; i++) printf("v[%d]=%d\n", i, v[i]);
    return 0;
}


Nota bene: compilare a 32 bit con gcc -m32.

Soluzioni


Sono disponibili le soluzioni dell'esercitazione.
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by WikkaWiki
Page was generated in 0.0708 seconds