Wywołanie procedury napisanej w języku C z poziomu procedury napisanej w assemblerze

Wywołanie procedury napisanej w języku C z poziomu procedury napisanej w assemblerze najczęściej występuje w częściach kodu implementowanego systemu, dotyczących obsługi przerwań, bądź też zmiany kontroli. Główną ideą podczas takich wywołań jest wykonanie odpowiednich operacji na stosie, w sposób analogiczny, jak to robi kompilator języka C.

EXTERN sys_calls ... push ebp push eax ;number of system call subroutine call sys_calls add esp, 8 ...

Ten fragment kodu pokazuje sposób wywołania procedury sys_calls(), której definicja wygląda następująco:

void sys_calls(int call_number, PROCESS_CONTEXT *old_process);

W tym wypadku w rejestrze EBP znajduje się wskaźnik na strukturę PROCESS_CONTEXT, natomiast w rejestrze EAX znajduje się numer procedury systemowej, która ma zostać wywołana. Oba te rejestry zostają umieszczone na stosie w odwrotnej kolejności, niż są zdefiniowane w wywołaniu procedury (tzn. jako ostatni zostaje wypchnięty na stos argument, który w definicji występuje jako pierwszy).

Aby zachować ciągłość stosu, po powrocie z procedury należy usunąć umieszczone wcześniej argumenty (procedura w C sama tego nie robi). W tym celu należy dodać do wartości rejestru ESP wartość która jest wynikiem sumy wielkości argumentów wywoływanej procedury. W tym wypadku na stosie zostały umieszczone dwa argumenty po 4 bajty, więc do wskaźnika stosu należy dodać wartość osiem.

Przed wywoływaniem procedury napisanej w języku C z poziomu procedury napisanej w języku assemblera należy również pamiętać o tym, aby poinformować kompilator w jaki sposób ma być potraktowany symbol sys_calls. W tym wypadku jest to symbol zewnętrzny zadeklarowany w innym pliku obiektowym - czyli kod na początku powinien zawierać deklaracje EXTERN sys_calls.