2012-07-01 6 views
6

Przeglądałem źródła różnych implementacji setjmp i longjmp i zauważyłem, że nie wszystkie rejestry CPU są zapisywane w strukturze jmp_buf. Po zapoznaniu się z ABI AMD64, zauważyłem, że zapisywane są tylko rejestry zapisane w trybie "the callee".Dlaczego setjmp (3) nie zapisuje wszystkich rejestrów na AMD64?

Nie rozumiem, w jaki sposób stan funkcji można w pełni wznowić, gdy tylko niektóre rejestry zostały zapisane. Z pewnością niezapisane rejestry musiały być wielokrotnie przeplatane, dopóki nie zadzwonię później pod numer longjmp?

Wszystko działa idealnie, więc z pewnością jest coś, czego nie rozumiem. Miałem nadzieję, że ktoś może rzucić trochę światła na to.

Dzięki!

+0

Istnieją implementacje setjmp, które zapisują jedynie wskaźnik instrukcji/wskaźnik ramki (patrz "libunwind"). Te mają bardzo szybki setjmp, ale stosunkowo powolne czasy longjmp i są oparte na tabelach ramek, które opisują, jak odzyskać inne rejestry z zapisanych lokalizacji wywołujących i takich. –

+0

Gdzie mogę znaleźć źródło, na które patrzyłeś? – nullpotent

+0

@AljoshaBre Są to najłatwiejsze do przeczytania do tej pory: [setjmp] (http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;ablbl;f=src/setjmp /x86_64/setjmp.s;h=98f58b8d6551e391f426fc53c81678a03ac89074;hb=HEAD) i [longjmp] (http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/ setjmp/x86_64/longjmp.s; h = e175a4b9606bba41eccc8972c22244e533718f0a; hb = HEAD). – haste

Odpowiedz

4

Funkcja setjmp jest funkcją podobną do każdej innej, dlatego można założyć, że odrywa ona wszystkie rejestry zapisane przez wywołującego. W związku z tym nie ma potrzeby zapisywania/przywracania tych rejestrów.

+0

Czy kompilator nie może używać żadnego z dostępnych rejestrów, tak jak mu się podoba w mojej funkcji? mi. nawet rejestry, które nie są zapisywane przez 'setjmp'? – haste

+0

Niezupełnie - nie może używać rejestrów zapisanych przez wywoływanie w wywołaniach funkcji, ponieważ mogą one/zostaną zmienione. Na przykład, rozważ "eax" (na x86): wywoływacz zapisze wartość zwracaną do tego rejestru, więc osoba wywołująca nie będzie mogła przechowywać niczego ważnego w wywołaniu funkcji. – duskwuff

+1

@Haste ja też na to spadłem. aby opisać to nieco bardziej szczegółowo: ponieważ są one zapisywane przez wywołującego, a setjmp jest traktowany jako normalna funkcja, wywołujący setjmp już zapisuje te rejestry, jeśli jest to potrzebne, więc gdy setjmp powraca do wywołującego po raz drugi (przez longjmp) , dzwoniący będzie miał wcześniej zapisane rejestry zapisane przez wywołującego i będzie mógł je przywrócić. –

Powiązane problemy