I tried to put code not in the main function, but directly into _start
:
segment .text
global _start
_start:
push rbp
mov rbp, rsp
; ... program logic ...
leave
ret
Compile:
yasm -f elf64 main.s
ld -o main main.o
Run:
./main
Segmentation fault(core dumped)
I read, leave is
mov esp,ebp
pop ebp
But why is it that such an epilogue to the pop stack frame and the set base frame pointer to a previous frame's base results in a segmentation fault?
Indeed, making an exit system call exits gracefully.
As per ABI1 the stack at the entry on
_start
isThere is no "return address".
The only way to exit a process is through
SYS_EXIT
1 Section 3.4.1 Initial Stack and Register State.
The
LEAVE
instruction is defined to not cause any exceptions, so it cannot be the source of your fault. You should be using GDB. Debuggers are invaluable in solving these sorts of problems.This is what happens:
So, most likely your program ran to completion, but the first thing on the stack that 0x0000000000000001.
RET
popped that into theRIP
register, and then it segfaulted because that address is not mapped.I don't write a lot of code on Linux, but I would bet that
_start
is required to use the exit system call. The only way you could possibly return to a useful address is if the kernel put a function somewhere that would do this for you.