Let's suppose that you have a library.asm with a function that has a loop:
section .text
useful_func:
push rbp
mov rbp, rsp
loop0:
; Do useful stuff...
jnz loop0
mov rsp, rbp
pop rbp
ret
and a main.asm that includes the library and calls that function:
%include "library.asm"
section .text
global _start
_start:
; Do stuff
call useful_func
; Do more stuff
Of course, as a user of library.asm, you're not really interested in the label loop0
, you're actually interested in useful_func
. However, both labels are imported. So if you change your main.asm to:
%include "library.asm"
section .text
global _start
_start:
; Do stuff
loop0:
call useful_func
jnz loop0
; Do more stuff
You get an error, since the label loop0
was defined twice.
So, is there any way to specify to NASM which labels are useful and should be exported/imported, and which ones shouldn't?
Note: There is no necessity for the use of the %include
command, it's simply the only way that I know to import from another file in NASM. If there is a better and more flexible command/way to do that, it's also appreciated.
Use local labels. nasm.us/doc/nasmdoc3.html section 3.9
Local labels start with a .
, and can be used as many times as you want on the code. Each local label is tied to the last non-local label. On this example:
1 label1:
2 .loop: ; Implicitly label1.loop
3 ;stuff
4 label2:
5 .loop: ; Implicitly label2.loop
6 ;other stuff
7 jmp .loop ; Implicitly label2.loop
line 7
will jump to line 5
, since both of them are local and after label2
. So you can change the labels that should not be external to local, and no conflict will happen:
library.asm
section .text
useful_func:
push rbp
mov rbp, rsp
.loop0: ; Now local
; Do useful stuff...
jnz .loop0
mov rsp, rbp
pop rbp
ret
main.asm
%include "library.asm"
section .text
global _start
_start:
; Do stuff
.loop0:
call useful_func
jnz .loop0
; Do more stuff
Another way to solve this is to mark the labels you want to export as global and then link the files together instead of relying on the %include directive.
If you don't mind changing your linkage and compilation (e.g. from nasm -f elf64 main.asm && ld main.o -o main
to nasm -f elf64 library.asm && nasm -f elf64 main.asm && ld library.asm main.o -o main
), then you can use the global
/extern
directives (read this doc sections 6.5 and 6.6 for more details) instead of %include
.
Using this method, you will only export the specific labels declared with global
/extern
. So you can use it to avoid the conflict:
library.asm
global useful_func ; Now global
section .text
useful_func:
push rbp
mov rbp, rsp
loop0:
; Do useful stuff...
jnz loop0
mov rsp, rbp
pop rbp
ret
main.asm
extern useful_func ; Now extern
section .text
global _start
_start:
; Do stuff
loop0:
call useful_func
jnz loop0
; Do more stuff
Note: Even if you decide to use this method, I'd suggest making your loops/conditionals local anyway, so you can reuse the labels.