I'm learning assembly programming. Below is the simple program that prints 'Hello, World!'. While the program runs perfectly, I'm getting the warning message while loading
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
Here is the code :
section .data
msg db 'Hello, world!', 0xa
len equ $ - msg
section .text
global main
main:
mov ebx, 1
mov ecx, msg
mov edx, len
mov eax, 4
int 0x80
mov eax, 1
int 0x80
Can anybody explain the meaning of this warning. I'm using nasm
with ubuntu 14
.
Use the label _start
instead of main
for the ELF entry point. main
implies it's like the C main
function, but this isn't even a function (e.g. you can't ret
).
You don't say, but from the warning messages and code I assume you're building your 32-bit code with nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
(If you're actually building 64-bit code, you're lucky that it happens to work, but it'll break as soon as you do anything with esp
instead of rsp
.)
The warning message is from ld
, not from nasm
. It says so right in the message. Tim's comment is correct: ld
looks for a _start
symbol in the files it links, but sets the entry point to the beginning of the text segment if it doesn't find one. (That's why this is a warning, not an error. If you had put some other code earlier in the file, execution would start there without global _start
/ _start:
)
It doesn't matter what other global/external symbols you define. main
has no relevance at all here, and could point anywhere you want. It's only useful for a disassembly output and stuff like that. Your code would work exactly the same if you took out the global main
/ main:
lines, or changed them to any other name.
Labelling that as main
is unwise because the ELF entry point is not a function. It's not main()
, and doesn't receive argc
and argv
arguments in the standard way, and can't ret
because ESP is pointing at argc
instead of a return address.
Only use main
if you link with gcc / glibc's CRT startup code that looks for a main
symbol and calls it after initializing libc. (So functions like printf work. Technically dynamic linker hooks let libc initialize itself before your _start
if you linked it, but generally don't do that unless you understand exactly what you're doing). Related: Assembling 32-bit binaries on a 64-bit system (GNU toolchain)
e.g. gcc -m32 -no-pie -o hello main.o
if you do define a main:
instead of gcc -m32 -static -nostdlib -o hello start.o
(which is equivalent to your bare ld
).
(For the past few years, Linux distros have configured GCC with -pie
as the default, which wants position-independent code. But that's really inconvenient in 32-bit mode where you don't have x86-64 RIP-relative addressing (look at GCC asm output for example), and means ld
won't convert call printf
into call printf@plt
for you. So for most hand-written asm following most tutorials, you want traditional non-PIE executables so no text relocations are needed.)