Robienie matematyki

Robienie matematyki

Wszystkie obliczenia odbywają się między rejestrami. Instrukcja arytmetyczna podaje najpierw miejsce docelowe, a następnie dwa źródła, które odczytuje: oznacza dest = src1 + src2.

Operacja arytmetyczna
t2, t0, t1←add
t0 = 7t1 = 5+t2 = 12

add umieszcza t0 + t1 w t2.

Dwie linie wchodzące z lewej to t0 i t1, zawsze w tej kolejności. Wchodzą w ten sam kształt niezależnie od wykonywanej operacji: dodawania, odejmowania, mnożenia, dzielenia lub reszty. Wchodzą dwie wartości, zachodzi jedna operacja i wychodzi jeden wynik do t2 po prawej. wymienia t2 jako pierwsze, ponieważ tam trafia wynik, co odpowiada jedynej regule kolejności, której przestrzega każda instrukcja arytmetyczna w tej lekcji.

Dodawanie i odejmowanie

pobiera liczby przechowywane w dwóch rejestrach i zapisuje ich sumę w trzecim. robi to samo dla odejmowania: oblicza t0 - t1. Obie instrukcje czytają wyłącznie z rejestrów.

Rejestracja arytmetyki
add t2, t0, t1 # t2 = t0 + t1
sub t2, t0, t1 # t2 = t0 - t1

Jedna rzecz do zapamiętania: rejestr przechowuje tylko 32 bity, więc istnieje górny limit. Jeśli wynik jest zbyt duży, aby się zmieścić, nie jest zgłaszany żaden błąd. Wartość po cichu zawija się do bardzo małych liczb i wykonanie jest kontynuowane. Codzienne wartości nie osiągną tego limitu, ale warto o tym wiedzieć.

Aby użyć stałej liczby zamiast drugiego rejestru, dodaj literę i, która oznacza natychmiastowy: dodaje stałą 1. Nie ma subi, więc aby odjąć stałą, dodaje się liczbę ujemną: .

💡
dodaje stałą. dodaje dwa rejestry. Pomylenie tych dwóch to najczęstszy błąd początkujących.

Mnożenie i dzielenie

mnoży dwa rejestry. dzieli je jako liczby całkowite i odrzuca ułamek, więc 7 / 2 daje 3. zwraca resztę, więc 7 % 2 daje 1. Dzielenie nigdy nie powoduje awarii. Dzielenie przez zero zwraca -1.

Mnożenie, dzielenie, reszta
mul t2, t0, t1 # t2 = t0 * t1
div t2, t0, t1 # t2 = t0 / t1 (całkowite)
rem t2, t0, t1 # t2 = t0 % t1 (reszta)

Łączenie elementów

Dodaj dwie liczby i wyświetl wynik
li t0, 7
li t1, 5
add t1, t0, t1 # t1 = 7 + 5 = 12
mv a0, t1 # usługa wypisywania odczytuje a0
li a7, 1
ecall
li a7, 10
ecall

ładuje 7 do t0. ładuje 5 do t1. dodaje je i zapisuje 12 do t1. kopiuje wynik do a0, ponieważ usługa drukowania zawsze odczytuje swoją wartość z a0. Następnie wybiera usługę drukowania liczby całkowitej, a ją uruchamia. Na koniec i kończą program.

Dodatkowe zadanie: mnożenie z przesunięciami

Gdy czynnik jest potęgą dwójki, istnieje szybsza metoda niż . (przesunięcie logiczne w lewo) przesuwa bity rejestru w lewo, a każde przesunięte miejsce podwaja wartość: przesuń o 1, aby pomnożyć przez 2, o 2 dla 4, o 3 dla 8. Przesunięcie kosztuje mniej niż mnożenie, więc kompilatory często go używają.

Mnożenie przez 8 za pomocą przesunięć
li t0, 5 # zacznij od 5
# przesunięcie w lewo o 3 bity (5 * 2^3 = 5 * 8)
sll a0, t0, 3 # a0 = 40
li a7, 1 # wypisz liczbę całkowitą
ecall
li a7, 10
ecall

umieszcza 5 w t0. przesuwa jego bity o trzy miejsca w lewo. Każde miejsce podwaja wartość, więc 5 podwaja się trzy razy (5, 10, 20, 40), dając 40 w a0. Reszta przebiega według wzorca drukowania z wcześniej. Spróbuj zmienić 3 na 1 lub 2 i przewidź wynik, zanim go uruchomisz.

Mnożenie przez przesunięcie
5sll a0, t0, 0
×2 →
10sll a0, t0, 1
×2 →
20sll a0, t0, 2
×2 →
40sll a0, t0, 3
0
0
0
0
0
1
0
1

5 przesunięte w lewo o 0 bitów pozostaje 5.

Osiem pól to binarna postać liczby nad nimi, po jednym bicie każde, czytane od lewej do prawej jak zwykle. Przesunięcie całego wiersza o jedną pozycję w lewo to ta sama operacja co pomnożenie przez 2, ponieważ przesunięcie cyfry o jedno miejsce w lewo w dowolnym systemie mnoży jej wartość przez podstawę tego systemu. System binarny ma tylko dwie cyfry, więc mnożnikiem jest 2. Przesunięcie trzy razy składa się w pomnożenie przez 8, co odpowiada temu, co robi z liczbą 5.