2012-05-20 10 views
8

Widziałem notację fastcall dołączoną przed wieloma funkcjami. Dlaczego jest używany?Jakie jest słowo kluczowe fastcall użyte w wizualizacji c?

+1

To nie jest sprawa C, to sprawa MSVC. –

+1

Nie można zakodować MSVC bez C xP – Mehrdad

+7

Kto wybrał opcję zamknięcia tego: Jak to nie jest prawdziwe pytanie? Tak, jest krótki i na temat, ale z pewnością jest to bardzo jasne pytanie z bardzo jasną odpowiedzią. –

Odpowiedz

21

Ta notacja przed funkcją nazywa się "konwencją wywołującą". Określa, w jaki sposób (na niskim poziomie) kompilator przekaże parametry wejściowe do funkcji i pobierze jej wyniki po jej wykonaniu.

Istnieje wiele różnych konwencji wywoływania, z których najpopularniejszym jest stdcall i cdecl.

Można by pomyśleć, że jest tylko jeden sposób robienia tego, ale w rzeczywistości istnieją dziesiątki sposobów, w jakie można wywoływać funkcję i przekazywać zmienne. Możesz umieścić parametry wejściowe na stosie (push, push, push to call, pop, pop, pop, aby odczytać parametry wejściowe). A może wolisz trzymać je w rejestrach (to jest fastcall - próbuje dopasować niektóre z parametrów wejściowych w rejestrach dla prędkości).

Ale co z zamówieniem? Czy naciskasz je od lewej do prawej lub od prawej do lewej? A co z wynikiem - zawsze jest tylko jeden (zakładając, że nie ma parametrów odniesienia), więc umieszczasz wynik na stosie, w rejestrze, pod określonym adresem pamięci?

Załóżmy również, że używasz stosu do komunikacji - kto ma za zadanie wyczyścić stos po wywołaniu funkcji - rozmówcy czy kamerze?

Co zrobić z tworzeniem kopii zapasowych, a następnie przywracaniem zawartości (niektórych) rejestrów procesora - czy osoba dzwoniąca powinna to zrobić, czy też osoba przekazująca gwarantuje, że zwróci wszystko tak, jak było?

Najbardziej popularną konwencją wywoływania (zdecydowanie) jest cdecl, która jest standardową konwencją wywołania zarówno w C, jak iw C++. Interfejs API WIN32 wykorzystuje numer stdcall, co oznacza, że ​​każdy kod wywołujący interfejs API WIN32 musi korzystać z funkcji stdcall dla tych wywołań funkcji (co czyni go kolejnym popularnym wyborem).

fastcall jest trochę dziwne - ludzie realizujący wiele funkcji z jednym parametrem wejściowym/wyjściowym, pchanie i wyskakiwanie ze stosu opartego na pamięci jest dość spore i sprawia, że ​​wywołania funkcji są trochę ciężkie, więc różne kompilatory wprowadziły (różne) konwencje wywoływania, które umieściłyby jeden lub więcej parametrów w rejestrach przed umieszczeniem reszty w stosie dla lepszej wydajności. Problem polega na tym, że nie wszystkie kompilatory używają tych samych reguł co do tego, co i gdzie i co robi z fastcall, i dlatego musisz być ostrożny, kiedy go używasz, ponieważ nigdy nie wiesz, kto co robi. Na koniec zapoznaj się z informacjami na temat wydajności Is fastcall really faster? na temat wydajności fastcall.

Skomplikowane rzeczy.

Coś ważne, aby pamiętać: nie należy dodawać ani zmieniać konwencje wzywające jeśli nie wiem dokładnie co robisz, bo jeśli zarówno rozmówcy i wywoływany nie zgadzają się na konwencji wywołującego, najprawdopodobniej skończy się to zepsuciem stosu i segfaultem.Zwykle dzieje się tak, gdy masz wywoływaną funkcję w bibliotece DLL/współdzielonej i napisany jest program, który zależy od biblioteki DLL/SO/dylib będącej pewną konwencją wywołania (na przykład cdecl), a następnie biblioteka jest rekompilowana z innym wywołaniem konwencja (na przykład fastcall). Teraz stary program nie może już komunikować się z nową biblioteką.

2

Wikipedia states that

Konwencje uprawnione fastcall nie zostały znormalizowane i zostały wdrożone w różny sposób, w zależności od producenta kompilatora. Zwykle konwencje wywoływania fastcall przekazują jeden lub więcej argumentów w rejestrach, co zmniejsza liczbę dostępów do pamięci wymaganych do wywołania.