我尝试将代码放在main函数中,但直接放入_start
:
segment .text
global _start
_start:
push rbp
mov rbp, rsp
; ... program logic ...
leave
ret
编译:
yasm -f elf64 main.s
ld -o main main.o
执行命令
./main
Segmentation fault(core dumped)
我看了,离开是
mov esp,ebp
pop ebp
但是为什么弹出堆栈帧和设置的基本帧指针到前一帧的基数这样的结尾会导致分段错误?
确实,退出系统调用会优雅地退出。
答案 0 :(得分:3)
LEAVE
指令定义为不会导致任何异常,因此它不能成为您的错误来源。你应该使用GDB。调试器在解决这些问题时非常有用。
这就是:
$ gdb ./main
[...]
程序接收信号SIGSEGV,分段故障 0x0000000000000001在?? ?? ()
(gdb)x / gx $ rsp-8
0x7fffffffe650:0x0000000000000001
所以,很可能你的程序运行完毕,但堆栈上的第一件事就是0x0000000000000001。 RET
将其弹出到RIP
寄存器中,然后将其分段,因为该地址未映射。
我没有在Linux上编写很多代码,但我敢打赌使用退出系统调用需要_start
。你可以返回一个有用的地址的唯一方法是,如果内核在某个地方放置一个可以为你做这个的函数。
答案 1 :(得分:3)
根据ABI 1 ,_start
条目的堆栈是
没有"返回地址"。
退出流程的唯一方法是SYS_EXIT
xorl %edi, %edi ;Error code
movl $60, %eax ;SYS_EXIT
syscall
1 部分 3.4.1初始堆栈和注册状态。