There was a macro file named NASM32.inc floating around a few years ago that did just this. It's now evolved into the NASMX macro set, you should look into that for a lot of decent examples of macros. However, to save you a little time, this is how you could go about doing it:
%ifndef _EXTERNDEF_INCLUDED
%define _EXTERNDEF_INCLUDED
%imacro externdef 1
%ifndef __%1_defined
%define __%1_defined
%else
%error %1 already defined.
%endif
%endmacro
%imacro call 1
%ifndef %1
%ifdef __%1_defined
%ifndef __%1_used
%define __%1_used
extern %1
%endif
%endif
%endif
call %1
%endmacro
%endif ;_EXTERNDEF_INCLUDED
%include "externdef.inc"
externdef printf ; used
externdef strlen ; unused
externdef socket ; unused
section .text
my_proc:
push dword sz_message2
push dword sz_format
call printf
add esp, (2 * 4)
ret
global main
main:
push dword sz_message1
push dword sz_format
call printf
add esp, (2 * 4)
call my_proc
mov eax, 0
ret
section .data
sz_message1: db "Hello world!", 0
sz_message2: db "Hello again!", 0
sz_format: db "%s", 13, 10, 0
bkeller@debian:~$ cd externdef/
bkeller@debian:~/externdef$ ls
externdef.inc testapp.asm
bkeller@debian:~/externdef$ nasm -f elf32 testapp.asm -o testapp.o
bkeller@debian:~/externdef$ gcc -m32 testapp.o -o testapp
bkeller@debian:~/externdef$ ./testapp
Hello world!
Hello again!
bkeller@debian:~/externdef$
%line 3+1 externdef.inc
%line 11+1 externdef.inc
%line 23+1 externdef.inc
%line 2+1 testapp.asm
%line 6+1 testapp.asm
[section .text]
my_proc:
push dword sz_message2
push dword sz_format
[extern printf]
%line 12+0 testapp.asm
call printf
%line 13+1 testapp.asm
add esp, (2 * 4)
ret
[global main]
main:
push dword sz_message1
push dword sz_format
call printf
add esp, (2 * 4)
call my_proc
mov eax, 0
ret
[section .data]
sz_message1: db "Hello world!", 0
sz_message2: db "Hello again!", 0
sz_format: db "%s", 13, 10, 0
As it is, the file EXTERNDEF.INC could also be included into other header files without worrying about multiple-inclusion issues. Hope this helps.