_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位).为什么会产生此错误?
因为 在Linux/OS X上,堆栈指针指向 对于Windows,它是 32位Linux 64位Linux Windows
或Windows/Linux链接到C库 通常建议,如果您使用libc函数,请编写一个 将_start
不是函数,堆栈上没有返回地址,因为没有用户空间调用者可以返回.用户空间中的执行在进程入口点从此处开始(在静态可执行文件中). (或者使用动态链接,它在动态链接器完成后跳到了这里,但是结果相同.)_start
的入口处的argc
(有关进程启动环境的更多详细信息,请参阅i386或x86-64 System V ABI文档);内核在启动用户空间之前将命令行参数args放入用户空间堆栈内存中. (因此,如果您尝试尝试ret
,则EIP/RIP = argc =一个小整数,不是有效的地址.如果调试器在地址0x00000001
上显示故障,则是这样.)
ExitProcess
,对于Linux,是系统调用-
int 80H
使用sys_exit
(对于x86)或syscall
使用60
(对于64Bit)或从C库调用exit
(如果要链接).mov eax, sys_exit ; sys_exit = 1
xor ebx, ebx
int 80H
mov rax, 60
xor rdi, rdi
syscall
push 0
call ExitProcess
call exit
exit
(与原始退出系统调用或libc _exit
不同)将首先刷新stdio缓冲区.如果您使用的是_start
中的printf
,请使用exit
确保在退出之前已打印所有输出,即使将stdout重定向到文件(使stdout成为全缓冲而不是行缓冲).main
函数并与gcc链接,以便由普通的CRT启动函数调用,您可以ret
进行调用.main
定义为_start
的内容并没有什么特别之处,如果它不像_start
所调用的C main
函数那样,则会混淆使用main
标签准备在main
返回后退出.
section .text
global _start
_start:
nop
main:
mov eax, 1
mov ebx, 2
xor eax, eax
ret
I compile with these commands:
nasm -f elf main.asm
ld -melf_i386 -o main main.o
When I run the code, Linux throw a segmentation fault error
(I am using Linux Mint Nadia 64 bits). Why this error is produced?
Because ret
is NOT the proper way to exit a program in Linux, Windows, or Mac!!!!
_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).
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.)
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 bit Linux
mov eax, sys_exit ; sys_exit = 1
xor ebx, ebx
int 80H
64 bit Linux
mov rax, 60
xor rdi, rdi
syscall
Windows
push 0
call ExitProcess
Or Windows/Linux linking against the C Library
call exit
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).
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.
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屋!