2010-03-29 3 views
96

poniższych linków wyjaśnić x86-32 konwencje wywołań systemowych zarówno dla smaku BSD Unix (Linux) &:Jakie są konwencje wzywającą do systemu UNIX i Linux wzywa i386 i x86-64

Ale jakie są konwencje wywołania systemowego x86-64 zarówno na UNIX & Linux?

+0

Nie ma "standard" dla Unix nazywając konwencje. Dla Linuxa pewnie, ale jestem pewien, że Solaris, OpenBSD, Linux i Minix prawdopodobnie mają różne przynajmniej nieznacznie różne konwencje wywoływania i wszystkie są uniksowe. – Earlz

+1

To nie do końca prawda - istnieje zestaw ABI UNIX dostępnych dla większości typów maszyn, który pozwala kompilatorom C osiągnąć interoperacyjność. Kompilatory C++ mają większy problem. –

+0

Oboje macie rację. Szukam FreeBSD i Linuxa. – claws

Odpowiedz

163

Sprawdziłem je używając GNU Asembler (gas) w systemie Linux.

Kernel Interfejs

x86-32 Linux system połączeń konwencja:

W parametrach x86-32 dla połączenia systemu Linux są przekazywane za pomocą rejestrów. %eax dla syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp są używane do przekazywania 6 parametrów do wywołań systemowych.

Wartość zwracana to %eax. Wszystkie inne rejestry (w tym EFLAGS) są przechowywane na całym numerze int $0x80.

Wziąłem następujący fragment z Linux Assembly Tutorial, ale wątpię w to. Jeśli ktokolwiek może pokazać przykład, byłoby wspaniale.

Jeśli istnieje więcej niż sześć argumentów, %ebx musi zawierać pamięć lokalizację, w której zapisany jest lista argumentów - ale nie martw się o tym ponieważ jest mało prawdopodobne, że będziesz używać wywołania systemowego z więcej niż sześcioma argumentami .

Dla przykładu i trochę więcej czytania, patrz http://www.int80h.org/bsdasm/#alternate-calling-convention

Jest szybszy sposób, aby układ 32-bitowy połączeń: za pomocą sysenter. Jądro odwzorowuje stronę pamięci do każdego procesu (vdso), ze stroną użytkownika o nazwie sysenter, która musi współpracować z jądrem, aby móc znaleźć adres zwrotny. Arg, aby zarejestrować mapowanie jest takie samo jak dla int $0x80, ale zamiast tej instrukcji, kod powinien wywoływać funkcję w vdso. (TODO: zaktualizuj to linkiem i/lub określonymi informacjami).

x86-32 [Free | Otwórz | netto | DragonFly] BSD UNIX System połączeń konwencja:

parametry są przekazywane na stosie. Przeprowadź parametry (ostatni parametr wciśnięty jako pierwszy) na stos. Następnie wcisnąć dodatkowy 32-bitowych danych fikcyjnych (to nie jest faktycznie dane fikcyjne. Odnoszą się do poniższego linku, aby uzyskać więcej informacji), a następnie dać instrukcję wywołania systemowego int $0x80

http://www.int80h.org/bsdasm/#default-calling-convention


x86-64 Linux Konwencja dotycząca wywołań systemowych:

x86-64 Mac OS X is similar but different. TODO: sprawdź, co * robi BSD.

Patrz rozdział: "A.2 AMD64 Linux Konwencje jądra" z System V Application Binary Interface AMD64 Architecture Processor Supplement. Najnowsze wersje komputerów psABI systemu i386 i x86-64 można znaleźć pod adresem linked from this page in the ABI maintainer's repo. (Patrz również wiki tag dla up-to-date linki ABI i wiele innych dobrych rzeczy o x86 asm.)

Oto urywek z tej kategorii:

  1. aplikacje użytkownika szczebla użyj jako liczby całkowite, aby przekazać sekwencje% rdi,% rsi,% rdx,% rcx, % r8x, % r8 i% r9. Interfejs jądra używa% rdi,% rsi,% rdx,% r10,% r8 i% r9.
  2. Wywołanie systemowe odbywa się poprzez instrukcję. To podkręca% rcx i% r11, a także% rax, ale inne rejestry są zachowywane.
  3. Numer syscall musi zostać przekazany w rejestrze% rax.
  4. Wywołania systemowe są ograniczone do sześciu argumentów, nie przekazuje się argumentu bezpośrednio na stosie.
  5. Po powrocie z systemu, zarejestruj% rax zawiera wynik wywołania systemowego . Wartość w zakresie od -4095 do -1 oznacza błąd, to jest -errno.
  6. Tylko wartości klasy INTEGER lub klasy MEMORY są przekazywane do jądra.

Pamiętaj, to jest z systemem Linux konkretnego dodatku do ABI, a nawet dla systemu Linux nie jest pouczające normatywne. (Ale to jest w rzeczywistości dokładne.)

User Interface

x86-32 Funkcja Wywoływanie konwencja:

W parametrach x86-32 zostały przekazane na stosie. Ostatni parametr był wpychany najpierw na stos, dopóki wszystkie parametry nie zostaną wykonane, a następnie wykonano instrukcję call. Jest to używane do wywoływania funkcji biblioteki C (libc) na Linuksie z zestawu.


x86-64 Funkcja Wywoływanie konwencja:

x86-64 przechodzi args w rejestrach, który jest bardziej wydajny niż args stos konwencji i386 System V w. Zapobiega opóźnieniom i dodatkowym instrukcjom przechowywania argów w pamięci (pamięci podręcznej), a następnie ładowaniu ich z powrotem do adresata. Działa to dobrze, ponieważ dostępnych jest więcej rejestrów i jest lepsze dla nowoczesnych procesorów o wysokiej wydajności, w których liczy się opóźnienie i wykonanie poza kolejnością. (ABI i386 ABI jest bardzo stary).

