4

我正在尝试在我的 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在运行时产生。有没有人对如何克服这个有任何想法?

4

1 回答 1

9

要回答有关BUS ERROR的具体问题,这是因为您没有正确退出应用程序,并且处理器在代码中的最后一条指令之后开始执行内存中的内容。最终导致故障。一旦处理器到达包含您的代码的可执行页面的末尾并开始执行该部分,就可能发生BUS ERROR 。部分是不可执行的,因此很可能导致您观察到的错误。这只是一个有根据的猜测,因为它高度依赖于内存的内容和布局。.data.data

看来您正在绕过C运行时,因此您不能使用RET返回操作系统。您需要调用 64 位 OS/X SYSCALL 之一

可以在Apple 的网站上找到 64 位 OS/X 系统调用的列表。您可以从本教程(在 64 位部分)学习基础知识。exit 系统调用有一个入口:

1    AUE_EXIT   ALL   { void exit(int rval); } 

从教程中,参数传递约定被描述为:

  • 参数在寄存器 rdi、rsi、rdx、r10、r8 和 r9 上传递 rax 寄存器中的系统调用号
  • 调用是通过 syscall 指令完成的
  • OS X 对混合的贡献是您必须将 0x20000000 添加到系统调用号(仍然必须找出原因)

完整的调用约定在64 位 System V ABI中描述。关于 SYSCALL 的另一个重要说明是:

  • 系统调用是通过 syscall 指令完成的。内核销毁寄存器 %rcx 和 %r11。

考虑到这一切,我们想调用1 AUE_EXIT ALL { void exit(int rval); }. 系统调用号在第一列。在 64 位 OS/X 上,我们向其添加 0x2000000 并将其传递给RAX。exit 系统调用采用一个参数,因此它在RDI中传递。这是退出值。使用 exit 系统调用并返回 0 的代码可能如下所示:

mov eax, 0x2000001 
xor edi, edi ; Return exit value 0 to system 
syscall

调试

正如@paulsm4 在他删除的答案中正确指出的那样:

最后,我不确定您的“总线错误”来自哪里。但是调试器会告诉你

要查找SIGBUSSIGSEGV错误,最好使用调试器逐步执行汇编指令并找出故障所在。在这种情况下,您会发现在 之后调用了意外指令mov [b], rax

OS/X 上最常用的命令行调试器是LLDB您可以在LLDB 教程中找到更多关于它的使用信息。

于 2016-06-20T01:13:06.590 回答