I am trying to learn NASM on my 64-bit Macbook Pro. I have the following code where I am trying to assign the value of a variable to an initialised variable.
global start
default rel
section .data
a: dq 1
section .bss
b: resq 1
section .text
start:
mov rax, a
mov [b], rax
The code compiles and links but produces a bus error
when run. Does anyone have any ideas on how to overcome this?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With