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 x86 tag dla up-to-date linki ABI i wiele innych dobrych rzeczy o x86 asm.)
Oto urywek z tej kategorii:
- 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.
- Wywołanie systemowe odbywa się poprzez instrukcję. To podkręca% rcx i% r11, a także% rax, ale inne rejestry są zachowywane.
- Numer syscall musi zostać przekazany w rejestrze% rax.
- Wywołania systemowe są ograniczone do sześciu argumentów, nie przekazuje się argumentu bezpośrednio na stosie.
- Po powrocie z systemu, zarejestruj% rax zawiera wynik wywołania systemowego . Wartość w zakresie od -4095 do -1 oznacza błąd, to jest
-errno
.
- 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:
- Jeśli klasa jest MEMORY, przekazać argument na stosie.
- 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.
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
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. –
Oboje macie rację. Szukam FreeBSD i Linuxa. – claws