uniroma1
.*_main.c
.cognome.nome
. Sulle postazioni del laboratorio sarà /home/biar/Desktop/cognome.nome/
.cognome.nome.zip
(zip -r cognome.nome.zip cognome.nome/
).cognome.nome.zip
.rm -rf cognome.nome
).E1/e1_eq.c
equivalente a quella di partenza, ma più semplice da tradurre in assembly. Testatela con il main di prova prima di passare a scrivere la versione .s
. E’ inutile tradurre la versione C equivalente se è errata!Per maggiori informazioni fate riferimento al regolamento delle esercitazioni.
Tradurre nel file E1/e1.s
la seguente funzione C contenuta in E1/e1.c
che aggiunge un elemento in testa una lista collegata:
#include <stdlib.h>
#include "e1.h"
int list_add_first(node_t **l, short elem) {
node_t *p = *l;
node_t *n = malloc(sizeof(node_t));
if (n == NULL) return -1; // allocation error
n->elem = elem;
n->next = p;
*l = n;
return 0;
}
Usare il main di prova nella directory di lavoro E1
compilando con gcc -m32 e1_main.c e1.s -o e1
.
Tradurre nel file E2/e2.s
la seguente funzione C contenuta in E2/e2.c
che, dati due array di short
,
retituisce 1 se sono uguali e 0 altrimenti. Riferirisi alla dichiarazione della
struttura node_t
dell’Esercizio 1.
int list_equal(const node_t *l1, const node_t *l2) {
while (l1!=NULL && l2!=NULL) {
if (l1->elem != l2->elem) return 0;
l1 = l1->next;
l2 = l2->next;
}
return l1==NULL && l2==NULL;
}
Suggerimento: usare le istruzioni SETcc.
Usare il main di prova nella directory di lavoro E2
compilando con gcc -m32 e2_main.c e2.s -o e2
.
Si richiede di scrivere un’implementazione della funzione standard C strpbrk:
char *my_strpbrk(const char *s1, const char *s2);
La funzione deve restituire il puntatore alla prima occorrenza in s1
di un qualsiasi carattere presente nella stringa s2
oppure NULL
se alcun carattere di s2 appare in s1
prima che s1
stessa termini.
Esempio: Se s1 = "Once again, this is a test"
e s2="ftir"
, my_strpbrk
deve restituire il puntatore
alla prima occorrenza in s1
di un qualsiasi carattere nella stringa s2
, cioè il puntatore alla i
di “again”. La chiamata my_strpbrk("Once again, this is a test",":#F")
deve invece restituire NULL
. Ovviamente non è accettabile chiamare direttamente la strpbrk
predefinita della libc
(non imparereste nulla).
Rispondere ai quiz riportati nel form di consegna.
printf("%x", ++(*s));
?
es1_e1.c
#include <stdlib.h>
#include "e1.h"
int list_add_first(node_t **l, short elem) {
node_t **si = l;
node_t *b = *si;
node_t *a = malloc(sizeof(node_t));
if (a != NULL) goto F;
return -1; // allocation error
F:;
short d = elem;
(*a).elem = d;
(*a).next = b;
*si = a;
return 0;
}
es1.s
.globl list_add_first
#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_add_first: # int list_add_first(node_t **l, short elem) {
pushl %ebx
pushl %esi
subl $4, %esp
movl 16(%esp), %esi # node_t **si = l;
movl (%esi), %ebx # node_t *b = *si;
movl $8, (%esp)
call malloc # node_t *a = malloc(sizeof(node_t));
testl %eax, %eax # if (a != NULL)
jnz F # goto F;
movl $1, %eax # return -1; // allocation error
jmp E
F:
movl 20(%esp), %edx # short d = elem;
movw %dx, (%eax) # (*a).elem = d;
movl %ebx, 4(%eax) # (*a).next = b;
movl %eax, (%esi) # *si = a;
movl $0, %eax
E:
addl $4, %esp
popl %esi
popl %ebx
ret # return 0;
list_equal.c
#include <stdlib.h>
#include "e2.h"
int list_equal(const node_t *l1, const node_t *l2) {
const node_t *a = l1;
const node_t *c = l2;
L:
if (a==0) goto E;
if (c==0) goto E;
short d = (*c).elem;
if ((*a).elem == d) goto F;
return 0;
F:
a = (*a).next;
c = (*c).next;
goto L;
E:;
char al = a == 0;
char ah = c == 0;
al = al & ah;
return (int) al;
}
e2.s
.globl list_equal
list_equal: # int list_equal(const node_t *l1, const node_t *l2)
movl 4(%esp), %eax # node_t *a = l1;
movl 8(%esp), %ecx # node_t *c = l2;
L:
testl %eax, %eax # if (a==0)
jz E # goto E;
testl %ecx, %ecx # if (c==0)
jz E # goto E;
movw (%ecx), %dx # short d = (*c).elem;
cmpw %dx, (%eax) # if ((*a).elem == d)
je F # goto F;
E1:
movl $0, %eax
ret # return 0;
F:
movl 4(%eax), %eax # a = (*a).next;
movl 4(%ecx), %ecx # c = (*c).next;
jmp L # goto L;
E:
testl %eax, %eax # char al = a == 0;
setz %al
testl %ecx, %ecx # char ah = c == 0;
setz %ah
andb %ah, %al # al = al & ah;
movsbl %al, %eax
ret # return (int) al;
my_strpbrk
#include <stdio.h>
#include "e3.h"
char *my_strpbrk(const char *s1, const char *s2) {
const char* p;
while (*s1) {
for (p=s2; *p; p++)
if (*s1 == *p) return (char*)s1;
s1++;
}
return (char*)NULL;
}
Risposte corrette ai quiz: