Linux RET in\U启动时的Nasm分段故障
我使用以下命令进行编译:Linux RET in\U启动时的Nasm分段故障,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我使用以下命令进行编译: section .text global _start _start: nop main: mov eax, 1 mov ebx, 2 xor eax, eax ret 当我运行代码时,Linux抛出一个分段错误 (我使用的是LinuxMintNadia64位)。为什么会产生此错误?因为ret不是退出Linux、Windows或Mac中程序的正确方法 \u start不是一个函数,堆栈上没有返回地址,因为没有
section .text
global _start
_start:
nop
main:
mov eax, 1
mov ebx, 2
xor eax, eax
ret
当我运行代码时,Linux抛出一个分段错误
(我使用的是LinuxMintNadia64位)。为什么会产生此错误?因为
ret
不是退出Linux、Windows或Mac中程序的正确方法
\u start
不是一个函数,堆栈上没有返回地址,因为没有要返回的用户空间调用方。用户空间中的执行从这里开始(在静态可执行文件中),在流程入口点。(或者使用动态链接,它在动态链接器完成后跳到这里,但结果相同)
在Linux/OS X上,堆栈指针指向\u start
条目上的argc
(有关进程启动环境的更多详细信息,请参阅i386或x86-64 System V ABI文档);内核在启动用户空间之前将命令行参数放入用户空间堆栈内存。(因此,如果您确实尝试ret
,EIP/RIP=argc=一个小整数,而不是一个有效的地址。如果调试器在地址0x00000001
或其他位置显示错误,这就是原因。)
对于Windows,它是ExitProcess,Linux是系统调用-
int 80H
对于x86使用sys\u exit
,对于64位使用60
或从C库调用exit
(如果您正在链接到它)
32位Linux
nasm -f elf main.asm
ld -melf_i386 -o main main.o
mov eax, sys_exit ; sys_exit = 1
xor ebx, ebx
int 80H
64位Linux
nasm -f elf main.asm
ld -melf_i386 -o main main.o
mov eax, sys_exit ; sys_exit = 1
xor ebx, ebx
int 80H
窗口
mov rax, 60
xor rdi, rdi
syscall
或针对C库的Windows/Linux链接
push 0
call ExitProcess
exit
(与原始exit系统调用或libc\u exit
不同)将首先刷新stdio缓冲区。如果从\u start
使用printf
,请使用exit
确保在退出之前打印所有输出,即使stdout被重定向到文件(使stdout完全缓冲,而不是行缓冲)
一般建议,如果使用libc函数,您可以编写一个main
函数并与gcc链接,这样就可以通过正常的CRT启动函数调用它,您可以ret
调用它
将
main
定义为\u start
所包含的内容并不意味着它特别,如果一个main
标签不像一个\u start
调用的Cmain
函数,它准备在main
返回后退出,那么使用main
标签会让人感到困惑。应该是返回代码,而不是这样的(Linux):mov eax,1 mov ebx,0 int 80h
在我看来,由于最后一行中的ret
,您得到了分段错误。@maxiperez根本不是一个愚蠢的问题:)。它表明程序不仅仅是一个“主要”功能,它们还以不同的方式与操作系统交互。