Asembler x86/Łączenie z językami wysokiego poziomu/Moduły w języku C

// 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