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

Lunedì 23 e giovedì 26 ottobre 2017 (Lezione 7 - 150 min) - Demetrescu/Coppa


Esercizio 1

Scrivere una funzione void cancspazi(char* s) che elimina tutti gli spazi da una stringa s e tradurla poi in IA32. Scrivere la soluzione nel file es2.s.

Usare il seguente programma di prova:

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

void cancspazi(char* s);

int main() {
    char s1[] = "obi wan kenobi ";
    char s2[] = "obiwankenobi";
    char s3[] = "  leila    luke ";
    char s4[] = "";
    cancspazi(s1);
    cancspazi(s2);
    cancspazi(s3);
    cancspazi(s4);
    printf("\"%s\" (corretto: \"obiwankenobi\")\n", s1);
    printf("\"%s\" (corretto: \"obiwankenobi\")\n", s2);
    printf("\"%s\" (corretto: \"leilaluke\")\n", s3);
    printf("\"%s\" (corretto: \"\")\n", s4);
    return 0;
}


Compilare come al solito con gcc -m32 -g es2.s es2-main.c -o es2. In caso di problemi debuggare con gdb.

Soluzione:

es2.s
# void cancspazi(char* s) {
#     char* p = s;
#     do if (*s!=' ') *p++ = *s;
#     while (*s++!=0);
# }

.globl cancspazi

cancspazi:              # s <-> eax, p <-> ecx
    movl 4(%esp), %eax  # eax = s
    movl %eax, %ecx     # ecx = p = s
    jmp S               # goto S
L:  incl %eax           # s++
S:  movb (%eax), %dl    # dl = *s
    cmpb $32, %dl       # if (dl == ' ')
    je L                #     goto L
    movb %dl, (%ecx)    # *p = dl
    incl %ecx           # p++
    testb %dl, %dl      # if (dl!=0)
    jne L               #     goto L
    ret


Esercizio 2 (compito C, esonero 2016/2017)

es.c
void arrayCrossMean(unsigned* x, unsigned* y, unsigned* z, unsigned n) {
    unsigned* end = x+n;
    y = y+n-1;

    while (x < end) {
        *z = *x + *y;
        if (*z) *z = (*z) >> 1;
        x++, z++, y--;
    }
}


main.c
#include <stdio.h>

void arrayCrossMean(unsigned* x, unsigned* y, unsigned* z, unsigned n);

void printArray(unsigned* v, unsigned n) {
    printf("{");
    int i = 0;
    for (i=0; i<n-1; ++i)
        printf("%u, ", v[i]);
    printf("%u", v[i]);
    printf("}");
}

int main() {
    unsigned z[5];

    unsigned x1[4] = {1, 2, 0, 4};
    unsigned y1[4] = {2, 0, 3, 5};

    printf("Test 1:\nx: ");
    printArray(x1, 4);
    printf("\ny: ");
    printArray(y1, 4);
    arrayCrossMean(x1, y1, z, 4);
    printf("\nz: ");
    printArray(z, 4);
    printf("\nRisultato atteso:\nz: {3, 2, 0, 3}\n");

    unsigned x2[5] = {0, 7, 1, 0, 3};
    unsigned y2[5] = {2, 0, 1, 2, 1};

    printf("\nTest 2:\nx: ");
    printArray(x2, 5);
    printf("\ny: ");
    printArray(y2, 5);
    arrayCrossMean(x2, y2, z, 5);
    printf("\nz: ");
    printArray(z, 5);
    printf("\nRisultato atteso:\nz: {0, 4, 1, 0, 2}\n");

    return 0;
}


Soluzione:
es-equiv.c
void arrayCrossMean(unsigned* x,    // x <-> eax
                    unsigned* y,    // y <-> ebx
                    unsigned* z,    // z <-> ecx
                    unsigned n) {

    unsigned  temp;                 // temp <-> esi
    unsigned* end = x;              // end <-> edx
    end += n;
    y += n;
    y--;

L:  if (x >= end) goto E;
    temp = *x;
    temp += *y;
    *z = temp;                      // *x + *y
    if (temp == 0) goto F;
    *z >>= 1;                       // *z = (*z) >> 1
F:  x++;
    z++;
    y--;
    goto L;
E: ;
}


es.s
.globl arrayCrossMean

arrayCrossMean:
    # void arrayCrossMean(unsigned* x,    // x <-> eax
    #                unsigned* y,         // y <-> ebx
    #                unsigned* z,         // z <-> ecx
    #                unsigned n) {

    pushl %ebx # prologo
    pushl %esi

    movl 12(%esp), %eax          # carico x
    movl 16(%esp), %ebx          # carico y
    movl 20(%esp), %ecx          # carico z

    # unsigned  temp;            // temp <-> esi
    movl %eax, %edx              # unsigned* end = x; // end <-> edx

    movl 24(%esp), %esi
    imull $4, %esi               # esi == 4*n
    addl %esi, %edx              # end += n;
    addl %esi, %ebx              # y += n;
    subl $4, %ebx                # y--;

L:  cmpl %edx, %eax              # if (x >= end)
    jae E                        #    goto E;
    movl (%eax), %esi            # temp = *x;
    addl (%ebx), %esi            # temp += *y;
    movl %esi, (%ecx)            # *z = temp;         // *x + *y
    testl %esi, %esi             # if (temp == 0)
    je F                         #    goto F;
    shrl (%ecx)                  # *z >>= 1;          // *z = (*z) >> 1
F:  addl $4, %eax                # x++;
    addl $4, %ecx                # z++;
    subl $4, %ebx                # y--;
    jmp L                        # goto L;

E:  popl %esi                    # epilogo
    popl %ebx
    ret


Suggerimento: semplificare la soluzione sopra usando l'istruzione LEA.
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by WikkaWiki