Esercizi Assembly. Un programma per calcolare la media Dato un vettore di 32 bytes unsigned...
-
Upload
immacolata-grosso -
Category
Documents
-
view
241 -
download
1
Transcript of Esercizi Assembly. Un programma per calcolare la media Dato un vettore di 32 bytes unsigned...
Esercizi Assembly
Un programma per calcolare la media
Dato un vettore di 32 bytes unsigned memorizzato a partire dalla locazione 0x20a0, 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 ff ff
0x20a0 V[0]V[1]V[2]
…
V[31]
V[31]=Σi=031V[i]/32
Come gestire l’overflow?L’istruzione da controllare e’:
addb (R1)+, R2
Microcodice :
1. MAR<-R1
2. R1<-R1+1
3. Temp1<-[MDR] 8 //gli 8 lsbs di MDR estesi in segno vanno in T1
4. Temp2<-[R2] 8 //gli 8 lsbs di R2 estesi in segno vanno in T2
5. ALU_OUT=Temp1+Temp2
Se (Temp1 + Temp2) >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 codiceorg 400hARRAY EQU 20a0h ; indirizzo base arrayDIM EQU 32 ; num.elementi arrayLOG2DIM EQU 5 ; log. base 2 di DIM
codemovl #DIM,R0movl #ARRAY,R1xorl R2,R2 ;resetta R2, risultato parziale
loop: addb (R1)+,R2 ;somma i-esimo elem. i=0..DIM-1jc error ;bit c settato =>Overflowsubl #1,R0 ;decrementa contatorejnz loop ;se contatore!=0 continua il ciclalsrb #LOG2DIM, R2;dividi per il numero di elementi,
;usiamo LSRB poichè lavoriamo con unsignedmovb R2, -(R1) ;memorizza la media in ARRAY[DIM-1]jmp fine
error: movl #DIM, R1 ;gestione overflow, calcola in R1addl #ARRAY, R1 ; R1=ARRAY+DIMsubl #1,r1xorl R3,R3notl R3,R3 ; R3=111....111movb R3,(R1) ; ARRAY[DIM]=11111111
fine: haltend
Una variazione sul tema… ora, senza contatore!
Calcolare la media di 128 words memorizzate a partire dall’indirizzo 0x20ab, ma senza impiegare un registro appositamente come contatore (R0 del programma precedente) .
0x20 ab V[0]V[1]V[2]
…
V[127]
V[127]=Σi=0127V[i]/127
0x21a9
0x20ad
0x21 ab
NOTA: non si considera l’overflow.
Il codice (funziona solo se il numero di elementi è pari a 128 words)
org 400h ; programma allocato a partire da 400hDATI EQU 20abh ;indirizzo inizio
code ;inizio istruzionimain:
xorl R2,R2 ; R2=risult.parzialemovl #DATI,R1 ; puntatore elementomovb R1,R0 ; copio lsB addr. inizio
; in R0loop: addw (R1)+, R2
cmpb R1,R0 ; lsB addr. elemento; e' = lsB addr. inizio ?
jnz looplsrw #7,R2 ; divido per 128movw R2,-(R1)halt ;serve solo per bloccare il simulatore
end ;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.
PROBLEMA:
Trovare l’altezza piu’ frequente tra gli studenti (moda).
altezza
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.
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}
num.studenti
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++) { array2[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=array1[i];
array2[index]++; }
Codiceorg 1400harray1 equ 800h ; V, vettore originalearray2 equ 1500h ; F, vettore frequenzedim equ 30code
;inizializzo array2 con tutti 0; for (i=0;i<256;i++) {; array2[i]=0;; };
MOVL #array2,R5 ;R2 base dell'arraymovl #0,r4
clean: movl #0, (R5)+addl #1,r4cmpl #0ffh,r4jc clean
; memorizzo frequenze in array2; for (i=0;i<N;i++) {; index=array1[i];; array2[index]++;; }
MOVL #dim,R2 ;R2 dimensione di array1XORL R3,R3 ;R3=0, contatore e offset per array1;
count: xorl r4,r4 ; r4 è inizializzato a zero perchè la successiva mvlb ; si aspetta i 3 bytes + significativi di R4 uguali a 0
mvlb array1(R3),R4 ;R4=V[i]=array1[R3] ;NOTA: MVLB non estende il segno
aslw #2,R4 ;offset_array2=R4*4;Moltiplicando per 4 il contenuto ;del lsb di R4 possiamo avere trabocchi, ;quindi usiamo aslw per operare con 2
bytemovl array2(R4),r5 ;r5=array2[offset_array2]
addl #1,r5 ; r5=array2[offset_array2]+1addl #array2,r4 ; prima r4 era = offset_array2, ora
;r4=offset_array2+base_add_array2movl r5,(r4) ;array2[offset_array2]=array2[offset_array2]+1addl #1,R3 ; i=i+1
cmpl #R2,R3jnz count
haltend
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
cm.170=moda
Codiceorg 1400harray2 equ 1500h
codeMOVL #255,R1 ;copia il lsb byte in R1ASLL #2,R1ADDL #array2,R1 ; in R1 c’è l’indirizzo dell 256° elemento di Array2MOVL #array2,R2 ;R2 puntatore all'arrayXORL R3,R3 ;R3=0;MOVL #1,R4 ;R4=1
loop:MOVL (R2)+,R5CMPB R5,R3JNC skip ; se R3>=R5 salta a skipMOVL -(R2),R3 ; in R3 c'è il massimo temp.MOVL R2,R4 ; in R4 c'è l'indice corrisp.all'elemento massimoADDL #4,R2
skip: CMPB R2,R1
jnz loop ; condizione di uscita dal cicloSUBL #ARRAY2,R4 ; R4=[OFFSET_MAX_FREQUENZA*4]ASRL #2,R4 ; R4 / 4=OFFSET_MAX_FREQUENZAhalt
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 modaMAX_RIC=0; //memorizza il numero di ricorrenze della modaFOR 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];}}
CodiceORG 400H
ARRAY EQU 1000HDIMEQU 10MAXNUM EQU 950HMAXRIC EQU 951H
CODE
XORL R0,R0 ; MAXNUM=0XORL R1,R1 ; MAXRIC=0XORL R2,R2 ; I=0
FOR1: MOVB ARRAY(R2),R5; R5=A[I]=ARRAY(R2)
CMPL #0,R2JZ DOIT ; IF (I==0) JMP DOITCMPB R5,R0 ; ELSE IF A[I]== MAXNUMJZ NOMAX ; JMP NOMAX (SKIP INNER CICLE)
DOIT:MOVL R2,R3 ;J=IXORL R4,R4 ;TEMPRIC=0
FOR2: CMPB ARRAY(R3), R5 ; IF A[I]!=A[J]
JNZ NOADD ; SKIP ADDADDL #1,R4 ; TEMPRIC++
NOADD:ADDL #1,R3 ; J++CMPL #DIM,R3 ; IF (J!=N) GOTO FOR2JNZ FOR2CMPL R4,R1 ; IF MAXRIC>TEMPRIC
JNC NOMAX ; SKIP UPDATING MAXMOVL R4,R1 ; MAXRIC=TEMPRICMOVB ARRAY(R2),R0; MAXNUM=A[I]
NOMAX: ADDL #1,R2 ; I++
CMPL #DIM,R2 ; IF (R2!=DIM) JNZ FOR1 ; GOTO FOR1
MOVB R0, MAXNUMMOVL R1, MAXRICHALT
END
Inversione di un array Dato un array di 10 elementi, memorizzato a partire
da 250h, rimpiazzarlo con l’array inverso (senza usare un altro vettore di appoggio).
12152
134893
11prima
984
1325
211
11
3dopo
250h254h258h25Ch260h264h268h26Ch270h274h
250h254h258h25Ch260h264h268h26Ch270h274h
Il primo passo di esecuzione
12152
134893
11 R1
R2
12152
134893
111
2152
13489
11
3R1
R2
R3=10/2=5 R3=R3-1=4scambia (R1) con (R2)
Rappresentazione dell’informazione
12152
134893
11250h254h258h25Ch260h264h268h26Ch270h274h
336 (dec)340344348352356360364368372
00010101000000000000000000000000
258h259h25ah25bh
344345346347
Base_Addr(Array) +(DIM-1)*size_of(elem) =Addr(Array[DIM-1])
336 +9 * 4 =372
9*4=36 (OFFSET)
ORG 400HDIM EQU 10ARRAY EQU 250H
CODEMOVL #ARRAY,R2 MOVL #DIM,R4SUBL #1,R4ASLL #2,R4 ; offset da sommare alla base dell'array per ottenere l'ultimo elementoADDL R4,R2 ; in R2 c'è l'indirizzo dell'ultimo elemento dell'array MOVL #ARRAY,R1 ; R1 <-indirizzo arrayMOVL #DIM,R3 ; R3<-10 (000... 00001010)ASRL #1,R3 ; R3=R3/2=5 (000... 000000101)
REPEAT:MOVL (R1),R0; R0 registro d'appoggio per lo scambioMOVL (R2),(R1); Copia memoria memoria dell'"ultimo" elemento sul "primo"MOVL R0,(R2); recupera il valore del primo elemento da R0 e copialo in codaADDL #4,R1; avanza di 4 byte il valore dell'offset sul vettore originale SUBL #4,R2; decrementa di 4 byte il valore dell'offset sul vettore invertitoSUBL #1,R3; decrementa il contatoreJNZ REPEAT; fino a 0
HALTEND
Il codice
Un algoritmo per la moltiplicazione
Il set di istruzioni del PD32 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(log2N).
Moltiplicazione: primo approccio
00110 x00101 =
00110 00000 00110 0000000000000011110
sommeparziali
00000 + 00110 00110 + 00000 000110 + 00110 0011110 + 00000 00011110 +00000000011110
somma parziale
“prodotto parziale”
Risultatofinale
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.
Sommo il moltiplicando alla somma parziale.
C=1C=0
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)
0 00 1 1 0
0 0 0 0 0
A C
0 0 1 0 1 DB
moltiplicando, A=6 moltiplicatore,D=5
• Ripeti i seguenti passi tante volte quanti sono i bit di D.1. Azzero C2. Trasla a destra D3. Se C=1 somma A e B4. Trasla a destra B5. Se C=1 inverto il bit più significativo di D
L’algoritmo (postcondizione)
0 00 1 1 0
0 0 0 0 0
A C
1 1 1 1 0 DB
moltiplicando, A=6
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.
Risultato=30
Il codice
ORG 400Hrls EQU 2000h ;addr.parte meno sig.del risult.rms EQU 2004h ;addr.parte + sig.del risult. A DL 6 ; variabile contenente il moltiplicandoD DL 5 ; variabile contente il moltiplicatore
CODEMOVL A,R0 ; carico il moltiplicando in R0MOVL D,R3 ; carico il moltiplicatore in R3XORL R2,R2 ; azzero R2 (B)MOVL #32,R1; R1 è il contatore: inizializzo a
; 32, #bits moltiplicatoremult: CLRC
LSRL #1, R3JNC dopo
ADDL R0,R2dopo: LSRL #1,R2
JNC poiXORL #80000000h, R3 ;inverto il bit + significativo di R3 (d)
poi: SUBL #1, R1JNZ multMOVL R3, rls ; la parte meno significativa
; contenuta in R3 viene caricata ; nella longword di memoria
; di indirzzo rlsMOVL R2,rms ; la parte più significativa in rms
END