我正在使用macOS 10.12进入x86_64程序集。
我正在尝试调用libc exit()
函数:
.section __TEXT,__text
.globl _main
_main:
pushq %rbp
movq %rsp, %rbp
movl $5, %edi
callq _exit
用以下代码编译:
as exit2.s -o exit2.o
ld exit2.o -e _main -lc -o exit
结果是:
Segmentation fault: 11
为什么会这样?
编辑:问题在于链接libc和调用约定。
答案 0 :(得分:1)
@fuz is almost certainly correct:因为您没有初始化libc而崩溃。在exit(3)
实际退出之前检查的数据结构中某处可能是NULL指针。例如如果需要,它会刷新stdout
,并运行使用atexit(3)
注册的任何函数。
如果您不希望它完成所有工作,请使用sys_exit
指令直接进行syscall
系统调用,或call
精简_exit(2)
它的libc包装函数。 (情况的基础与Linux上的相同,因为exit(3)
与_exit(2)
由POSIX标准化:请参阅Syscall implementation of exit()。
我认为the tutorial you're following看起来很好看,但也许某些旧版本的OS X允许在不调用任何libc init函数的情况下使用libc函数(包括printf
?!?)。否则,他们在编辑构建命令后没有测试他们的代码。 (假设他们进行了测试,可能是动态链接,这可行。)
OS X会在程序集中使用_
作为前缀,因此请使用call __exit
(两个下划线)来调用_exit()
。 (例如call _printf
调用C printf
函数。
_exit(2)
可能会崩溃,但调用任何libc函数仍然是一个坏主意首先调用libc init函数。最好直接进行系统调用(参见教程后面的内容),甚至更好,用gcc hello_asm.S -o hello_asm
构建它以确保初始化libc。然后,您可以按照本教程的其余部分进行操作,包括printf
。
请勿在静态可执行文件中调用Mach-O入口点_main
或main
。 CRT启动代码还没有运行。通常的惯例是为进程入口点调用它_start
。
(请注意,OS X将CRT起始码放在动态链接器中,因此the "entry point" in a dynamically-linked executable is the C main
function, unlike in Linux where dynamic executables can avoid the CRT startup code。
如果您与gcc exit2.o -o exit
而不是ld
相关联,则会为您初始化libc,您使用该gcc -static -nostartfiles
来执行相当于this.form.get('passwordRepeat').setErrors(null);
的操作。)