Vettori: indicizzazione in base alla posizione
Un vettore è un array: una sequenza di numeri memorizzati uno accanto all'altro in memoria. Nella lezione precedente ne hai sommato uno spostando un puntatore in avanti di 4 byte per ogni elemento. Lo stesso metodo funziona qui. C'è un altro modo comune per raggiungere un elemento: tramite indice. Un indice è la posizione di un elemento contata dall'inizio, dove il primo elemento ha indice 0, il secondo ha indice 1, e così via.
Somma un vettore avanzando un puntatore
.dataa: .word 5, 10, 15, 20 # quattro elementi.textla t0, a # t0 = indirizzo di ali t1, 4 # t1 = numero di elementi rimanentili t2, 0 # t2 = somma correnteloop:beq t1, zero, donelw t3, 0(t0) # carica l'elemento correnteadd t2, t2, t3 # aggiunge al totaleaddi t0, t0, 4 # avanza alla parola successiva (4 byte)addi t1, t1, -1 # uno in menoj loopdone:mv a0, t2 # stampa il totale: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Il ciclo funziona come segue. t0 contiene l'indirizzo di a, e t1 contiene il numero di elementi rimanenti, a partire da 4. A ogni passaggio, termina il ciclo quando il conteggio raggiunge zero. carica l'elemento all'indirizzo in t0. aggiunge quel valore al totale corrente. fa avanzare il puntatore alla parola successiva. decrementa il conteggio. Dopo quattro passaggi (5 + 10 + 15 + 20), done stampa 50. Questo è lo stesso schema usato nella lezione sulla memoria, ora applicato a un vettore.
Dall’indice all’indirizzo
L'indicizzazione calcola un indirizzo da un puntatore di base e una posizione: address = base + index * 4. Il 4 è la dimensione di una parola in byte. Un compilatore genera questo stesso calcolo per a[i] in un linguaggio come C. L'indice stesso non accede mai alla memoria. Solo l'indirizzo calcolato da esso lo fa.
slli t5, t3, 2 # t5 = indice * 4 (dimensione di una parola)add t6, t0, t5 # t6 = indirizzo di element[index]lw t6, 0(t6) # t6 = element[index]
sposta l'indice in t3 a sinistra di 2 bit, il che lo moltiplica per 4 (due raddoppi: 2 x 2), la dimensione di una parola. Aggiungendo il risultato al puntatore di base si ottiene l'indirizzo di element[index]. Questo spostamento è lo stesso metodo delle potenze di due della lezione sull'aritmetica, ed è il modo standard per scalare un indice in base alla dimensione di una parola.
a[0]: indice 0, offset 0.
i come posizione, e l'indirizzo che quella posizione produce dopo che lo scala di 4 e lo aggiunge alla base. I numeri esadecimali sono gli indirizzi reali che a occupa quando il simulatore esegue questo programma. L'obiettivo è prevedere l'indirizzo successivo prima che compaia. Questo ti permette di leggere dentro un ciclo incrementale, o a[i] in un linguaggio simile a C, e immaginare l'indirizzo di memoria che tocca invece di trattare la notazione come una scatola nera.Sommare un vettore per indice
.dataa: .word 5, 10, 15, 20 # quattro elementi.textla t0, a # t0 = indirizzo base di ali t1, 4 # t1 = numero di elementili t2, 0 # t2 = indice, inizia a 0li t3, 0 # t3 = totale cumulativoloop:beq t2, t1, doneslli t4, t2, 2 # t4 = indice * 4 (offset in byte)add t5, t0, t4 # t5 = indirizzo di a[index]lw t5, 0(t5) # t5 = a[index]add t3, t3, t5 # total += a[index]addi t2, t2, 1 # passa all'indice successivoj loopdone:mv a0, t3 # stampa il totale: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Il ciclo funziona come segue. t2 è l'indice, a partire da 0. A ogni passaggio, termina il ciclo quando l'indice raggiunge 4, il conteggio degli elementi contenuto in t1. converte l'indice in un offset in byte. aggiunge quell'offset all'indirizzo di base in t0 per produrre l'indirizzo di a[index]. carica il valore memorizzato lì. Quel valore viene aggiunto al totale corrente in t3, e avanza all'indice successivo. Dopo quattro passaggi (5 + 10 + 15 + 20), done stampa 50.
Somma di due vettori, elemento per elemento
.dataa: .word 3, 6, 9, 12 # primo vettoreb: .word 1, 2, 3, 4 # secondo vettorec: .space 16 # spazio per 4 parole di risultato.textla t0, a # indirizzo base di ala t1, b # indirizzo base di bla t2, c # indirizzo base di cli t3, 0 # indice, inizia da 0li t4, 4 # numero di elementili s0, 0 # totale correnteloop:beq t3, t4, doneslli t5, t3, 2 # offset in byte = indice * 4add t6, t0, t5 # indirizzo di a[index]lw t6, 0(t6) # valore di a[index]add a0, t1, t5 # indirizzo di b[index]lw a0, 0(a0) # valore di b[index]add t6, t6, a0 # a[index] + b[index]add a0, t2, t5 # indirizzo di c[index]sw t6, 0(a0) # c[index] = a[index] + b[index]add s0, s0, t6 # totale += c[index]addi t3, t3, 1 # passa all'indice successivoj loopdone:mv a0, s0 # stampa il totale: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
Il ciclo funziona come segue. converte l'indice t3 in un offset in byte. Aggiungendolo a ciascun puntatore di base (t0, t1, t2) si ottengono gli indirizzi di a[i], b[i] e c[i]. A ogni passaggio, entrambi gli elementi vengono caricati, sommati, memorizzati in c, e aggiunti al totale corrente in s0. avanza all'indice successivo, e il ciclo si ripete finché tutti e quattro gli elementi non sono elaborati.
