ABI języka C¶
Bardzo dużo funkcji pomocniczych udostępnia nam standard POSIX oraz biblioteka standardowa C, jednak aby móc z nich korzystać z poziomu Assemblera trzeba znać interfejs binarny (ABI) języka C - sposób przekazywania argumentów, wywoływania funkcji, itp.
32-bitowe (cdecl)¶
Funkcja fun(a, b, c)
zwraca typ int.
- Aby poprawnie ją wywołać, należy po kolei:
- odłożyć argumenty od końca, w tym wypadku najpierw
c
, potemb
, potema
- zrobić
call fun
- usunąć argumenty ze stosu -
add esp, 12
(3 argumenty po 4 bajty; stos rośnie w dół, dlatego dodajemy) - wykorzystać wartość znajdującą się w eax - tam zwróciła swój wynik funkcja
- odłożyć argumenty od końca, w tym wypadku najpierw
Cały kod dla wywołania esi = fun(1,4,9)
:
push 9
push 4
push 1
call fun
add esp, 12
mov esi, eax
Funkcje mogą do woli zmieniać te rejestry:
eax
ecx
edx
Natomiast pozostałe rejestry pozostaną bez zmian po powrocie z funkcji, więc przed wywołaniem nie trzeba ich zapisywać.
64-bitowe (SysV AMD64)¶
Konwencja System V AMD64 ABI znacznie różni się od cdecl, głównie za sprawą znacznie większej liczby rejestów w nowszej architekturze.
Pierwsze sześć argumentów całkowitych/wskaźników jest przekazywanych w rejestrach:
rdi
rsi
rdx
rcx
(r10
w wywołaniach systemowych linuxa)r8
r9
Pozostałe argumenty umieszczane są na stosie od prawej do lewej, tak jak w cdecl. Zwracana wartość jest natomiast w rejestrach rax, a także rdx jeżeli potrzebne jest 128 bitów. Dodatkowo stos musi być wyrównany do granicy 16 bajtów (kwestia wydajności), a pierwsze 128 bajtów nieużywanej części stosu może być dowolnie używane przez funkcję jako tymczasowy bufor pamięci.
Funkcje nie mogą zmienić wartości rejestrów rbp, rbx, r12-r15, a na reszcie mogą wykonywać dowolne operacje.