繁体   English   中英

_start 中 RET 上的 Nasm 分段错误

[英]Nasm segmentation fault on RET in _start

section .text
     global _start
_start:
     nop
main:
     mov eax, 1
     mov ebx, 2
     xor eax, eax
     ret

我用这些命令编译:

nasm -f elf main.asm
ld -melf_i386 -o main main.o

当我运行代码时,Linux 抛出一个分段错误错误

(我使用的是 Linux Mint Nadia 64 位)。 为什么会产生这个错误?

因为ret不是在 Linux、Windows 或 Mac 中退出程序的正确方法!!!!

_start不是函数,堆栈上没有返回地址,因为没有用户空间调用者要返回。 用户空间中的执行从这里开始(在静态可执行文件中),在进程入口点。 (或者使用动态链接,它在动态链接器完成后跳到这里,但结果相同)。

在 Linux / OS X 上,堆栈指针指向_start入口处的argc (有关进程启动环境的更多详细信息,请参阅 i386 或 x86-64 System V ABI 文档); 内核在启动用户空间之前将命令行参数放入用户空间堆栈内存中。 (因此,如果您确实尝试ret ,则 EIP/RIP = argc = 一个小整数,而不是有效地址。如果您的调试器在地址0x00000001或其他地方显示错误,这就是原因。)


对于 Windows,它是ExitProcess而 Linux 是系统调用 - int 80H使用sys_exit ,对于 x86 或使用60 syscall用于 64Bit 或调用从 C 库exit (如果您链接到它)。

32位Linux

mov     eax, sys_exit ; sys_exit = 1
xor     ebx, ebx
int     80H

64 位 Linux

mov     rax, 60
xor     rdi, rdi
syscall

视窗

push    0
call    ExitProcess

或者 Windows/Linux 链接到 C 库

call    exit

exit (与原始退出系统调用或 libc _exit )将首先刷新 stdio 缓冲区。 如果您从_start使用printf ,请使用exit确保在退出之前打印所有输出,即使 stdout 被重定向到文件(使 stdout 为全缓冲,而不是行缓冲)。

它通常建议,如果你使用libc函数,你写一个main函数和链接用gcc,所以它通过它可以正常启动CRT函数调用ret到。

main定义为_start落入的东西并不会使它变得特别,如果它不像由准备在main返回后退出的_start调用的 C main函数,那么使用main标签只是令人困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM