/* Poczatek kodu w C - plik suma.c */ #include <stdio.h> int suma1(int, int); /* Prototypy funkcji, ktore */ int suma2(int, int); /* zostana napisane w asemblerze. */ int main() { int s; s = suma1(7, 9); /* Powyzsze wywolanie wyglada w asemblerze tak: push 9 ; odlozenie na stos drugiego argumentu push 7 ; odlozenie na stos pierwszego argumentu call suma1 ; wolanie funkcji asemblerowej add esp, 8 ; wyczyszczenie stosu z argumentow mov [ebp - 4], eax ; zapisanie wyniku zwroconego w rejestrze eax */ printf("suma1 = %d\n", s); s = suma2(7, 9); printf("suma2 = %d\n", s); return 0; } /* Koniec kodu w C */ ; Poczatek kodu w asemblerze - plik suma.asm global suma1 ; Etykiety poczatkow funkcji trzeba zadeklarowac jako global, global suma2 ; zeby byly widoczne na zewnarz modulu asemblerowego. section .text ; Funkcje suma1, niezbyt optymalnie, mozna w C napisac tak: ; int suma1(int a, int b) { ; int c; ; ; c = a + b; ; return c; ; } ; GCC z wylaczona optymalizacja przetlumaczy to mniej wiecej tak (9 instrukcji): suma1: ; Prolog funkcji push ebp ; Zapamietaj na stosie wskaznik poprzedniej ramki stosu. mov ebp, esp ; Zapisz do ebp wskaznik biezacej ramki stosu. sub esp, 4 ;* Zarezerwuj 4 bajty na stosie na zmienna c. ; Cialo funkcji mov eax, [ebp + 12] ; Przepisz do eax argument b. add eax, [ebp + 8] ; Dodaj do eax argument a; mov [ebp - 4], eax ;* Zapisz wynik w zmiennej c; mov eax, [ebp - 4] ;* Zwroc wartosc ze zmiennej c. ; Epilog funkcji leave ; To jest rownowazne wykonaniu sekwencji: ; mov esp, ebp ; Wyczysc stos ze zmiennych lokalnych. ; pop ebp ; Przywroc poprzedni wskaznik ramki stosu. ret ; ; Wlaczenie optymalizacji (opcja -O3) usunie instrukcje oznaczone gwiazdka, ; czyli usunie zmienna c, ktora oczywiscie nie jest potrzebna (pozostalo 6 instrukcji). ; Mozna jednak zaimplementowac te funkcje sprytniej tak (3 instrukcje): suma2: mov eax, [esp + 8] ; Przepisz do eax drugi argument. add eax, [esp + 4] ; Dodaj do niego pierwszy argument. ret ; W eax jest to, co trzeba zwrocic. ; Faktycznie GCC tez wie, ze tak mozna, gdy mu dodatkowo wlaczyc opcje ; -fomit-frame-pointer ale nie z kazda funkcja tak dobrze sobie poradzi. ; Koniec kodu w asemblerze # Skompilowac powyzsze mozna tak: nasm -f elf -o suma.o suma.asm gcc -o suma suma.c suma.o