Wybór czterech rejestrów argumentów na x64 - wspólny dla UN * X / Win64
Jedną z rzeczy, o których należy pamiętać w przypadku x86, jest to, że nazwa rejestru do kodowania „numeru rejestru” nie jest oczywista; pod względem kodowania instrukcji ( bajt MOD R / M , patrz http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), numery rejestrów 0 ... 7 są - w tej kolejności - ?AX, ?CX, ?DX, ?BX, ?SP, ?BP, ?SI, ?DI.
Dlatego wybranie A / C / D (regs 0..2) jako wartości zwracanej i pierwszych dwóch argumentów (co jest "klasyczną" __fastcallkonwencją 32-bitową ) jest logicznym wyborem. Jeśli chodzi o wersję 64-bitową, zamawiane są „wyższe” regy, a Microsoft i UN * X / Linux wybrali R8/ R9jako pierwsi.
Mając to na uwadze, wybór przez Microsoft RAX(wartości zwracanej) oraz RCX, RDX, R8, R9(arg [0..3]) są zrozumiałe wybór jeśli zdecydujesz cztery rejestry argumentów.
Nie wiem, dlaczego AMD64 UN * X ABI wybrało RDXwcześniej RCX.
Wybór sześciu rejestrów argumentowych na x64 - specyficzny dla UN * X
UN * X, na architekturach RISC, tradycyjnie przekazywał argumenty w rejestrach - konkretnie dla pierwszych sześciu argumentów (tak jest przynajmniej w przypadku PPC, SPARC, MIPS). Co może być jednym z głównych powodów, dla których projektanci AMD64 (UN * X) ABI zdecydowali się na użycie sześciu rejestrów również w tej architekturze.
Więc jeśli chcesz sześć rejestrów przekazać argumenty, i to jest logiczne, aby wybrać RCX, RDX, R8a R9dla czterech z nich, co dwa pozostałe należy wybrać?
„Wyższe” rejestry wymagają dodatkowego bajtu przedrostka instrukcji, aby je wybrać i dlatego mają większy rozmiar instrukcji, więc nie chciałbyś wybierać żadnej z nich, jeśli masz opcje. Z klasycznych rejestrów, ze względu na ukryte znaczenie RBPi RSPnie są one dostępne, a RBXtradycyjnie ma specjalne zastosowanie w UN * X (globalna tabela offsetów), z którymi najwyraźniej projektanci AMD64 ABI nie chcieli niepotrzebnie stać się niekompatybilnymi.
Ergo, jedynym wyborem były RSI/ RDI.
Więc jeśli musisz wziąć RSI/ RDIjako rejestry argumentów, jakie powinny to być argumenty?
Wykonanie ich arg[0]i arg[1]ma pewne zalety. Zobacz komentarz cHao.
?SIi ?DIsą operandami źródłowymi / docelowymi instrukcji łańcuchowych, a jak wspomniało cHao, ich użycie jako rejestrów argumentów oznacza, że w przypadku konwencji wywoływania AMD64 UN * X najprostsza możliwa strcpy()funkcja składa się na przykład tylko z dwóch instrukcji procesora, repz movsb; retponieważ źródło / cel adresy zostały wprowadzone przez dzwoniącego do odpowiednich rejestrów. Występuje, szczególnie w niskopoziomowym i generowanym przez kompilator kodzie „klejowym” (pomyśl, na przykład, niektóre alokatory sterty w C ++ wypełniające zerami obiekty w konstrukcji lub strony jądra wypełniające stertysbrk()lub błędy stronicowania przy kopiowaniu przy zapisie) ogromną ilość kopiowania / wypełniania bloków, dlatego będzie to przydatne w przypadku kodu tak często używanego do zapisywania dwóch lub trzech instrukcji procesora, które w przeciwnym razie ładowałyby takie argumenty adresu źródłowego / docelowego do „prawidłowe” rejestry.
Więc w pewnym sensie, UN * X i Win64 różnią się tylko tym, że UN * X „wstawia” dwa dodatkowe argumenty, w celowo wybranych RSI/ RDIrejestrów, z naturalnym wyborem cztery argumenty RCX, RDX, R8i R9.
Ponadto ...
Istnieje więcej różnic między interfejsami ABI UN * X i Windows x64 niż tylko mapowanie argumentów do określonych rejestrów. Aby zapoznać się z przeglądem systemu Win64, sprawdź:
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64 i AMD64 UN * X również uderzająco różnią się sposobem wykorzystania przestrzeni stosowej; na przykład w Win64 wywołujący musi przydzielić przestrzeń stosu dla argumentów funkcji, mimo że argumenty 0 ... 3 są przekazywane w rejestrach. Z drugiej strony w UN * X funkcja liścia (tj. Taka, która nie wywołuje innych funkcji) nie jest nawet wymagana do przydzielania miejsca na stosie, jeśli nie potrzebuje więcej niż 128 bajtów (tak, posiadasz i możesz używać pewna ilość stosu bez przydzielania go ... no chyba, że jesteś kodem jądra, źródłem sprytnych błędów). Wszystko to są określone wybory optymalizacyjne, większość ich uzasadnienia jest wyjaśniona w pełnych odniesieniach ABI, na które wskazuje wikipedia pierwotnego postu.