2013-05-19 22 views
11

Jestem zdezorientowany różnicą między add a addu.Różnica między dodawaniem a dodawaniem

Odniesienie instrukcja MIPS mówi:

  • add (z przelewem)
  • dodać unsigned (bez przelewu)

Moje rozumienie jest użycie dodać z podpisanych argumentów i Addu z niepodpisanych argumentów .

Ale rozważmy ten przykład (tylko 6-bitowe):

 
overflow 
| 
V 
1 | 1 1 1 <- carry 
    | 1 1 1 1 0 1 + 
    | 1 1 1 1 1 0 = 
----------------- 
    | 1 1 1 0 1 1 

I to jest moje rozumowanie:

  • jeśli uważam pierwszy i drugi argument podpisaną numery (dwa uzupełniają) , wtedy wynik jest poprawny (-3 + -2 = -5) i nie chcę wyjątku przepełnienia. Więc użyłbym addu, aby uniknąć tego wyjątku, ale chociaż wynik jest taki sam, nazwa sugeruje użycie addu dla numerów bez znaku!
  • jeśli uważam pierwszy i drugi argument niepodpisany, to chcę, aby wyjątek został podniesiony (ponieważ 61 + 62 nie jest równe 59). Więc użyłbym dodaj, aby podnieść wyjątek, a nie addu, jak sugerowałaby nazwa.

Teraz moje pytania to:

  • zakładając, że argumenty są podpisane (ujemne w powyższym przykładzie) Numery, należy użyć Addu (jak sugeruje moje rozumowanie) lub powinno się używać dodać (jak nazwa wskazuje)?
  • zakładając, że operandy są liczbami niepodpisanymi (dodatnimi), czy powinienem użyć add (jak sugeruje moje rozumowanie) lub addu (jak sugeruje nazwa)?
+1

bardzo źle nazwane instrukcje. nie ma czegoś takiego jak niepodpisany add lub dodany podpis. ma to związek z zalewkowaniem lub nie powinno być dodatkiem lub czymś takim ... (nadal może być, ponieważ asembler nie jest czymś wyryte w kamieniu, jak kod maszynowy) –

Odpowiedz

5

Jeśli używasz liczb z podpisem, powinieneś użyć add, jeśli chcesz, aby pułapka była generowana, gdy wynik się przepełni.

Jeśli używasz numerów bez znaku, zawsze powinieneś używać addu i sprawdzać przepełnienie dodania, porównując wynik z dowolnymi liczbami (jeśli wynik jest mniejszy niż argumenty, które wystąpiły w wyniku dodania).

Tu idzie fragment, aby pokazać, jak można sprawdzić przepełnienia w unsigned Ponadto:

li $a1, 0xFFFF0FFF 
    li $a2, 0x00010000 

    addu $a3, $a1, $a2 # This unsigned addition overflows (set $a3 to $a1+$a2) 
    bgt $a1, $a3, overflowed 
    bgt $a1, $a2, overflowed 
    # If you get here, unsigned addition did not overflow 
    # your code goes here... 
overflowed: 
    # If you get here, unsigned addition overflowed 
    # your code goes here... 
+0

Dzięki za odpowiedź! ale ... Dlaczego chciałbym pułapkę wyjątku na podpisane numery? Podniesie się za każdym razem, gdy wynik będzie liczbą ujemną. Po drugie, czy możesz podać przykład kontroli przepełnienia w drugim przypadku (np. W przypadku liczb niepodpisanych)? Dlaczego warto korzystać z tego rodzaju kontroli przepełnienia, gdy mogę po prostu użyć opcji dodawania? – collimarco

+1

@collimarco: Nie zostanie podniesiony za każdym razem, gdy wynik będzie liczbą ujemną. Zostanie on podniesiony, jeśli wynik operacji przepełni się (tj. Wynikowa liczba, widziana w komplementie A2, nie jest właściwą liczbą). Na przykład, jeśli dodasz -3 + -5, wynik będzie ujemny (-8) i nie zostanie podniesiona pułapka. – gusbro

10

Nazwy instruktażowe są mylące. Użyj addu dla podpisanych i niepodpisanych operandów, jeśli chcesz , a nie, potrzebujesz pułapki na przepełnienie.

Użyj add, jeśli potrzebujesz pułapki na przelew z jakiegoś powodu. Większość języków nie chce mieć pułapki na podpisane przepełnienie, więc add jest rzadko przydatna.

3

przelewowy NIE deklarowanego w pytaniu, to carry bit to nie jest nieco przepełnienie, w podanym przykładzie nie ma przelewu, przelew jest gdy:

MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0 
OR 
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1 

tak trzymać add to będzie przepełnienie flagi, a bit przenoszenia w twoim przykładzie (który nie jest przepełnieniem) nie będzie ci przeszkadzał. addu robi to samo, z wyjątkiem tego, że nie zgłoszono żadnego wyjątku.

0

W rzeczywistości nie jest to przepełnienie w twoim przykładzie. Przepełnienie występuje, gdy przeniesienie do bitu znaku nie jest równe przeprowadzeniu bitu znaku. W twoim przykładzie, chociaż wykonanie bitu znaku jest "1" (pozornie przepełnienie), bit do przeniesienia do znaku jest również "1". Dlatego w tym stanie MIPS nie uzna go za przelew. Wzorzec występowania przepełnienia odpowiada faktycznie temu, czy wynik jest poprawny. Oznacza to, że jeśli wynik jest poza zakresem, który reprezentują twoje bity, występuje przepełnienie. Na przykład, jeśli dodasz dwa 4-bitowe numery 0111 (7) i 0010 (2), otrzymasz przepełnienie, ponieważ wynik (9) jest poza zakresem, który może reprezentować 4-bitowy numer (-8 do 7) . Jeśli spojrzeć na arytmetyce:

0111 (7) + 0010 (2) = 1001 (-7) 

widać, że chociaż nie ma przeniesienia z bitu znaku, wynik jest nadal nieprawidłowa. Dlatego jest to przepełnienie (i MIPS wykryje je).