gpt4 book ai didi

linux - _start 中 RET 上的 Nasm 段错误

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:18:11 27 4
gpt4 key购买 nike

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


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

32 位 Linux (i386)

%define  SYS_exit  1   ; call number __NR_exit from <asm/unistd_32.h>

mov eax, SYS_exit ; use the NASM macro we defined earlier
xor ebx, ebx ; ebx = 0 exit status
int 80H ; _exit(0)

64 位 Linux (amd64)

mov     rax, 60        ; SYS_exit aka __NR_exit from asm/unistd_64.h
xor rdi, rdi ; edi = 0 first arg to 64-bit system calls
syscall ; _exit(0)

(在 GAS 中,您实际上可以使用 #include <sys/syscall.h><asm/unistd.h> 来为您正在组装 .S 的模式获取正确的数字,但 NASM 无法轻松使用 C 预处理器。参见 Polygot include file for nasm/yasm and C提示。)

32 位 Windows (x86)

push    0
call ExitProcess

或者 Windows/Linux 链接到 C 库

; pass an int exit_status as appropriate for the calling convention
; push 0 / xor edi,edi / xor ecx,ecx
call exit

(或者对于 32 位 x86 Windows,call _exit ,因为 C 名称前面有一个下划线,这与 x86-64 Windows 不同。POSIX _exit 函数将是 call __exit ,如果 Windows 有的话。)

Windows x64 的调用约定包括调用者必须保留的影子空间,但是 exit不会返回,所以可以让它踩到返回地址上方的那个空间。此外,调用约定要求在 call exit 之前进行 16 字节堆栈对齐。除了 32 位 Windows,但通常不会因为像 exit() 这样的简单函数而真正崩溃。 .


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

一般建议如果你使用libc函数,你写一个main函数并与 gcc 链接,因此它会被正常的 CRT 启动函数调用,您可以 ret到。

另见

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

关于linux - _start 中 RET 上的 Nasm 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19760002/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com