Esercizi Assembly Un programma per calcolare la media
Esercizi Assembly
Un programma per calcolare la media Dato un vettore di 32 bytes unsigned memorizzato a partire dalla locazione 0 x 20 a 0, calcolarne la media e memorizzarne il valore sovrascrivendo l’ultima posizione del vettore. Se viene rilevato un overflow in V[31] e’ posizionato il valore ff ff 0 x 20 a 0 V[0] V[1] V[2] … V[31]=Σi=031 V[i]/32
Come gestire l’overflow? L’istruzione da controllare e’: addb (R 1)+, R 2 Microcodice : 1. MAR<-R 1 2. R 1<-R 1+1 3. Temp 1<-[MDR] 8 //gli 8 lsbs di MDR estesi in segno vanno in T 1 4. Temp 2<-[R 2] 8 //gli 8 lsbs di R 2 estesi in segno vanno in T 2 5. ALU_OUT=Temp 1+Temp 2 Se (Temp 1 + Temp 2) >232 -1 il CARRY bit viene settato per segnalare l’overflow. Quindi , e’ sufficiente far seguire all’operazione di somma un salto condizionato del tipo: jc error
Il codice org 400 h ARRAY DIM LOG 2 DIM loop: error: fine: EQU 20 a 0 h EQU 32 EQU 5 ; indirizzo base array ; num. elementi array ; log. base 2 di DIM code movl #DIM, R 0 movl #ARRAY, R 1 xorl R 2, R 2 ; resetta R 2, risultato parziale addb (R 1)+, R 2 ; somma i-esimo elem. i=0. . DIM-1 jc error ; bit c settato =>Overflow subl #1, R 0 ; decrementa contatore jnz loop ; se contatore!=0 continua il cicla lsrb #LOG 2 DIM, R 2; dividi per il numero di elementi, ; usiamo LSRB poichè lavoriamo con unsigned movb R 2, -(R 1) ; memorizza la media in ARRAY[DIM-1] jmp fine movl #DIM, R 1 ; gestione overflow, calcola in R 1 addl #ARRAY, R 1 ; R 1=ARRAY+DIM subl #1, r 1 xorl R 3, R 3 notl R 3, R 3 ; R 3=111. . 111 movb R 3, (R 1) ; ARRAY[DIM]=1111 halt end
Una variazione sul tema… ora, senza contatore! Calcolare la media di 128 words memorizzate a partire dall’indirizzo 0 x 20 ab, ma senza impiegare un registro appositamente come contatore (R 0 del programma precedente). 0 x 20 ab 0 x 20 ad V[0] V[1] V[2] … 0 x 21 a 9 0 x 21 ab V[127] NOTA: non si considera l’overflow. V[127]=Σi=0127 V[i]/127
Il codice (funziona solo se il numero di elementi è pari a 128 words) org 400 h DATI code main: ; programma allocato a partire da 400 h EQU 20 abh ; indirizzo inizio ; inizio istruzioni xorl R 2, R 2 movl #DATI, R 1 movb R 1, R 0 loop: addw (R 1)+, R 2 cmpb R 1, R 0 jnz loop lsrw #7, R 2 movw R 2, -(R 1) halt end ; R 2=risult. parziale ; puntatore elemento ; copio ls. B addr. inizio ; in R 0 ; ls. B addr. elemento ; e' = ls. B addr. inizio ? ; divido per 128 ; serve solo per bloccare il simulatore ; fine della compilazione
Un altro esempio: la moda Assumiamo di avere un vettore, V, di N bytes che memorizza nella posizione i-esima l’altezza in centimetri dell’i-esimo studente. altezza PROBLEMA: Trovare l’altezza piu’ frequente tra gli studenti (moda). id-studente
Prima soluzione: vettore di frequenze Vogliamo calcolare la moda, costruendo innanzitutto un vettore di frequenze, F, di 255 longwords, che associ in posizione j, il numero di ricorrenze dell’altezza j nel vettore di partenza V. num. studenti Probabilmente: F[j]=0 se i<50 o i>220 Osservazione: Noto il vettore delle frequenze F, il calcolo della moda si riconduce a determinare per quale i, F[i]=max{F} cm.
L’algoritmo per il calcolo delle frequenze Possiamo costruire F in 2 passi. 1) Inizializziamo l’array F, di 255 longwords, con tutti 0. for (i=0; i<256; i++) { array 2[i]=0; } 2) Memorizziamo le frequenze in F scandendo una sola volta V e incrementando di volta in volta l’elemento di F in posizione V(i) di 1. for (i=0; i<N; i++) { index=array 1[i]; array 2[index]++; }
Codice org 1400 h array 1 equ 800 h array 2 equ 1500 h dim equ 30 code ; V, vettore originale ; F, vettore frequenze ; inizializzo array 2 con tutti 0 ; for (i=0; i<256; i++) { ; array 2[i]=0; ; } ; MOVL #array 2, R 5 movl #0, r 4 clean: movl #0, (R 5)+ addl #1, r 4 cmpl #0 ffh, r 4 jc clean ; r 4 è inizializzato a zero perchè la successiva mvlb ; si aspetta i 3 bytes + significativi di R 4 uguali a 0 mvlb array 1(R 3), R 4 ; R 4=V[i]=array 1[R 3] ; NOTA: MVLB non estende il segno aslw #2, R 4 ; offset_array 2=R 4*4 ; Moltiplicando per 4 il contenuto ; del lsb di R 4 possiamo avere trabocchi, ; quindi usiamo aslw per operare con 2 byte movl array 2(R 4), r 5 ; r 5=array 2[offset_array 2] addl #1, r 5 ; r 5=array 2[offset_array 2]+1 addl #array 2, r 4 ; prima r 4 era = offset_array 2, ora ; r 4=offset_array 2+base_add_array 2 movl r 5, (r 4) ; array 2[offset_array 2]=array 2[offset_array 2]+1 addl #1, R 3 ; i=i+1 cmpl #R 2, R 3 jnz count ; R 2 base dell'array ; memorizzo frequenze in array 2 ; for (i=0; i<N; i++) { ; index=array 1[i]; ; array 2[index]++; ; } MOVL #dim, R 2 XORL R 3, R 3 array 1; count: xorl r 4, r 4 ; R 2 dimensione di array 1 ; R 3=0, contatore e offset per halt end
Prima soluzione: determiniamo il max su F Ora che abbiamo il vettore delle frequenze, il calcolo della moda si riconduce a determinare per quale i, F[i]=max{F} num. studenti 170=moda cm.
Codice org 1400 h array 2 equ 1500 h code MOVL #255, R 1 ; copia il lsb byte in R 1 ASLL #2, R 1 ADDL #array 2, R 1 ; in R 1 c’è l’indirizzo dell 256° elemento di Array 2 MOVL #array 2, R 2 ; R 2 puntatore all'array XORL R 3, R 3 ; R 3=0; MOVL #1, R 4 ; R 4=1 loop: MOVL (R 2)+, R 5 CMPB R 5, R 3 JNC skip ; se R 3>=R 5 salta a skip MOVL -(R 2), R 3 ; in R 3 c'è il massimo temp. MOVL R 2, R 4 ; in R 4 c'è l'indice corrisp. all'elemento massimo ADDL #4, R 2 skip: CMPB R 2, R 1 jnz loop ; condizione di uscita dal ciclo SUBL #ARRAY 2, R 4 ; R 4=[OFFSET_MAX_FREQUENZA*4] ASRL #2, R 4 ; R 4 / 4=OFFSET_MAX_FREQUENZA halt end
Ancora Moda… evitiamo il calcolo del vettore delle frequenze Dato un vettore di DIM dati da un byte, rappresentati come unsigned trovare: 1) l’elemento con il massimo numero di ricorrenze (moda) 2) il corrispondente numero di ricorrenze L’ALGORITMO MAX_NUM=0; //memorizza la moda MAX_RIC=0; //memorizza il numero di ricorrenze della moda FOR INT I=0 TO DIM-1 { IF ((I==0) || ( (I!=0) && (A[I]!=MAX_NUM) ) ) { // Conta il numero di ricorrenze dell’elemento i-esimo se e solo se I=0, oppure // I!=0 e l’elemento A[I] non è già la moda TEMP_RIC=0; FOR INT J=I TO DIM-1 { IF A[J]=A[I] TEMP_RIC++; } IF (TEMP_RIC>MAX_RIC) {MAX_RIC=TEMP_RIC; MAX_NUM=A[I]; } }
Codice ORG 400 H ARRAY EQU 1000 H DIMEQU 10 MAXNUM EQU 950 H MAXRIC EQU 951 H CODE XORL R 0, R 0 ; MAXNUM=0 XORL R 1, R 1 ; MAXRIC=0 XORL R 2, R 2 ; I=0 FOR 1: MOVB ARRAY(R 2), R 5; R 5=A[I]=ARRAY(R 2) CMPL #0, R 2 JZ DOIT ; IF (I==0) JMP DOIT CMPB R 5, R 0 ; ELSE IF A[I]== MAXNUM JZ NOMAX ; JMP NOMAX (SKIP INNER CICLE) DOIT: MOVL R 2, R 3 ; J=I XORL R 4, R 4 ; TEMPRIC=0 FOR 2: CMPB ARRAY(R 3), R 5 ; IF A[I]!=A[J] JNZ NOADD ; SKIP ADDL #1, R 4 ; TEMPRIC++ NOADD: ADDL #1, R 3 ; J++ CMPL #DIM, R 3 ; IF (J!=N) GOTO FOR 2 JNZ FOR 2 CMPL R 4, R 1 ; IF MAXRIC>TEMPRIC JNC NOMAX ; SKIP UPDATING MAX MOVL R 4, R 1 ; MAXRIC=TEMPRIC MOVB ARRAY(R 2), R 0; MAXNUM=A[I] NOMAX: ADDL #1, R 2 CMPL #DIM, R 2 JNZ FOR 1 ; I++ ; IF (R 2!=DIM) ; GOTO FOR 1 MOVB R 0, MAXNUM MOVL R 1, MAXRIC HALT END
Inversione di un array Dato un array di 10 elementi, memorizzato a partire da 250 h, rimpiazzarlo con l’array inverso (senza usare un altro vettore di appoggio). 250 h 254 h 258 h 25 Ch 260 h 264 h 268 h 26 Ch 270 h 274 h prima 11 1 21 5 2 13 4 8 9 3 250 h 254 h 258 h 25 Ch 260 h 264 h 268 h 26 Ch 270 h 274 h dopo 3 9 8 4 13 2 5 21 1 11
Il primo passo di esecuzione R 3=10/2=5 11 1 21 5 2 13 4 8 9 3 scambia (R 1) con (R 2) R 1 R 2 11 1 21 5 2 13 4 8 9 3 R 3=R 3 -1=4 3 1 21 5 2 13 4 8 9 11 R 2
Rappresentazione dell’informazione 250 h 254 h 258 h 25 Ch 260 h 264 h 268 h 26 Ch 270 h 274 h 11 1 21 5 2 13 4 8 9 3 336 (dec) 340 344 348 352 356 360 364 368 372 258 h 259 h 25 ah 25 bh 00010101 00000000 Base_Addr(Array) + (DIM-1)*size_of(elem) = Addr(Array[DIM-1]) 9*4=36 (OFFSET) 344 345 346 347 336 + 9*4= 372
Il codice ORG 400 H DIM EQU 10 ARRAY EQU 250 H CODE MOVL #ARRAY, R 2 MOVL #DIM, R 4 SUBL #1, R 4 ASLL #2, R 4 ; offset da sommare alla base dell'array per ottenere l'ultimo elemento ADDL R 4, R 2 ; in R 2 c'è l'indirizzo dell'ultimo elemento dell'array MOVL #ARRAY, R 1 ; R 1 <-indirizzo array MOVL #DIM, R 3 ; R 3<-10 (000. . . 00001010) ASRL #1, R 3 ; R 3=R 3/2=5 (000. . . 000000101) REPEAT: MOVL (R 1), R 0; R 0 registro d'appoggio per lo scambio MOVL (R 2), (R 1); Copia memoria dell'"ultimo" elemento sul "primo" MOVL R 0, (R 2); recupera il valore del primo elemento da R 0 e copialo in coda ADDL #4, R 1; avanza di 4 byte il valore dell'offset sul vettore originale SUBL #4, R 2; decrementa di 4 byte il valore dell'offset sul vettore invertito SUBL #1, R 3; decrementa il contatore JNZ REPEAT; fino a 0 HALT END
Un algoritmo per la moltiplicazione Il set di istruzioni del PD 32 non prevede istruzioni per effettuare la moltiplicazione tra due operandi. La moltiplicazione puo’ essere realizzata banalmente sommando al moltiplicando se stesso, un numero di volte pari al valore del moltiplicatore. 5*3=5+5+5=15. Tale algoritmo ha complessità computazionale pari a O(N), dove N è il valore del moltiplicatore. Vogliamo proporre un algoritmo per la moltiplicazione la cui complessità sia pari a O(log 2 N).
Moltiplicazione: primo approccio 00110 x 00101 = 00110 00000 00110 somme 00000 parziali 0000011110 00000 00110 00000 000110 0011110 0000011110 + somma parziale + + “prodotto parziale” + + Risultato finale
In altre parole. . . Traslo a destra il moltiplicatore di una posizione per verificare se il suo lsb vale 1. Il suo lsb finisce in C. C=1 C=0 Sommo il moltiplicando alla somma parziale. Traslo a destra la somma parziale, copiando il bit fuoriuscito (lsb della somma parziale) nel msb del moltiplicatore (che diventa passo dopo passo la parte meno significativa del risultato)
L’algoritmo (precondizioni) moltiplicando, A=6 moltiplicatore, D=5 0 0 1 1 0 A 0 0 0 B 0 0 0 1 C 0 1 D • Ripeti i seguenti passi tante volte quanti sono i bit di D. 1. Azzero C 2. Trasla a destra D 3. Se C=1 somma A e B 4. Trasla a destra B 5. Se C=1 inverto il bit più significativo di D
L’algoritmo (postcondizione) moltiplicando, A=6 Risultato=30 0 0 1 1 0 A 0 0 0 B 0 1 1 1 C 1 0 D Il risultato della moltiplicazione necessita di un numero di bits doppio per poter essere rappresentato. Per semplicità moltiplicando e moltiplicatore hanno 5 bits nel nostro esempio=> risultato scritto in 10 bits. I 5 MSB sono scritti in B, i 5 LSB sovrascrivono il moltiplicatore.
Il codice ADDL R 0, R 2 ORG 400 H LSRL #1, R 2 rls EQU 2000 h ; addr. parte meno sig. del risult. dopo: JNC poi rms EQU 2004 h ; addr. parte + sig. del risult. XORL #80000000 h, R 3 ; inverto il bit + significativo di A DL 6 ; variabile contenente il moltiplicando R 3 (d) D DL 5 ; variabile contente il moltiplicatore poi: SUBL #1, R 1 JNZ mult MOVL R 3, rls CODE MOVL A, R 0 ; carico il moltiplicando in R 0 MOVL D, R 3 ; carico il moltiplicatore in R 3 XORL R 2, R 2 ; azzero R 2 (B) MOVL R 2, rms MOVL #32, R 1; R 1 è il contatore: inizializzo a END ; 32, #bits moltiplicatore mult: CLRC LSRL #1, R 3 JNC dopo ; la parte meno significativa ; contenuta in R 3 viene caricata ; nella longword di memoria ; di indirzzo rls ; la parte più significativa in rms
- Slides: 24