W tym nowy mechanizm: Najpierw parametry są podzielone na klasy. Klasa każdego parametru określa sposób, w jaki jest przekazywana do wywoływanej funkcji.

uzyskać pełne informacje patrz: „3.2 wywołanie funkcji sekwencji” System V Application Binary Interface AMD64 Architecture Processor Supplement który brzmi, w części:

Gdy argumenty są klasyfikowane, rejestry są przydzielane (w lewej do prawej kolejności) dla przekazując w następujący sposób:

  1. Jeśli klasa jest MEMORY, przekazać argument na stosie.
  2. Jeśli klasa jest INTEGER, następny dostępny Rejestr sekwencji% RDI,% RSI,% RDX,% RCX,% R8% R9 jest używany

Więc %rdi, %rsi, %rdx, %rcx, %r8 and %r9 są rejestry w celu używane do przekazywania parametrów integer/wskaźnik (tj. klasa INTEGER) do dowolnej funkcji libc z zestawu. % rdi jest używany dla pierwszego parametru INTEGER. % rsi dla drugiego,% rdx dla trzeciego i tak dalej. Następnie należy podać instrukcję. Stos (%rsp) musi być wyrównany do 16B po wykonaniu call.

Jeśli istnieje więcej niż 6 parametrów INTEGER, 7 parametr INTEGER i późniejsze są przekazywane na stosie. (Wywołujący wywołujący, taki sam jak x86-32.)

Pierwsze 8 argumentów zmiennoprzecinkowych są przekazywane w% xmm0-7, później na stosie. Nie ma zarejestrowanych wektorów rejestrujących. (Funkcja z mieszanką argumentów FP i liczb całkowitych może mieć więcej niż 8 argumentów rejestru całkowitego.)

Funkcje varariadic (like printf) zawsze potrzebują %al = liczby rejestrów FP.

Istnieją zasady dotyczące pakowania struktur do rejestrów (rdx:rax po powrocie) vs. w pamięci. Zobacz ABI po szczegóły i sprawdź dane wyjściowe kompilatora, aby upewnić się, że twój kod zgadza się z kompilatorami o tym, jak coś powinno zostać przekazane/zwrócone.

+0

W Linuksie 32 "wszystkie rejestry oprócz ax bx cd dx si di bp są zachowane". Nie mogę wymyślić żadnego ... –

+0

Na amd64, jeśli istnieje więcej niż 6 parametrów i są one przekazywane na stosie, kto jest odpowiedzialny za czyszczenie stosu po wywołaniu, dzwoniącym lub kelnerze? –

+1

@ Nicolás: program wywołujący czyści stos. Zaktualizowałem odpowiedź, podając więcej szczegółów na temat konwencji wywoływania funkcji. –

11

Być może szukasz ABI x86_64?

Jeśli nie jest to dokładnie to, czego szukasz, użyj „” ABI x86_64 w preferowanej wyszukiwarki, aby znaleźć alternatywne referencje.

+3

właściwie, chcę tylko konwencji System Call. esp dla UNIX (FreeBSD) – claws

+3

@claws: konwencja wywołań systemowych jest jedną z części ABI. –

+1

tak. Poszedłem do każdego jądra systemu operacyjnego i zapytałem ich o to. Kazali mi zaglądać do źródła i wymyślać. Nie rozumiem bez dokumentacji rzeczy, jak mogą zacząć rozwijać? Dlatego dodałem odpowiedź z zebranych informacji, mając nadzieję, że inni uzupełnią pozostałe szczegóły. – claws

4

Oprócz linku, który oferuje Jonathan Leffler w swojej odpowiedzi, może ci się przydać również plik Agner Fog z Calling Conventions pdf.

+0

właściwie, chcę tylko konwencji System Call. – claws

8

Konwencje wywołania określają sposób przekazywania parametrów w rejestrach podczas wywoływania lub wywoływania przez inny program. A najlepszym źródłem tych konwencji są standardy ABI zdefiniowane dla każdego z tych urządzeń. Aby ułatwić kompilację, ten sam ABI jest również używany przez przestrzeń użytkownika i program jądra. Linux/Freebsd są zgodne z tym samym ABI dla x86-64 i innym zestawem dla wersji 32-bitowej. Ale x86-64 ABI dla Windows różni się od Linuksa/FreeBSD. I ogólnie ABI nie rozróżnia połączeń systemowych od normalnych "wywołań funkcji". Czyli, jest tutaj szczególny przykład konwencji x86_64 telefonicznych i jest taka sama dla Linux przestrzeni użytkownika i jądra: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ (uwaga Sekwencja a, b, c, d, e, f parametrów)

A good rendering of calling conventions vs registers usage

Wydajność jest jeden z powodów, dla tych ABI (na przykład, poprzez przepuszczenie parametrów zamiast zapisywania rejestrów w stosy pamięci)

na ARM jest różne ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

ARM64 konwencja:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

dla systemu Linux na PowerPC:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

I osadzony jest PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

Niniejszy dokument jest dobry przegląd wszystkich różnych konwencjach:

http://www.agner.org/optimize/calling_conventions.pdf

+0

Zupełnie poza tym punktem. Plakat z pytaniem nie wymagałby 64-bitowej konwencji wywołania syscall w systemie Linux, gdyby był taki sam, jak ogólne konwersje ABI. –

+0

System V (Linux) ABI znajdują się na https://refspecs.linuxbase.org – kchoi

Powiązane problemy