从 NASM 调用 C 函数 _printf 会导致分段错误 [英] Calling the C-function _printf from NASM causes a Segmentation Fault
问题描述
我一直在尝试使用 NASM 在 Mac-OS 和 Windows 上学习 64 位汇编.
I've been trying to learn 64-bit assembly on both Mac-OS and Windows using NASM.
我的代码是
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
时,出现错误
While trying to call _printf
, I got the error
分段错误:11
当我删除对 _printf
的调用时,我的代码运行良好.为什么调用 _printf
会导致分段错误?
When I remove the call to _printf
, my code runs fine.
Why does the call to _printf
cause a segmentation fault?
我在此处找到了 ABI 调用约定,但没有成功调用 C 函数.
I have found the ABI Calling Convention here, but had no luck successfully calling a C-function.
我希望打印 Hello World!
,但我得到的是Segmentation Fault: 11".
I would expect Hello World!
to be printedd, however I get 'Segmentation Fault: 11' instead.
推荐答案
~~调用_printf
TL;DR: System V AMD64 ABI 要求堆栈指针按 16 字节对齐.到调用 _printf
时,堆栈指针错位了 8 个字节.
TL;DR: The System V AMD64 ABI requires the stack-pointer to be 16-byte-aligned. By the time of calling _printf
, the stack-pointer is misaligned by 8 bytes.
使用 LLDB 调试二进制文件给出:
Debugging the binary with LLDB gives:
第 0 帧:0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
frame #0: 0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
MacOS 使用 System V AMD64 ABI,因此堆栈指针依赖于 16 字节对齐(见这个问题),简而言之,这意味着堆栈指针(rsp
)应该总是被整除16 调用函数时.
MacOS uses the System V AMD64 ABI and therefore relies on 16-byte alignment for the stack-pointer (see this question), in short this means the stack-pointer (rsp
) should always be divisible by 16 when calling a function.
到调用 _printf
时,堆栈指针 (rsp
) 错位了 8 个字节.这是怎么来的?
By the time of calling _printf
, the stack-pointer (rsp
) is misaligned by 8 bytes. How did this come?
我在此页面上找到了答案,调用了_main
函数将返回地址(8 个字节)压入堆栈,因此未对齐.
I found the answer on this page, calling the _main
function pushes the return address (8 bytes) on the stack and therefore misaligns it.
我最初的想法 - 堆栈帧的设置 - 将另一个地址推入堆栈,因此 rsp
再次被 16 整除.
My initial idea - the setup of the stack frame - pushed another address on the stack and therefore rsp
was divisible by 16 again.
然而,更简单的解决方案是 sub rsp, 8
正如 Margaret Bloom 所建议的一个>
However an easier solution would be just sub rsp, 8
as suggested by Margaret Bloom
将您的代码更改为:
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 上测试
Tested on macOS 10.13.6
这篇关于从 NASM 调用 C 函数 _printf 会导致分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!