Precedent | Sommaire | Suivant

A. La programmation separée avec nasm

Les exemples ci-dessous illustre la possibilite de faire de la configuration separee en assembleur (ici en utilisant nasm).

A.1 Exemple avec deux fichiers en assembleur

Le fichier lib.asm contient une fonction qui incremente un entier passe en argument (passage par pointeur). La fonction incr prend un pointeur sur un entier (int sur 4 octets) en argument et l'incremente de 1. Pour que cette fonction soit visible au linkage, on la declare au debut du fichier grace a la directive global :
$ cat lib.asm
		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
	

A.2 Exemple avec un fichier en assembleur et un fichier en C

Dans cet exemple, on conserve toujours la fonction incr definie dans le fichier objet lib.o (obtenu a partir de lib.asm). On appelle cette fonction a partir d'un tres court programme ecrit en C. La fonction incr est declaree comme etant externe :
$ cat main.c
		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