I am trying to learn writing assembly language for 64 bit Mac OS. I have no problem with 32 bit Mac OS and both 32 bit and 64 bit Linux.
However, Mac OS 64 bit is different and I couldn't figure out. Therefore I am here to ask for help.
I have not problem using system call to print. However, I would like to learn how to call C functions using 64 bit assembly language of Mac OS.
Please look at the following code
.data
_hello:
.asciz "Hello, world\n"
.text
.globl _main
_main:
movq $0, %rax
movq _hello(%rip), %rdi
call _printf
I use $ gcc -arch x86_64 hello.s
to assemble and link.
It generates binary code. However, I got a segmentation fault when running it.
I tried adding "subq $8, %rsp" before calling _printf, still the same result as before.
What did I do wrong?
By the way, is that any way to debug this code on Mac? I tried adding -ggdb or -gstab or -gDWARF, and $gdb ./a.out, and can't see the code and set break points.
You didn't say exactly what the problem you're seeing is, but I'm guessing that you're crashing at the point of the call to printf
. This is because OS X (both 32- and 64-bit) requires that the stack pointer have 16-byte alignment at the point of any external function call.
The stack pointer was 16-byte aligned when _main
was called; that call pushed an eight-byte return address onto the stack, so the stack is not 16-byte aligned at the point of the call to _printf
. Subtract eight from %rsp
before making the call in order to properly align it.
So I went ahead and debugged this for you (no magic involved, just use gdb, break main
, display/5i $pc
, stepi
, etc). The other problem you're having is here:
movq _hello(%rip), %rdi
This loads the first eight bytes of your string into %rdi
, which isn't what you want at all (in particular, the first eight bytes of your string are exceedingly unlikely to constitute a valid pointer to a format string, which results in a crash in printf
). Instead, you want to load the address of the string. A debugged version of your program is:
.cstring
_hello: .asciz "Hello, world\n"
.text
.globl _main
_main:
sub $8, %rsp // align rsp to 16B boundary
mov $0, %rax
lea _hello(%rip), %rdi // load address of format string
call _printf // call printf
add $8, %rsp // restore rsp
ret
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