【发布时间】:2016-11-16 00:13:15
【问题描述】:
我正在学习汇编,我正在尝试运行一个非常简单的程序。
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时,我仍然有SIGTRAP我在加载
ld -lc -ldylib1.o -e start simple.o时仍然有段错误当我添加
section .data并加载ld simple.o时,我仍然有一个 SIGKILL当我添加
section .data并使用ld -macosx_version_min 10.8 -lSystem simple.o加载时出现总线错误
我想知道为什么我会收到这些信号(以便了解它是如何工作的)。我还想知道为什么我必须指定macosx_version_min,以及我如何在没有朋友告诉我的情况下找到它。
【问题讨论】:
-
ret,引用手册,“将程序控制转移到位于堆栈顶部的返回地址。”那将是 42。 -
您确定使用 SIGKILL 吗?如果入口点在一个不可执行的页面中,我会期待 SIGSEGV(至少在 Linux 上)。尝试使用
strace ./a.out来跟踪系统调用,包括执行文件的execve。此外,运行gdb ./a.out(或lldb,或您喜欢的任何调试器),并单步执行您的代码,以便查看导致内核传递信号的指令错误和结果。 -
另外,你的标题是错误的。你的程序绝对不是空的。如果是这样,您只需将零填充作为指令运行,或者 SIGILL,如果执行遇到其他一些未解码为有效指令的字节。