Statycznie odwracam niektóre programy skompilowane dla Atheros AR7161 przy użyciu radare2. Ten procesor implementuje MIPS i pamiętam, że MIPS ma gniazdo opóźnienia gałęzi. Jest to rzeczywiście zauważalne podczas deasemblacji, ponieważ widzę instrukcje, które powinny logicznie wykonać, zanim gałęzie zostaną umieszczone tuż po nich.
Jednak podczas analizy jakiegoś fragmentu kodu natrafiłem na instrukcję beqz, dla której zakładając, że instrukcja, która powinna zostać wykonana jako pierwsza, nie ma sensu w kontekście programu. Muszę przyznać, że moja analiza może być błędna, co nie jest nieprawdopodobne; jednakże mam pewne wątpliwości, które chciałbym również wyjaśnić:
-
Czy wszystkie instrukcje rozgałęzienia / skoku zawsze używają gniazda opóźnienia gałęzi tak, że instrukcja bezpośrednio po niej powinna być logicznie wykonana jako pierwsza ? Jeśli nie, w jakich przypadkach by tak nie było?
-
Czy istnieje sposób, aby radare2 pokazywał logiczną kolejność wykonywania zamiast tego zakodowanego w pliku binarnym?
Edytuj : konkretnie mam do czynienia z następującą sekwencją:
beqz v0, <some address> lb v0, 0x40(sp)
Mam w głowie bardzo rozmyty obraz tej instrukcji wchodzącej do potoku. Mogę sobie wyobrazić, że druga instrukcja jest pobierana podczas dekodowania pierwszej; stąd , wykonanie szczeliny opóźnienia rozgałęzienia powinno faktycznie rozpocząć się. Jednak instrukcja rozgałęzienia zależy od modyfikacji tego samego rejestru przez instrukcję w szczelinie opóźnienia gałęzi, więc co się stanie? Czy instrukcja rozgałęzienia oceni warunek przy użyciu starego rejestru va lue, czy nowy zaktualizowany o lb?
Dzięki
Komentarze
- Czytanie serii MIPS może przynieść korzyści Raymond Chen tutaj: link Pierwsza odpowiedź brzmi: nie (i zobacz link, aby uzyskać szczegółowe informacje). Nie mogę ' odpowiedzieć na drugie pytanie.
Odpowiedź
Instrukcja w szczelinie opóźnienia rozgałęzienia jest oceniana po instrukcji rozgałęzienia (lub skoku). Wykonanie instrukcji w gałęzi opóźnienia gałęzi nie wpływa na ocenę warunku rozgałęzienia.
Zauważyłem, że gniazdo opóźnienia gałęzi jest używane do kilku rzeczy:
- Ostatnia instrukcja bloku podstawowego prowadząca do instrukcji rozgałęzienia
- Test rozgałęzienia nie będzie zależny od wyniku obliczania instrukcji szczeliny opóźnienia gałęzi
- Często spotykane w przypadku bezwarunkowych skoków / rozgałęzień na przykład
b
,jal
- Pierwsza instrukcja bloku przejścia .
- Żadne skutki uboczne nie powinny występować, jeśli branża jest zajęta.
- Analiza pokaże, że żadne rejestry, których to dotyczy, nie są potrzebne w przypadku zajęcia gałęzi.
- Pierwsza instrukcja bloku, jeśli brana jest gałąź
- Jeśli istnieje wiele ścieżek do celu rozgałęzienia, ta instrukcja prawdopodobnie pojawi się wiele razy z różnymi gałęziami
- Ładowanie wartości warunkowej, często zwracanej
Ten artykuł omawia szczegółowo szczeliny opóźnienia gałęzi.
Jak zauważył Igor, „prawdopodobna” wersja instrukcji rozgałęzienia zachowuje efekty instrukcji w szczelinie opóźnienia gałęzi tylko wtedy, gdy instrukcja jest faktycznie pobierana.
Odpowiedź
- Istnieją odmiany gałęzi warunkowych zwanych „gałąź [pod warunkiem] prawdopodobna”, np.
-
bgezl
– gałąź większa niż lub równa zeru prawdopodobnie -
beql
– gałąź włączona Równie prawdopodobne
-
Te instrukcje mają szczelinę opóźnienia, ale instrukcja w szczelinie opóźnienia jest wykonywana tylko jeśli gałąź jest zajęta. Jeśli gałąź nie zostanie pobrana, instrukcja w gnieździe opóźnienia jest nie wykonywana ( zerowana ) .
Uwaga: te instrukcje zostały usunięte w wydaniu 6 architektury MIPS. Dodał również kompaktowe odmiany gałęzi, które nie mają slotów opóźnienia
Jeśli chodzi o twój fragment, mocno podejrzewam, że gałąź używa starej wartości rejestru, ale prawdopodobnie możesz to potwierdzić tylko poprzez uruchomienie go na rzeczywistym procesorze.