Architektura Komputerów 2 – Laboratorium nr 5 – Łączenie kodu C i Asemblera

1. Dostęp do funkcji języka C z poziomu Asemblera

Aby wywołać funkcję napisaną w C z kodu Asemblerowego należy umieścić jej argumenty całkowite (liczby lub wskaźniki na adresy w pamięci) kolejno w rejestrach RDI, RSI, RDX, RCX, R8, R9, argumenty zmiennoprzecinkowe w rejestrach XMM0-XMM7 i wywołać tą funkcję korzystając z rozkazu call. Jeśli przekazujemy argumenty zmiennoprzecinkowe, wtedy do rejestru RAX musimy również wpisać ich ilość.

Przykład wywołania funkcji:

Kod należy także odpowiednio skompilować i zlinkować. Możemy wykonać tą operację jednocześnie korzystając z polecenia:

gcc kod_asm.s kod_c.c -o plik_wykonywalny -g

W kodzie Asemblerowym możemy korzystać także z innych funkcji C np. z biblioteki stdio.h.

W ramach zadania z zajęć należało wczytać od użytkownika dwie liczby – całkowitą i zmiennoprzecinkową, przekazać je do funkcji napisanej w C zwracającej wynik działania a^2+b^3, gdzie a i b to kolejne liczby – całkowita i zmiennoprzecinkowa, a następnie korzystając z funkcji printf wyświetlić ten wynik.

Kod źródłowy w C:

Kod źródłowy w Asemblerze:

2. Wstawka Asemblerowa w kodzie C

Wstawki w kodzie C wykonuje się korzystając ze słowa kluczowego asm(). W kolejnych liniach, w cudzysłowach, wpisuje rozkazy Asemblerowe. Każdą z linii zawierających rozkaz musi zostać ujęta w cudzysłowy oraz kończyć się znakiem nowej linii – \n, przed zamknięciem cudzysłowu. W następnych liniach, zaczynając od dwukropka podajemy kolejno: zmienne do których skopiowana zostanie wartość z rejestrów po zakończeniu wstawki, zmienne których wartości trafią do rejestrów przed wykonaniem rozkazów oraz rejestry których będziemy używać.

Wartości wejściowe i wyjściowe umieszczone będą w rejestrach wybranych przez kompilator. Aby uzyskać do nich dostęp należy skorzystać z aliasów, wpisując znak % oraz numer parametru – np. %5. Aby uzyskać dostęp do rejestrów korzystając z ich nazw należy użyć podwójnego znaku % oraz nazwy rejestru – np. %%RAX.

Dostęp do stałych zadeklarowanych wcześniej w kodzie jest możliwy wprost po podaniu ich nazwy.

Poniżej kod z zajęć i zarazem przykład wykorzystania kodu Asemblerowego wewnątrz kodu C. Program ma za zadanie zmienić wielkość liter (na małe) we wcześniej zadeklarowanej zmiennej typu string.

3. Dostęp do funkcji Asemblerowych z kodu w języku C

Aby móc używać funkcji napisanych w innym języku i dołączonych dopiero na etapie kompilacji, musimy zapowiedzieć ich ich dołączenie, podać typ zawracany oraz typy przyjmowanych parametrów. Służy do tego słowo kluczowe extern za którym umieszcza się typowy prototyp funkcji:

W języku Asembler funkcję również należy zadeklarować na początku kodu (w sekcji text) korzystając z poniższej składni:

Następnie należy umieścić etykiety o nazwach identycznych jak nazwy funkcji i kończących się rozkazem ret. Parametry wywołania z C zostaną umieszczone w rejestrach opisanych w punkcie pierwszym. Wartość zwracaną należy umieścić w rejestrze RAX w przypadku wartości całkowitych lub XMM0 w przypadku wartości zmiennoprzecinkowych.

Kod źródłowy w C:

Kod źródłowy w Asemblerze:

Specjalne podziękowania dla Mateusza Gniewkowskiego za pomoc w przygotowaniu tego wpisu :-)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *