Laboratorio di calcolatori elettronici
COMPITO D del 28 Giugno 2004
Proff. V.Catania - risoluzione e commenti di Ignazio Coco
esportato con SciTE
Testo del compito:
Utilizzando l'assembly del DLX scrivere un programma che:
(a)Detti f={9,2,6,2,1,8,4,2,6,0,2,5,1,1,3,8} i campioni di una funzione nei punti 1,2,3,...,16, calcoli e visualizzi l'integrale utilizzando il metodo dei trapezi.
(b) Scambi gli elementi consecutivi del vettore f che sono entrambi pari e visualizzi f così modificato.
(c) Visualizzare il numero di massimi relativi di f.
SVOLGIMENTO:
.data
mess: .asciiz "\nIntegrale %d"
.align 2
mess_addr: .word mess
integr: .space 4
mess2: .asciiz "\nElemento %d"
.align 2
mess2_addr: .word mess2
elem: .space 4
mess3: .asciiz "\nIl numero di max relativi è: %d"
.align 2
mess3_addr: .word mess3
max_rel: .space 4
vett1: .word 9,2,6,2,1,8,4,2,6,0,2,5,1,1,3,8
.text
addi r2,r0,0 ;spiazzamento di vett1
addi r3,r0,15 ;contatore per vett1, è uguale alla dimensione di vett1 - 1
;perchè il numero di aree(integrali) da sommare è 15, in quanto
;per calcolare l'integrale prendo l'elemento i esimo e i+1 esimo
addi r8,r0,2 ;valore 2 per effettuare la divisione
addi r10,r0,0 ;resetto r10 a zero che conterrà l'integrale della funzione
;CALCOLO INTEGRALE (tra due punti consecutivi)
;[f(x1)+f(x2)] * altezza / 2 --> area trapezoidale
;dove f(x1) è la prima base del trapezio ed f(x2) la seconda
;altezza è sempre pari ad 1
;cosicchè il calcolo diviene [f(x1)+f(x2)]/2
;in questo ciclo tale divisione viene memorizzata come un int
;poichè non espressamente richiesto di usare l'aritmetica double
loop_integr:
addi r4,r2,4 ;spiazzamento per prelevare l'elemento i+1 esimo
lw r5,vett1(r2) ;carico l'i esimo elemento
lw r6,vett1(r4) ;carico l'i+1 esimo elemento
add r7,r5,r6 ;li sommo [ f(x2)+f(x2) ]
div r9,r7,r8 ;divido tale somma per 2 (NB r8=2)
add r10,r10,r9 ;sommo in r10 il valore appena trovato
addi r2,r2,4 ;incremento lo spiazzamento
subi r3,r3,1 ;decremento il contatore
bnez r3,loop_integr ;se r3 non è zero cicla
sw integr(r0),r10 ;metti in integr il contenuto di r10 (l'integrale) per essere stampato
addi r14,r0,mess_addr ;metti in r14 l'indirizzo del messagio da stampare
trap 5 ;stampa
addi r2,r0,0 ;resetta r2 a zero, lo userò come spiazzamento per vett1
addi r3,r0,15 ;resetta r3 a 15, lo userò come contatore per vett1
;r3 è pari a dimensione di vett1 - 1, in quanto il 16 esimo elemento
;non ha un elemento dopo di sè
loop_scambio:
addi r4,r2,4 ;in r4 metto lo spiazzamento per l'elemento successivo
lw r5,vett1(r2) ;carico in r5 l'elemento attuale
lw r6,vett1(r4) ;in r6 il successivo
andi r7,r5,1 ;vedo se l'elemento attuale è pari (se lo è, r7 è 0)
bnez r7,non_con ;se non lo è, vai a non_con (cioè r7=1)
andi r7,r6,1 ;vedo se anche il successivo è pari (se lo è, r7 è 0)
bnez r7,non_con ;se non lo è, vai a non_con (cioè r7=1)
sw vett1(r4),r5 ;metto l'elemento attuale (r5) in vett1(r4) che è la posizione dell'elemento successivo
sw vett1(r2),r6 ;metto l'elemento successivo (r6) in vett1(r2) che è la posizione dell'elemento attuale
non_con:
addi r2,r2,4 ;incremento lo spiazzamento
subi r3,r3,1 ;decremento il contatore
bnez r3,loop_scambio ;se r3 non è zero cicla
addi r2,r0,0 ;resetto a zero r2, lo userò come spiazzamento per vett1
addi r3,r0,16 ;resetto a 16 r3, lo userò come contatore per vett1
;stavolta devo stampare tutti gli elementi quindi il contatore è 16
loop_stampa:
lw r4,vett1(r2) ;carico l'iesimo elemento di vett1 in r4
sw elem(r0),r4 ;lo metto in elem affinchè venga stampato
addi r14,r0,mess2_addr ;passo ad r14 l'indirizzo della stringa da stampare
trap 5 ;stampo
addi r2,r2,4 ;incremento lo spiazzamento
subi r3,r3,1 ;decremento il contatore
bnez r3,loop_stampa ;se r3 non è zero cicla
addi r3,r0,4 ;spiazzamento per vett1, parte da 4 (secondo elemento) perchè
;prendo come massimo relativo un elemento (i) che abbia elemento
;precedente (i-1) e successivo (i+1) entrambi minori
addi r12,r0,0 ;contatore dei massimi relativi
addi r13,r0,14 ;contatore per vett1 (14 perchè escludo il primo e l'ultimo elemento
;dalla ricerca del max relativo)
loop_cerca_max:
addi r4,r3,4 ;metto in r4 lo spiazzamento per l'elemento successivo
subi r2,r3,4 ;metto in r2 lo spiazzamento per l'elemento precedente
lw r5,vett1(r2) ;in r5 l'elemento precedente
lw r6,vett1(r3) ;in r6 l'elemento attuale
lw r7,vett1(r4) ;in r7 l'elemento successivo
sgt r8,r6,r5 ;setto r8 ad 1 se r6>r5
sgt r9,r6,r7 ;setto r9 ad 1 se r6>r7
and r10,r8,r9 ;verifico che entrambe le condizioni precedenti siano verificate
beqz r10,non_max ;se non lo sono (il risultato dell'and precedente è 0) salta a non_max
addi r12,r12,1 ;la condizione precedente è verificata, incremento r12 di 1
;ho trovato un massimo relativo
non_max:
addi r3,r3,4 ;incremento lo spiazzamento
subi r13,r13,1 ;decremento il contatore
bnez r13,loop_cerca_max ;se r3 non è nullo cicla
sw max_rel(r0),r12 ;metto il contenuto di r12(il numero di max relativi) in max_rel
addi r14,r0,mess3_addr ;inserisco in r14 l'indirizzo del messaggio da stampare
trap 5 ;stampo
trap 0 ;fine programma