Asembler x86/Łączenie z językami wysokiego poziomu/Funkcje zewnętrzne

Poniższy przykład pokazuje, jak bezpośrednio w kodzie asemblera wykorzystać funkcję printf() znaną z języka C.

global main
extern printf
 
section .data
 
beer    db      "%d bottles of beer on the wall, %d bottles of beer."
        db      0x0a
        db      "Take one down and pass it around, %d bottles of beer."
        db      0x0a
        db      0
main:
        mov ecx, 5     ; deklarowana liczba przebiegów pętli
_loop:
        dec  ecx       ; ECX = ECX-1
        push ecx       ; umieszcza aktualny indeks pętli na stosie

        push ecx       ; argumenty funkcji printf() umieszczamy na stosie
        inc  ecx       ; w odwrotnej kolejności, tj. od prawej do lewej strony
        push ecx
        push ecx
        push beer
        call printf    ; wywołanie funkcji printf(beer,ecx,ecx,ecx-1)
        add  esp,16    ; zdejmujemy jej argumenty ze stosu

        pop  ecx       ; pobieramy ze stosu aktualny indeks pętli
        or   ecx, ecx  ; ustala wartość flagi ZF=0, jeśli ECX=0
        jne  _loop     ; warunkowy skok do początku pętli, gdy flaga ZF=0

        xor  eax,eax   ; EAX = 0
        ret            ; return EAX

W celu kompilacji i linkowania programu należy wykonać polecenia:

nasm -f elf -o beer.o beer.asm
gcc -s -o beer beer.o

Po czym możemy uruchomić program:

user@myhost:~$ ./beer
5 bottles of beer on the wall, 5 bottles of beer.
Take one down and pass it around, 4 bottles of beer.
4 bottles of beer on the wall, 4 bottles of beer.
Take one down and pass it around, 3 bottles of beer.
3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer.
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottles of beer.
1 bottles of beer on the wall, 1 bottles of beer.
Take one down and pass it around, 0 bottles of beer.
user@myhost:~$