Asembler x86/Łączenie z językami wysokiego poziomu/Moduły w języku C
Wygląd
// zawartość pliku str.c
#include <stdio.h>
extern unsigned int mystrlen (const char*);
int main()
{
char c[32];
puts("Wprowadź dowolny ciąg znaków..");
scanf("%31s", c);
printf("Wprowadzony ciąg zawiera %d znaków.\n",mystrlen(c));
return 0;
}
Poniższy kod w języku Asembler kompilujemy do pliku obiektowego libfunmystrlen.o korzystając z polecenia:
as libfunmystrlen.s -o libfunmystrlen.o
/* zawartość pliku libfunmystrlen.s
zadeklarowaliśmy funkcję w C linkowaną statycznie
extern unsigned int mystrlen(const char*); , zatem:
8(%EBP) zawiera wskaźnik pierwszego znaku
4(%EBP) adres powrotu z funkcji
%EBP pierwotną wartość rejestru EBP
*/
.text
.global mystrlen
mystrlen:
pushl %ebp # tworzymy ramkę stosu
movl %esp,%ebp # EBP = ESP (base pointer = stack pointer)
movb 8(%ebp), %esi # ESI wskazuje teraz na pierwszy znak danego ciągu
xorl %ecx,%ecx # zerowanie rejestru ECX zliczającego znaki w ciąg
cld # ustalenie kierunku odczytu znaków dla polecenia LODSB
petla:
xorl %eax,%eax # zerujemy EAX zanim pobierzemy kolejny znak
lodsb # do rejestru AL pobierany jest znak [esi]
# indeks ESI zwiększany jest o 1
incl %ecx # po każdym przebiegu ECX = ECX+1
orl %eax,%eax # jeżeli EAX różne od zera
jnz petla # skok do "petla"
decl %ecx # odjęcie końcowego znaku $ od wartości zliczonej w ECX
movl %ecx,%eax # wynik funkcji umieszczany jest w EAX
movl %ebp,%esp # niszczymy ramkę stosu, ESP=EBP
popl %ebp # przywracamy pierwotną wartość EBP
ret # koniec funkcji
Następnie pozostaje jedynie zlinkować statycznie powstałe pliki obiektowe w jeden plik wykonywalny str korzystając z polecenia:
gcc libfunmystrlen.o str.c -o str