我正在学习集会,而我正在尝试运行一个非常简单的程序。
section .text
global start
global _main
start:
call _main
ret
_main:
push 42
ret
我在OSX 64位上使用NASM。这是我试过的:
$ nasm -f macho64 simple.asm -o simple.o
$ ld simple.o -o a.out
$ ./a.out
dyld: no writable segment
[1] 38021 trace trap ./a.out
$
$ ld -lc -ldylib1.o -e start simple.o -o a.out
$ ./a.out
[1] 38134 segmentation fault ./a.out
$
$ ld -macosx_version_min 10.8 -lSystem simple.o -o a.out
[1] 38134 segmentation fault ./a.out
$
关注this post后,我在代码中添加了section .data
。
$ nasm -f macho64 simple.asm && ld simple.o && ./a.out
[1] 39119 killed ./a.out
1)如何让我的程序不被杀?
2)为什么我的程序会获得这些信号( SIGTRAP , SIGSEGV 和 SIGKILL )?
3)我可以在哪里找到答案而不问?到目前为止,我发现的解释确实需要先前有关装配的知识。
修改
我理解push 42
的错误,谢谢。我的程序在加载ld -macosx_version_min 10.8 -lSystem simple.o
时运行。但是:
加载ld simple.o
加载ld -lc -ldylib1.o -e start simple.o
当我添加section .data
并加载ld simple.o
我添加section .data
并加载ld -macosx_version_min 10.8 -lSystem simple.o
时出现总线错误
我想知道为什么我会得到那些信号(为了理解它是如何工作的)。我也想知道为什么我必须指定macosx_version_min
以及如何在没有朋友告诉我的情况下找到它。
答案 0 :(得分:2)
1)如何让我的程序不被杀?
不是C:你没有ret
那样。您的代码不会从预先建立的环境中调用;您应该ret
求什么?通过发出这样的指令,您的jmp
- 当前位于%rsp
的堆栈上的任何值,并进入可能位于进程外的地区空间,因此是SIGSEGV。
您必须明确告诉操作系统您的进程已通过系统调用终止其执行。
此外,ELF的起点通常是_start
,而不是start
,否则您应该向链接器指示。
当加载ld -lc -ldylib1.o -e start simple.o时,我仍然有段错误。
不要与C链接,除非您符合其执行模式。另外,我不明白你的意思是“用ld file.o加载”。
答案 1 :(得分:2)
您的主要问题很简单。在你的短程序中,你会在RET
弹出它之前立即在堆栈上推送值42以跳转到它 - 这会导致segfault
,因为它会跳转到地址00000042
(32 -bit-mode),(在保护模式下)最有可能导致异常。