OS / X 64位汇编代码会生成总线错误

时间:2016-06-19 22:38:05

标签: macos assembly nasm x86-64 bus-error

我正在尝试在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。有没有人对如何克服这个问题有任何想法?

1 个答案:

答案 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中找到有关其用法的更多信息。