我一直试图使用NASM在Mac-OS和Windows上学习64位汇编。
我的代码是
extern _printf
section .data
msg db "Hello World!", 10, 0
section .text
global _main
_main:
mov rax, 0
mov rdi, msg
call _printf
mov rax, 0x2000001
mov rdi, 0
syscall
然后我用
进行编译nasm -f macho64 -o main.o main.asm
gcc -o main main.o
尝试致电_printf
时出现错误
分段错误:11
当我删除对_printf
的调用时,我的代码运行良好。
为什么调用_printf
会导致分段错误?
我已经找到了ABI调用约定here,但没有成功调用C函数的运气。
我希望可以打印Hello World!
,但是我会得到'Segmentation Fault:11'。
答案 0 :(得分:3)
~~您需要在调用 _printf
TL; DR::System V AMD64 ABI要求堆栈指针是16字节对齐的。在调用_printf
时,堆栈指针未对齐8个字节。
使用LLDB调试二进制文件可获得:
帧#0:0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
MacOS使用System V AMD64 ABI,因此堆栈指针(see this question)依赖16字节对齐,简而言之,这意味着堆栈指针(rsp
)应该始终可分调用函数时乘以16。
在调用_printf
时,堆栈指针(rsp
)未对齐8个字节。这是怎么来的?
我在this page上找到了答案,调用_main
函数将返回地址(8字节)压入堆栈,因此未对齐。
我最初的想法-设置堆栈框架-将另一个地址压入堆栈,因此rsp
再次被16整除。
但是,Margaret Bloom提出的更简单的解决方案就是sub rsp, 8
将代码更改为:
extern _printf
section .data
msg: db "Hello World!", 10, 0
section .text
global _main
_main:
;; Fix the stack alignment
sub rsp, 8
mov rax, 0
mov rdi, msg
call _printf
mov rax, 0x2000001
mov rdi, 0
syscall
在macOS 10.13.6上测试