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.
我正在努力学习为64位Mac OS编写汇编语言。我对32位Mac OS以及32位和64位Linux没有任何问题。
However, Mac OS 64 bit is different and I couldn't figure out. Therefore I am here to ask for help.
但是,Mac OS 64位是不同的,我无法弄清楚。因此,我在这里寻求帮助。
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.
我没有使用系统调用打印的问题。但是,我想学习如何使用Mac OS的64位汇编语言调用C函数。
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
我使用$ 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.
我在调用_printf之前尝试添加“subq $ 8,%rsp”,仍然和以前一样。
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.
顺便说一下,这是在Mac上调试此代码的方法吗?我尝试添加-ggdb或-gstab或-gDWARF和$ gdb ./a.out,但无法查看代码并设置断点。
1 个解决方案
#1
8
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.
你没有确切地说出你所看到的问题是什么,但我猜你在调用printf时崩溃了。这是因为OS X(32位和64位)要求堆栈指针在任何外部函数调用时具有16字节对齐。
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.
调用_main时,堆栈指针是16字节对齐的;该调用将一个8字节的返回地址压入堆栈,因此堆栈在调用_printf时不是16字节对齐的。在进行调用之前从%rsp中减去8,以便正确对齐它。
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:
所以我继续为你调试这个(没有魔法,只需使用gdb,break main,display / 5i $ pc,stepi等)。你遇到的另一个问题是:
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:
这会将字符串的前八个字节加载到%rdi中,这根本不是您想要的(特别是,字符串的前八个字节极不可能构成指向格式字符串的有效指针,这会导致在printf崩溃)。相反,您想要加载字符串的地址。调试版程序是:
.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
#1
8
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.
你没有确切地说出你所看到的问题是什么,但我猜你在调用printf时崩溃了。这是因为OS X(32位和64位)要求堆栈指针在任何外部函数调用时具有16字节对齐。
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.
调用_main时,堆栈指针是16字节对齐的;该调用将一个8字节的返回地址压入堆栈,因此堆栈在调用_printf时不是16字节对齐的。在进行调用之前从%rsp中减去8,以便正确对齐它。
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:
所以我继续为你调试这个(没有魔法,只需使用gdb,break main,display / 5i $ pc,stepi等)。你遇到的另一个问题是:
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:
这会将字符串的前八个字节加载到%rdi中,这根本不是您想要的(特别是,字符串的前八个字节极不可能构成指向格式字符串的有效指针,这会导致在printf崩溃)。相反,您想要加载字符串的地址。调试版程序是:
.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