To answer the specific question about the BUS ERROR, it occurs because you haven't properly exited your application and the processor started executing what was in memory after the last instruction in your code. That eventually lead to a fault. Likely the BUS ERROR occurred once the processor reached the end of the executable page containing your code and started executing the .data
section. .data
section is non-executable so likely caused the error you observed. This is just an educated guess as it is highly dependent on the contents and layout of memory.
It appears you are bypassing the C runtime, so you can't use RET to return back to the OS. You'll need to invoke one of the 64-bit OS/X SYSCALLs.
A list of the 64-bit OS/X System Calls can be found on Apple's site. You can learn the basics from this tutorial (in the 64-bit section). The exit system call has an entry:
1 AUE_EXIT ALL { void exit(int rval); }
From the tutorial, the parameter passing convention is described as:
- arguments are passed on the registers rdi, rsi, rdx, r10, r8 and r9
syscall number in the rax register
- the call is done via the syscall instruction
- what OS X contributes to the mix is that you have to add 0x20000000 to the syscall number (still have to figure out why)
The complete calling convention is described in the 64-bit System V ABI. One other important note about SYSCALLs is:
- A system-call is done via the syscall instruction. The kernel destroys
registers %rcx and %r11.
With all this in mind we want to call 1 AUE_EXIT ALL { void exit(int rval); }
. The system call number is in the first column. On 64-bit OS/X we add 0x2000000 to it and pass it in RAX. The exit system call takes one parameter, so it is passed in RDI. This is the exit value. Code that would use the exit system call and return 0 could look like this:
mov eax, 0x2000001
xor edi, edi ; Return exit value 0 to system
syscall
Debugging
As @paulsm4 correctly pointed out in his deleted answer:
Finally, I'm not sure where your "bus error" is coming from. But a debugger would tell you
To find SIGBUS and SIGSEGV errors it is best to use a debugger to step through the assembly instructions and find where the failure is at. In this case you would have discovered that an unexpected instruction was being called after mov [b], rax
.
The most common command line debugger available on OS/X is LLDB. You can find more information on it usage in the LLDB tutorial.