Wektory: indeksowanie według pozycji
Wektor to tablica: ciąg liczb przechowywanych obok siebie w pamięci. W poprzedniej lekcji sumowałeś go, przesuwając wskaźnik o 4 bajty dla każdego elementu. Ta sama metoda działa tutaj. Istnieje inny powszechny sposób dotarcia do elementu: przez indeks. Indeks to pozycja elementu liczona od początku, gdzie pierwszy element ma indeks 0, drugi ma indeks 1, i tak dalej.
Zsumuj wektor, przesuwając wskaźnik
.dataa: .word 5, 10, 15, 20 # cztery elementy.textla t0, a # t0 = adres ali t1, 4 # t1 = liczba pozostałych elementówli t2, 0 # t2 = suma bieżącaloop:beq t1, zero, donelw t3, 0(t0) # wczytuje bieżący elementadd t2, t2, t3 # dodaje do sumyaddi t0, t0, 4 # przechodzi do następnego słowa (4 bajty)addi t1, t1, -1 # o jeden mniejj loopdone:mv a0, t2 # wypisuje sumę: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Pętla działa następująco. t0 przechowuje adres a, a t1 przechowuje liczbę pozostałych elementów, zaczynając od 4. W każdym przebiegu kończy pętlę, gdy licznik osiągnie zero. ładuje element spod adresu w t0. dodaje tę wartość do sumy bieżącej. przesuwa wskaźnik do następnego słowa. zmniejsza licznik. Po czterech przebiegach (5 + 10 + 15 + 20) done wypisuje 50. To ten sam wzorzec użyty w lekcji o pamięci, teraz zastosowany do wektora.
Od indeksu do adresu
Indeksowanie oblicza adres na podstawie wskaźnika bazowego i pozycji: address = base + index * 4. Liczba 4 to rozmiar słowa w bajtach. Kompilator generuje to samo obliczenie dla a[i] w języku takim jak C. Sam indeks nigdy nie uzyskuje dostępu do pamięci. Robi to tylko obliczony z niego adres.
slli t5, t3, 2 # t5 = indeks * 4 (rozmiar słowa)add t6, t0, t5 # t6 = adres element[index]lw t6, 0(t6) # t6 = element[index]
przesuwa indeks w t3 o 2 bity w lewo, co mnoży go przez 4 (dwa podwojenia: 2 x 2), rozmiar jednego słowa. Dodanie wyniku do wskaźnika bazowego daje adres element[index]. To przesunięcie to ta sama metoda potęg dwójki z lekcji arytmetyki i standardowy sposób skalowania indeksu przez rozmiar słowa.
a[0]: indeks 0, przesunięcie 0.
i jako pozycja oraz adres, który ta pozycja wytwarza po tym, jak skaluje ją przez 4 i dodaje do bazy. Liczby szesnastkowe to rzeczywiste adresy, które zajmuje a, gdy symulator uruchamia ten program. Celem jest przewidzenie następnego adresu, zanim się pojawi. To pozwala czytać wewnątrz pętli inkrementującej lub a[i] w języku typu C i wyobrażać sobie adres pamięci, którego dotyka, zamiast traktować notację jak czarną skrzynkę.Sumowanie wektora przez indeks
.dataa: .word 5, 10, 15, 20 # cztery elementy.textla t0, a # t0 = adres bazowy ali t1, 4 # t1 = liczba elementówli t2, 0 # t2 = indeks, zaczyna się od 0li t3, 0 # t3 = suma bieżącaloop:beq t2, t1, doneslli t4, t2, 2 # t4 = indeks * 4 (przesunięcie bajtowe)add t5, t0, t4 # t5 = adres a[index]lw t5, 0(t5) # t5 = a[index]add t3, t3, t5 # total += a[index]addi t2, t2, 1 # przechodzi do następnego indeksuj loopdone:mv a0, t3 # wypisuje sumę: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Pętla działa następująco. t2 to indeks, zaczynający od 0. W każdym przebiegu kończy pętlę, gdy indeks osiągnie 4, liczbę elementów przechowywaną w t1. konwertuje indeks na przesunięcie w bajtach. dodaje to przesunięcie do adresu bazowego w t0, aby uzyskać adres a[index]. ładuje wartość tam przechowywaną. Ta wartość jest dodawana do sumy bieżącej w t3, a przechodzi do następnego indeksu. Po czterech przebiegach (5 + 10 + 15 + 20) done wypisuje 50.
Dodawanie dwóch wektorów, element po elemencie
.dataa: .word 3, 6, 9, 12 # pierwszy wektorb: .word 1, 2, 3, 4 # drugi wektorc: .space 16 # miejsce na 4 słowa wyniku.textla t0, a # adres bazowy ala t1, b # adres bazowy bla t2, c # adres bazowy cli t3, 0 # indeks, zaczyna się od 0li t4, 4 # liczba elementówli s0, 0 # suma bieżącaloop:beq t3, t4, doneslli t5, t3, 2 # przesunięcie w bajtach = indeks * 4add t6, t0, t5 # adres a[index]lw t6, 0(t6) # wartość a[index]add a0, t1, t5 # adres b[index]lw a0, 0(a0) # wartość b[index]add t6, t6, a0 # a[index] + b[index]add a0, t2, t5 # adres c[index]sw t6, 0(a0) # c[index] = a[index] + b[index]add s0, s0, t6 # suma += c[index]addi t3, t3, 1 # przechodzi do następnego indeksuj loopdone:mv a0, s0 # wypisuje sumę: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
Pętla działa następująco. konwertuje indeks t3 na przesunięcie w bajtach. Dodanie go do każdego wskaźnika bazowego (t0, t1, t2) daje adresy a[i], b[i] i c[i]. W każdym przebiegu oba elementy są ładowane, dodawane do siebie, zapisywane do c i dodawane do sumy bieżącej w s0. przechodzi do następnego indeksu, a pętla powtarza się, aż wszystkie cztery elementy zostaną przetworzone.
