Reputation: 477
I'm on Ubuntu using nasm 2.14.02.
I'm trying to write a simple hello world program with nasm by pushing the variable onto the stack and then calling printf:
; Import c-lib printf
extern printf
; Define Message and Length
section .data:
msg: db "Hello People!", 0xA
msg_len equ $-msg
section .text:
global _start
_start:
push msg
call printf
mov eax, 1
mov ebx, 0
int 80h
Assembling the program with nasm works fine, but when I try to link it with ld it throws this error:
ld: hello_world.o: in function `_start':
hello_world.asm:(.text:+0x6): undefined reference to `printf'
So it seems extern does not import printf. What am I doing wrong. This is literally my first assembler program, so please use simple words.
Edit:
The commands I was using are:
nasm hello_world.asm -f elf64
ld hello_world.o -o hello_world
Upvotes: 3
Views: 1924
Reputation: 178
You need to link your code with a library that provides printf
; that's provided by the C standard library. The easiest way to get that is to use gcc to call the linker for you.
nasm -felf32 hello_world.asm
gcc -static -o hello_world hello_world.o
The above will not work, however, because gcc will try to add some additional code found in crt1.o
that contains _start
to start the C runtime and then invoke main
.
The easiest fix for your code is to write a main
method instead.
section .text:
global main
main:
push ebp ; these two lines are the usual function entry
mov ebp, esp
push msg
call printf
xor eax, eax ; set eax to zero as the return value
mov esp, ebp ; these two lines are the usual function exit
pop ebp
ret
I'm not on a 32-bit machine, so I can't easily test that, but I think that's what you need. Use nasm
and then gcc
, as above, to assemble and link it.
If you do want to use _start
, that's fine. You need to link with the C standard library (statically... using GOT is a whole other thing), probably with -lc
.
Upvotes: 1