我正在尝试在64位Macbook Pro上学习 NASM 。我有以下代码,我试图将变量的值赋给初始化变量。
global start
default rel
section .data
a: dq 1
section .bss
b: resq 1
section .text
start:
mov rax, a
mov [b], rax
代码编译和链接但在运行时产生bus error
。有没有人对如何克服这个问题有任何想法?
答案 0 :(得分:8)
要回答有关 BUS ERROR 的具体问题,可能是因为您没有正确退出应用程序,并且处理器在代码中的最后一条指令后开始执行内存中的内容。这最终会导致错误。可能一旦处理器到达包含代码的可执行页面的末尾并且开始执行.data
部分,就会发生 BUS ERROR 。 .data
部分是不可执行的,因此很可能导致您观察到的错误。这只是一个有根据的猜测,因为它高度依赖于内存的内容和布局。
您似乎绕过 C 运行时,因此无法使用 RET 返回操作系统。您需要调用其中一个64位OS / X SYSCALL。
可以在Apple's site上找到64位OS / X系统调用的列表。您可以从这个tutorial(在64位部分中)学习基础知识。退出系统调用有一个条目:
1 AUE_EXIT ALL { void exit(int rval); }
从教程中,参数传递约定描述为:
- 参数传递给寄存器rdi,rsi,rdx,r10,r8和r9 rax寄存器中的系统调用号
- 通过系统调用指令
完成调用- OS X对混合的影响是你必须在系统调用号码中添加0x20000000(仍然要弄清楚原因)
完整的调用约定在64-bit System V ABI中描述。关于SYSCALL的另一个重要注意事项是:
- 系统调用通过syscall指令完成。内核破坏了 注册%rcx和%r11。
考虑到这一切,我们想要致电1 AUE_EXIT ALL { void exit(int rval); }
。系统呼叫号码位于第一列。在64位OS / X上,我们向它添加0x2000000并在 RAX 中传递它。退出系统调用需要一个参数,因此它在 RDI 中传递。这是退出值。使用exit系统调用并返回0的代码可能如下所示:
mov eax, 0x2000001
xor edi, edi ; Return exit value 0 to system
syscall
正如@ paulsm4在他删除的答案中正确指出的那样:
最后,我不确定你的"总线错误"是来自。但是调试器会告诉你
要查找 SIGBUS 和 SIGSEGV 错误,最好使用调试器逐步执行汇编指令并查找失败的位置。在这种情况下,您会发现在mov [b], rax
之后调用了意外的指令。
OS / X上最常用的命令行调试器是 LLDB 。您可以在LLDB tutorial中找到有关其用法的更多信息。