If you use a custom linker script, _start is not (necessarily) the entry point
For most of my life I took for granted that programs begin executing at an
address denoted by the symbol _start
(a single underscore, followed by the
word “start”). Turns out it’s not so simple.
Take this x86 assembly program that prints “Hello, World!” on Linux:
.global _start
.text
message:
.ascii "Hello, World!\n"
_start:
# print the message
mov $1, %rax # syscall 1 is write
mov $1, %rdi # file descriptor 1 is stdout
mov $message, %rsi # pass address of messsage
mov $13, %rdx # pass length of message
syscall # perform write system call
# exit
mov $60, %rax # syscall 60 is exit
mov $0, %rdi # pass exit status of 0
syscall # perform exit system call
To compile and run this program (assume it’s in the file hello.s):
$ gcc -c hello.s # compile hello.s to object file hello.o
$ ld hello.o # link hello.o to executable a.out
$ ./a.out
Hello, World!