Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么从_返回时会启动segfault?_Assembly_Stack_System Calls_Exit - Fatal编程技术网

Assembly 为什么从_返回时会启动segfault?

Assembly 为什么从_返回时会启动segfault?,assembly,stack,system-calls,exit,Assembly,Stack,System Calls,Exit,我试图将代码不放在main函数中,而是直接放在\u 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 运行: 我读了,离开了 mov esp,ebp pop ebp 但是,为什么对弹出堆栈帧的这种尾声和

我试图将代码不放在main函数中,而是直接放在
\u 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
运行:

我读了,离开了

mov esp,ebp
pop ebp
但是,为什么对弹出堆栈帧的这种尾声和指向前一帧的基帧的set base frame指针会导致分割错误呢


事实上,发出退出系统调用可以优雅地退出。

LEAVE指令被定义为不会导致任何异常,因此它不能成为您的故障源。您应该使用GDB。调试器在解决这类问题方面是无价的

情况就是这样:

$gdb./main
[…]
程序接收信号SIGSEGV,分段故障。
0x0000000000000001英寸??()

(gdb)x/gx$rsp-8
0x7FFFFFE650:0x0000000000000001

因此,您的程序很可能运行完成,但堆栈上的第一件事是0x0000000000000001
RET
将其弹出到
RIP
寄存器中,然后它会出现故障,因为该地址未映射

我在Linux上写的代码不多,但我敢打赌使用exit系统调用需要
\u start
。您可能返回到有用地址的唯一方法是,如果内核将一个函数放在某个可以为您执行此操作的位置。

根据1,在
\u start
上的条目处的堆栈是

没有“回信地址”。
退出流程的唯一方法是通过
SYS\u exit

xorl %edi, %edi   ;Error code
movl $60, %eax    ;SYS_EXIT
syscall


1第3.4.1节初始堆栈和寄存器状态。

\u start
不是由内核调用的,您不能从中返回。您能详细说明一下吗?我认为这是普通的例行公事。如何正确地“返回/退出”it?通过退出系统呼叫?是的,在提出问题之前,我使用了gdb并在main.s:7 7 ret(gdb)n 0x0000000000000001中显示了
6 leave(gdb)n_start()??()
没有发布,因为不知道“?”是什么意思。我也考虑将rip设置为内存中的未映射位置,但是,如果能够准确地知道,那就太好了。这意味着地址不在有效的模块中。因为GDB不知道它属于哪个模块,所以它会打印“?”。这里需要注意的关键是0x0000000000000001不是有效的可执行地址。当RIP指向无效或不可执行的地址时,它通常是由RET指向错误地址或间接JMP或调用错误地址引起的。如果是RET,就像这里的情况一样,堆栈顶部下面的8个字节将匹配RIP。如果是JMP或调用,有时寄存器会与RIP匹配。确实,您可能会期望堆栈上的第一个值为1,因为这是Linux传递
argc
值的地方,并且在没有任何参数的情况下调用的程序的
argc
值为1。关于参数的有用提示。所以要得到argc和argv,应该分别使用ebp+8和ebp+16堆栈偏移量?这回答了我的问题。
xorl %edi, %edi   ;Error code
movl $60, %eax    ;SYS_EXIT
syscall