Próbuję zrozumieć jakiś montaż.
Montaż jak następuje, interesuje mnie testl
linia:
000319df 8b4508 movl 0x08(%ebp), %eax
000319e2 8b4004 movl 0x04(%eax), %eax
000319e5 85c0 testl %eax, %eax
000319e7 7407 je 0x000319f0
Próbuję zrozumieć ten punkt testl
pomiędzy %eax
i %eax
? Myślę, że specyfika tego, co ten kod nie jest ważna, po prostu próbuję zrozumieć test samym sobą - czy wartość nie zawsze byłaby prawdziwa?
assembly
x86
instructions
maxpenguin
źródło
źródło
test
acmp
. Tak, rozumiem, że to twoja wiara oparta na komentarzach do Cody'ego. Jednak umieszczenie tego w moim poście to inna sprawa; nie jest to stwierdzenie, na które jestem gotów stać, po prostu dlatego , że nie wiem, czy jest identyczne we wszystkich przypadkach.je
,jz
,cmp
, itest
, a nie JE, JZ, CMP lub TEST. Jestem taki wybredny.test a,a
icmp $0,a
ustawić flagi identycznie; dzięki za wskazanie, że to nietrywialne twierdzenie. re: TEST vstest
.: ostatnio zacząłem używać wielkich liter, takich jak podręczniki Intela. Ale kiedy mówię o mnemonikach AT&T i mnemonikach Intela, używamtestb
stylu dla AT&T. IDK, jeśli to pomaga w czytelności.Znaczenie
test
to ORAZ argumenty razem i sprawdzić wynik na zero. Więc ten kod sprawdza, czy EAX ma wartość zero, czy nie.je
przeskoczy jeśli zero.Przy okazji, generuje to mniejszą instrukcję, niż
cmp eax, 0
jest to powód, dla którego kompilatory zwykle robią to w ten sposób.źródło
Instrukcja testowa wykonuje operację logiczną AND pomiędzy operandami, ale nie zapisuje wyniku z powrotem do rejestru. Aktualizowane są tylko flagi.
W twoim przykładzie test eax, eax ustawi flagę zero, jeśli eax jest równe zero, flagę znaku, jeśli ustawiono najwyższy bit, a także kilka innych flag.
Instrukcja Jump if Equal (je) przeskakuje, jeśli ustawiona jest flaga zero.
Możesz przetłumaczyć kod na bardziej czytelny kod w następujący sposób:
Ma tę samą funkcjonalność, ale wymaga o kilka bajtów więcej miejsca na kod. To jest powód, dla którego kompilator wyemitował test zamiast porównania.
źródło
test eax, eax
icmp eax, 0
obaj ustawiają wszystkie flagi i ustawiają je na identyczne wartości. Obie instrukcje ustawiają wszystkie flagi „zgodnie z wynikiem”. Odejmowanie0
nigdy nie może spowodować przeniesienia ani przepełnienia. Twój argument jest poprawny dla każdego natychmiastowego innego niż 0, ale nie dla 0.test
jest jakand
, z wyjątkiem tego, że pisze tylko FLAGI, pozostawiając oba wejścia niezmienione. Dzięki dwóm różnym wejściom przydaje się do testowania, czy niektóre bity mają wartość zero lub czy przynajmniej jeden jest ustawiony. (np.test al, 3
ustawia ZF, jeśli EAX jest wielokrotnością 4 (a zatem ma wyzerowane oba niskie 2 bity).test eax,eax
ustawia wszystkie flagi dokładnie w taki sam sposób, wcmp eax, 0
jaki :a = a&a = a-0
).(PF jak zwykle jest ustawiany tylko zgodnie z dolnymi 8 bitami )
Z wyjątkiem przestarzałego AF (pomocniczy znacznik przenoszenia, używany w instrukcjach ASCII / BCD). TEST pozostawia go niezdefiniowanym , ale CMP ustawia go „zgodnie z wynikiem” . Ponieważ odejmowanie zera nie może dać przeniesienia z 4 do 5 bitu, CMP powinien zawsze wyczyścić AF.
TEST jest mniejszy (nie jest natychmiastowy) i czasami szybszy (może łączyć się w makro w celu porównania i rozgałęzienia na większej liczbie procesorów w większej liczbie przypadków niż CMP). To jest
test
preferowanym idiomem do porównywania rejestru z zerem . Jest to optymalizacja wizjeracmp reg,0
, której można używać niezależnie od znaczenia semantycznego.Jedynym częstym powodem używania CMP z natychmiastowym 0 jest to, że chcesz porównać z operandem pamięci. Na przykład,
cmpb $0, (%esi)
aby sprawdzić kończący bajt zerowy na końcu niejawnej długości ciągu w stylu C.AVX512F dodaje
kortestw k1, k2
i AVX512DQ / BW (Skylake-X, ale nie KNL)ktestb/w/d/q k1, k2
, które działają na rejestrach maski AVX512 (k0..k7), ale nadal ustawiają regularne FLAGI, tak jaktest
robi to liczba całkowitaOR
lubAND
instrukcje. (Coś w rodzaju SSE4ptest
lub SSEucomiss
: dane wejściowe w domenie SIMD i dają w wyniku FLAGI całkowite).kortestw k1,k1
jest idiomatycznym sposobem rozgałęzienia / cmovcc / setcc na podstawie wyniku porównania AVX512, zastępując SSE / AVX2(v)pmovmskb/ps/pd
+test
lubcmp
.Użycie
jz
vs.je
może być mylące.jz
ije
są dosłownie tą samą instrukcją , tj. tym samym kodem operacyjnym w kodzie maszynowym. Robią to samo, ale mają inne znaczenie semantyczne dla ludzi . Dezasemblery (i zazwyczaj dane wyjściowe asm z kompilatorów) będą zawsze używać tylko jednego, więc rozróżnienie semantyczne zostaje utracone.cmp
isub
ustawia ZF, gdy ich dwa wejścia są równe (tj. wynik odejmowania wynosi 0).je
(skok, jeśli równe) jest semantycznie istotnym synonimem.test %eax,%eax
/and %eax,%eax
ponownie ustawia ZF, gdy wynik jest równy zero, ale nie ma testu „równości”. ZF po teście nie mówi ci, czy dwa operandy były równe. Zatemjz
(skok jeśli zero) jest semantycznie istotnym synonimem.źródło
test
bitowychand
, może nie być oczywiste dla osób dopiero uczących się asemblera (i leniwych / nieświadomych sprawdzania instrukcji obsługi co 60 sekund;) :)).kortest*
iktest*
kiedy byłem na tym.Ten fragment kodu pochodzi z podprogramu, któremu nadano wskaźnik do czegoś, prawdopodobnie jakiejś struktury lub obiektu. Druga linia wyłuskuje ten wskaźnik, pobierając wartość z tego elementu - prawdopodobnie sam wskaźnik lub po prostu int, przechowywany jako drugi element członkowski (przesunięcie +4). Trzeci i czwarty wiersz testują tę wartość na zero (NULL, jeśli jest wskaźnikiem) i pomijają następujące kilka operacji (nie pokazano), jeśli wynosi zero.
Test na zero jest czasami kodowany jako porównanie z bezpośrednią wartością dosłownego zera, ale kompilator (lub człowiek?), Który to napisał, mógł pomyśleć, że operacja testowa będzie działać szybciej - biorąc pod uwagę wszystkie nowoczesne rzeczy związane z procesorem, takie jak potokowanie i rejestrowanie zmiana nazwy. To z tego samego worka sztuczek, który zawiera pomysł wyczyszczenia rejestru za pomocą XOR EAX, EAX (które widziałem na czyjejś tablicy rejestracyjnej w Kolorado!), A nie oczywistego, ale może wolniejszego MOV EAX, # 0 (używam starszej notacji ).
W asm, podobnie jak perl, TMTOWTDI.
źródło
Jeśli eax ma wartość zero, wykona skok warunkowy, w przeciwnym razie będzie kontynuował wykonywanie na 319e9
źródło
W niektórych programach można ich użyć do sprawdzenia przepełnienia bufora. Na samej górze przydzielonego miejsca jest umieszczane 0. Po wprowadzeniu danych do stosu szuka 0 na samym początku przydzielonego miejsca, aby upewnić się, że przydzielone miejsce nie jest przepełnione.
Został użyty w ćwiczeniu stack0 w ćwiczeniach exploitów, aby sprawdzić, czy jest przepełniony, a jeśli go nie było i było tam zero, wyświetlał „Spróbuj ponownie”
źródło
cmp DWORD PTR [esp+0x5c], 0
/jz 0x8048427 <main+51>
byłby bardziej wydajny niż oddzielne obciążenie MOV, a następnie TEST. Nie jest to typowy przypadek użycia do sprawdzania zera.moglibyśmy zobaczyć jg,jle Jeśli
testl %edx,%edx. jle .L3
moglibyśmy łatwo znaleźć jle jest odpowiednie(SF^OF)|ZF
, jeśli% edx jest równe zero, ZF = 1, ale jeśli% edx nie jest zerem i jest równe -1, po testl, OF = 0 i SF = 1, więc flaga = prawda, ten skok narzędzia. Przepraszam, mój angielski jest słabyźródło