Search code examples
assemblyx86-64nasmstatic-librariesld

How to link an .a library with an .asm file?


As the question mentions i am trying to link an .a library with an .asm file. I am using Ubuntu, nasm and gcc for doing so with the following MRE and commands:

nasm -f elf64 -o use.o use.asm
nasm -f elf64 -o strlen.o strlen.asm

ar rc libstring.a strlen.o
ranlib libstring.a

ld -static -nostdlib -build-id=none -L. -lstring -o use.bin use.o

The used files look like this: strlen.asm:

BITS 64
GLOBAL strlen

;-------------------------------------------------------------------------------
; @func strlen
;
; @params String str
;
; @returns uint_32 length
;-------------------------------------------------------------------------------

strlen:
push rcx
push rsi

xor eax, eax
xor ecx, ecx
mov rsi, [rsp + 0x10]

jmp .foreach

.inc_i:
inc ecx

.foreach:
lodsb
or al, al
jnz .inc_i

.return:
mov eax, ecx
pop rsi
pop rcx
ret

use.asm:

BITS 64

GLOBAL _start
EXTERN strlen

_start:
push str
call strlen
cli
hlt

str: DB "String!", 0x00

I do NOT expect them to do something, they should just compile. Currently the linker gives this error:

ld: use.o: in function `_start':
use.asm:(.text+0x6): undefined reference to `strlen'

Since the error does not mention that the file could not be found, i guess the naming convention of .a files is correct. But why does it not find the method then?


Solution

  • In order to solve this, one has to order the -L and -l flags in a way, they are placed after the files which require them. When using multiple libraries in different locations, one has to make sure the repositioning doesn't misposition the -L flag(s), that could cause some trouble aswell.

    So in this MRE, the ld command should look like this:
    ld -static -nostdlib -build-id=none use.o -L . -l string -o use.bin

    Also don't forget to sudo chmod +x make.sh when using a bash script to compile, that might give you 5 minutes of head scratching ^^