_start 中 RET 上的 Nasm 分段错误 [英] Nasm segmentation fault on RET in _start

查看:28
本文介绍了_start 中 RET 上的 Nasm 分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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抛出一个segmentation fault错误

When I run the code, Linux throw a segmentation fault error

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

(I am using Linux Mint Nadia 64 bits). Why this error is produced?

推荐答案

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

Because ret is NOT the proper way to exit a program in Linux, Windows, or Mac!!!!

_start 不是函数,栈上没有返回地址,因为没有用户空间调用者要返回.用户空间中的执行从这里开始(在静态可执行文件中),在进程入口点.(或者是动态链接,动态链接结束后就跳到这里了,结果一样)

_start is not a function, there is no return address on the stack because there is no user-space caller to return to. Execution in user-space started here (in a static executable), at the process entry point. (Or with dynamic linking, it jumped here after the dynamic linker finished, but same result).

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

On Linux / OS X, the stack pointer is pointing at argc on entry to _start (see the i386 or x86-64 System V ABI doc for more details on the process startup environment); the kernel puts command line args into user-space stack memory before starting user-space. (So if you do try to ret, EIP/RIP = argc = a small integer, not a valid address. If your debugger shows a fault at address 0x00000001 or something, that's why.)

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

For Windows it is ExitProcess and Linux is is system call - int 80H using sys_exit, for x86 or using syscall using 60 for 64Bit or a call to exit from the C Library if you are linking to it.

32 位 Linux

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

64 位 Linux

mov     rax, 60
xor     rdi, rdi
syscall

Windows

push    0
call    ExitProcess

<小时>

或针对 C 库的 Windows/Linux 链接

call    exit

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

exit (unlike a raw exit system call or libc _exit) will flush stdio buffers first. If you used printf from _start, use exit to make sure all output is printed before you exit, even if stdout is redirected to a file (making stdout full-buffered, not line-buffered).

一般建议如果你使用libc函数,你写一个main函数并与gcc链接,这样它就会被普通的CRT启动函数调用,你可以ret.

It's generally recommended that if you use libc functions, you write a main function and link with gcc so it's called by the normal CRT start functions which you can ret to.

main 定义为 _start 落入的东西并没有使它特别,如果使用 main 标签只是令人困惑不像一个由 _start 调用的 C main 函数,它准备在 main 返回后退出.

Defining main as something that _start falls through into doesn't make it special, it's just confusing to use a main label if it's not like a C main function called by a _start that's prepared to exit after main returns.

这篇关于_start 中 RET 上的 Nasm 分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