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