global incr incr: push eax ; sauvegarde du registre push ebx ; sauvegarde du registre push ebp mov ebp, esp mov ebx, [ebp+8] ; recuperation de l'argument dans EBX mov eax, [ebx] ; on stocke l'entier dans EAX add eax, 1 ; incrementation de EAX mov [ebx], eax ; on modifie la variable pointee par EBX mov esp, ebp pop ebp pop ebx pop eax ret |
On produit un fichier objet au format ELF grace a la commande suivante :
$ nasm -f elf lib.asm -o lib.o
Le fichier suivant contient le code principal. Ce code
incremente la variable mavar avec la fonction incr
definie precedement. Cette fonction externe doit etre declaree
au debut du fichier avec la directive extern.
Il est indispensable de definir le point d'entree du programme pour
que le linkeur puisse assembler correctement les fichiers objets.
Par defaut, ce point d'entree correspond au label _start
qui doit etre declare en global (sans quoi le point d'entree ne serait
pas vu par le linkeur) :
$ cat main.asm
extern incr global _start _start: push dword [mavar] call incr mavar dw 0x01 |
On compile de la meme facon ce fichier :
$ nasm -f elf main.asm -o main.o
Une fois que les fichiers objet ont etes obtenus, on les lie entre eux
grace a la commande ld. On met l'argument
"--oformat binary" pour obtenir un binaire pur :
$ ld --oformat binary main.o lib.o
$ ndisasm -u a.out
00000000 FF350B800408 push dword [0x804800b] 00000006 E805000000 call 0x10 0000000B 0100 add [eax],eax 0000000D 90 nop 0000000E 90 nop 0000000F 90 nop 00000010 50 push eax 00000011 53 push ebx 00000012 55 push ebp 00000013 89E5 mov ebp,esp 00000015 8B5D08 mov ebx,[ebp+0x8] 00000018 8B03 mov eax,[ebx] 0000001A 0501000000 add eax,0x1 0000001F 8903 mov [ebx],eax 00000021 89EC mov esp,ebp 00000023 5D pop ebp 00000024 5B pop ebx 00000025 58 pop eax 00000026 C3 ret |
extern void incr(int*); main() { int a=1; printf("%d\n",a); incr(&a); printf("%d\n",a); return; } |
On compile et on teste :
$ gcc main.c lib.o
$ ./a.out
1
2