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 |
--- layout: default title: Esercitazione del 3 maggio 2019 ---

[T08] Esercitazione del 3 maggio 2019

Istruzioni per l’esercitazione:

Per maggiori informazioni fate riferimento al regolamento delle esercitazioni.

Esercizio 1 (Confronto tra lista e array)

Tradurre in IA32 la seguente funzione list_equal_array definita in E1-list-array-equal/e1.c che, dato in p il puntatore al primo nodo di una lista di short e un array di n short, restituisce 1 se la lista è uguale all’array e 0 altrimenti.

e1.c

#include "e1.h"
#include <stdlib.h>

int list_equal_array(const node_t *p, short *buf, int n) {
    int i;
    for (i = 0; i < n; i++) {
        if (p == NULL || p->elem != buf[i]) return 0;
        p = p->next;
    }
    return p == NULL;
}

Si riporta un estratto del file e1.h che definisce il tipo node_t:

typedef struct node_t {
    short elem;
    struct node_t *next; 
} node_t; 

Scrivere la soluzione nel file E1-list-array-equal/e1.s. Usare il file E1-list-array-equal/e1_eq.c per sviluppare la versione C equivalente.

Esercizio 2 (Copia di file)

Scrivere nel file T2-file-copy/e2.c una funzione int copy(const char* src, const char* dst) che realizza la copia di un file di dimensione arbitraria con nome file sorgente src e destinazione dst. La funzione deve restituire EXIT_FAILURE in caso di errore e EXIT_SUCCESS altrimenti.

Suggerimento: allocare dinamicamente un buffer da usare per il travaso di dati dal file sorgente al file destinazione. Provare con dimensioni diverse scegliendo la minima ragionevole per mantenere le prestazioni.

Usare il programma di prova ./test.sh che compila, esegue e verifica il risultato.

Esercizio 3 (Domande)

Domanda 1 Con riferimento ai permessi sui file, la notazione ottale 0640 a quale configurazione di permessi corrisponde?

Domanda 2 Dato il seguente codice, quale tra le seguenti affermazioni è corretta?

Domanda 2

Domanda 3 Quale tra le seguenti affermazioni è FALSA?

Domanda 4 Data la seguente porzione di codice, selezionare la risposta corretta:

Domanda 4

Domanda 5 Data la seguente porzione di codice, selezionare la risposta corretta:

Domanda 5

Domanda 6 Supponendo di essere su una architettura con indirizzi di 32 bit, se la dimensione di una pagina di memoria è 4 kB (4096 byte), lo spazio di indirizzamento logico di un processo quante pagine (allocate o meno) contiene? (con la notazione 2^n si indica 2 elevato al numero n)

Domanda 7 Sia A = 0x08F444D8 un indirizzo nello spazio di indirizzamento logico di un processo P, su un’architettura a 32 bit. Si assuma che la memoria virtuale utilizzi pagine di 4 kB (4096 byte). Indicare il numero di pagina e l’offset di A (in decimale):

Domanda 8 Sia A = 0xFF9257B0 un indirizzo nello spazio di indirizzamento logico di un processo P, su un’architettura a 32 bit. Si assuma che la memoria virtuale utilizzi pagine di 4 kB (4096 byte) e che la pagina dell’indirizzo A sia stata mappata nel frame numero 128 (decimale). Indicare l’indirizzo fisico corrispondente all’indirizzo logico A:

Soluzioni

Esercizio 1 (Confronto tra lista e array)

e1_eq.c

#include "../e1.h"
#include <stdlib.h>

int list_equal_array(const node_t *p, short *buf, int n) {

    const node_t *edx = p;
    short *ebx = buf;
    int edi = n;

    // Registers; i<->ecx, p<->edx, tmp<->eax, buf <-> ebx, n <->edi

    int ecx=0;
L:  if (ecx >= edi) goto E;
    if (edx == NULL) goto F;
    int eax = edx->elem;
    if (eax != ebx[ecx]) goto F;
    edx = edx->next;
    ecx++;
    goto L;
E:  return edx == NULL;
F:  return 0;
}

e1.s

.globl list_equal_array

# typedef struct node_t {    // base
#     short elem;            // offset: 0 |xx..|   (base)
#     struct node_t *next;   // offset: 4 |xxxx|  4(base)
# } node_t;                  // sizeof: 8

list_equal_array:  # int list_equal_array(const node_t *p, short *buf, int n) {

    pushl %ebx
    pushl %edi

    movl 12(%esp), %edx                  # const node_t *edx = p;
    movl 16(%esp), %ebx                  # short *ebx = buf;
    movl 20(%esp), %edi                  # int edi = n;

    # Registers: i<->ecx, p<->edx, tmp<->eax, buf <-> ebx, n <->edi

    xorl %ecx, %ecx                      # int ecx = 0;
L:  cmpl %edi, %ecx                      # if (ecx >= edi)
    jge E                                #     goto E;
    testl %edx, %edx                     # if (edx == NULL)
    je E                                 #      goto F
    movw (%edx), %ax                     # int eax = edx->elem;
    cmpw (%ebx, %ecx, 2), %ax            # if (eax != ebx[ecx])
    jne F                                #     goto F;
    movl 4(%edx), %edx                   # edx = edx->next;
    incl %ecx                            # ecx++;
    jmp L                                # goto L;
E:  testl %edx, %edx                     # return edx == NULL;
    sete %al
    movsbl %al, %eax
    jmp G
F:  xorl %eax, %eax                      # return 0
G:  popl %edi
    popl %ebx
    ret
Esercizio 2 (Copia di file)

e2.c

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

void check_perror(int res, const char* msg);

#define BUF_SIZE 8192

int copy(const char* src, const char* dst) {

    int res;
    void* buf;

    // allocazione buffer
    buf = malloc(BUF_SIZE);
    if (buf == NULL) {
        fprintf(stderr, "malloc");
        exit(EXIT_FAILURE);
    }

    // open files
    int fdin = open(src, O_RDONLY);
    check_perror(fdin, "open");

    int fdout = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    check_perror(fdout, "open");

    // copy loop
    while(1) {
        ssize_t r = read(fdin, buf, BUF_SIZE);
        check_perror(r, "read");
        if (r==0) break;
        
        ssize_t w = write(fdout, buf, r);
        check_perror(w, "write");
    }

    // close files
    res = close(fdin);
    check_perror(res, "close");

    res = close(fdout);
    check_perror(res, "close");
    
    // allocazione buffer
    free(buf);

    return EXIT_SUCCESS;
}

void check_perror(int res, const char* msg) {
    if (res != -1) return;  
    perror(msg);
    exit(EXIT_FAILURE);
}
Esercizio 3 (Domande)
  1. rw-r-----
  2. Se il programma termina correttamente, dopo l’esecuzione, il file test.txt contiene esclusivamente i caratteri hello``
  3. In ogni istante in cui un processo è nello stato “running”, tutte le sue pagine di memoria devono essere mappate su frame della memoria fisica
  4. s è un array di char allocato nello stack frame della funzione main
  5. s è una variabile puntatore che punta ad un array di char allocato nella sezione “data” del processo
  6. 2^20
  7. Pagina = 36676, offset = 1240
  8. 0x000807B0