Sistemi di Calcolo

Corso di Laurea in Ingegneria Informatica e Automatica

Home | Avvisi | Diario Lezioni | Esercitazioni | Esami | Materiale Didattico | Valutazioni Studenti | Lezioni di Camil Demetrescu |

[T09] Esercitazione del 10 maggio 2019

Istruzioni per l’esercitazione:

Per maggiori informazioni fate riferimento al regolamento delle esercitazioni.

Esercizio 1 (somma di matrice)

Tradurre in IA32 la seguente funzione matsum definita in T1-mat-sum/e1.c che calcola la somma degli elementi della matrice quadrata m di dimensioni n x n.

e1.c

int matsum(int** m, int n){
    int i, j, s = 0;
    for (i=0; i<n; ++i)
        for (j=0; j<n; ++j)
            s += m[i][j];
    return s;
}

Scrivere la soluzione nel file T1-mat-sum/e1.s. Usare il file T1-mat-sum/e1_eq.c per sviluppare la versione C equivalente.

Esercizio 2 (indicatore di progresso)

Si vogliono usare i segnali per creare un indicatore di progresso per la funzione do_sort, che implementa un semplice algoritmo di ordinamento a bolle. L’indicatore di progresso è la percentuale di n coperta da i, vale a dire 100.0*i/n. Si scriva la soluzione nel file E2-sort-timer/e2.c modificandolo e aggiungendo quanto necessario al raggiungimento dell’obiettivo.

e2.c

#include "e2.h"

static void do_sort(int *v, int n) {
    int i, j;
    for (i=0; i<n; ++i)
        for (j=1; j<n; ++j)
            if (v[j-1] > v[j]) {
                int tmp = v[j-1];
                v[j-1] = v[j];
                v[j] = tmp;
            }
}

void sort(int *v, int n) {

    // completare con gestione segnali...

    do_sort(v, n);
}

Il risultato atteso deve essere come segue (ovviamente i numeri esatti delle percentuali possono variare):

start sorting...
-------------------------------
5.4%
11.2%    <---- percentuali stampate dal gestore del segnale
17.1%
23.3%
29.7%
36.5%
43.7%
51.5%
59.7%
68.7%
79.0%
90.7%
-------------------------------
v[0]=0
v[1]=1
v[2]=2
v[3]=3
v[4]=4
v[5]=5
v[6]=6
v[7]=7
v[8]=8
v[9]=9

Suggerimento: rendere la variabile i di do_sort globale (dichiarata fuori dalla funzione) e tenere in un’altra variabile globale max il valore di n. In questo modo è possibile accedervi da un handler di un segnale che può stampare il rapporto tra i e max. Fare riferimento alla dispensa del corso sul segnali.

Esercizio 3 (Domande)

Domanda 1 Quale delle seguenti affermazioni è VERA?

Domanda 2 Dato il seguente codice, quale tra le seguenti affermazione è VERA?

Domanda 2

Domanda 3 Data la seguente porzione di codice, quale delle seguenti affermazioni è FALSA?

Domanda 3

Domanda 4 Dato il seguente codice, selezionare la risposta corretta:

Domanda 4

Domanda 5 Dato il seguente codice, selezionare la risposta corretta:

Domanda 5

Domanda 6 Quale delle seguenti affermazioni è FALSA?

Domanda 7 Quale delle seguenti affermazioni è VERA?

Domanda 8 Quale delle seguenti affermazioni è FALSA?

Soluzioni

Esercizio 1 (somma di matrice)

e1_eq.c

#include "e1.h"

int matsum(int** m, int n){
    int i, j, s = 0;
    i=0;
L1: if (i>=n) goto E;
    j=0;
L2: if (j>=n) goto F;
    int* tmp = m[i];
    s += tmp[j];
    ++j;
    goto L2;
F:  ++i;
    goto L1;
E:  return s;
}

es1.s

.globl matsum

matsum: #int matsum(int** m, int n) {
    # s <-> eax, i <-> ecx, j <-> edx, m <-> edi, n <-> ebx, tmp <-> esi
    pushl %esi
    pushl %edi
    pushl %ebx
    movl 16(%esp), %edi
    movl 20(%esp), %ebx
    xorl %eax, %eax              # s=0;
    xorl %ecx, %ecx              # i=0;
L1: cmpl %ebx, %ecx              # if (i>=n)
    jne E                        #     goto E;
    xorl %edx, %edx              # j=0;
L2: cmpl %ebx, %edx              # if (j>=n)
    jne F                        #     goto F;
    movl (%edi,%ecx,4), %esi     # int* tmp = m[i];
    addl (%esi,%edx,4), %eax     # s += tmp[j];
    incl %edx                    # ++j;
    jmp L2                       # goto L2;
F:  incl %ecx                    # ++i;
    jmp L1                       # goto L1;
E:  popl %ebx
    popl %edi
    popl %esi
    ret                          # return s;
Esercizio 2 (indicatore di progresso)

e2.c

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "e2.h"

int i, max;

static void do_sort(int *v, int n) {
    int j;
    for (i=0; i<n; ++i)
        for (j=1; j<n; ++j)
            if (v[j-1] > v[j]) {
                int tmp = v[j-1];
                v[j-1] = v[j];
                v[j] = tmp;
            }
}

void handler(int sig) {
    printf("%3.1f%%\n", 100.0*i/max);
    ualarm(500000,0);
}

void sort(int *v, int n) {

    max = n;

    struct sigaction act = { 0 };               // preparazione struttura 
    act.sa_handler = handler;                   // gestore segnale
    int ret = sigaction(SIGALRM, &act, NULL);   // gestore installato
    if (ret == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
    
    ualarm(500000,0);

    do_sort(v, n);

    act.sa_handler = SIG_IGN;                   // segnale ignorato
    ret = sigaction(SIGALRM, &act, NULL);       // gestore installato
    if (ret == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
}
Esercizio 3 (Domande)
  1. WEXITSTATUS(status) estrae il byte meno significativo dalla variabile int status
  2. Il programma stampa “I’m child 0”, “I’m child 1”, “I’m child 2” ma l’ordine delle stampe non è predicibile perché dipende dallo scheduler
  3. E è il numero di pagina dell’indirizzo di x [l’operazione E azzera i 12 bit meno significativi]
  4. Il programma non termina (o termina dopo molto) [dopo essere stato gestito, SIGFPE ritenta l’operazione che lo ha provocato]
  5. Il programma termina dopo circa 3 secondi ma non stampa “bye!” [il segnale SIGALRM ha come default la terminazione]
  6. Il segnale SIGSEGV non può essere catturato [gli unici segnali a non poter essere catturati sono SIGKILL e SIGSTOP]
  7. ualarm(t, n) invia un segnale dopo t microsecondi e successivamente ogni n microsecondi [vedi man ualarm]
  8. Il primo parametro di mprotect deve essere un indirizzo fisico (non logico) [i processi non hanno visibilità degli indirizzi fisici]