load warning: cannot find entry symbol _start
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 error messages and code I assume you're building your 32bit code with nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
(If you're actually building 64bit 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 error 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.
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, 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 without 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.)
I would suggest that you link your object files (however they are produced) with gcc
, not ld
.
gcc
will call ld
with the appropriate options, since it knows more about the source code and will create whatever is necessary for the assumptions that ld
makes.