从 NASM 调用 C 函数 _printf 导致分段错误
Calling the C-function _printf from NASM causes a Segmentation Fault
我一直在尝试使用 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
时,出现错误
Segmentation fault: 11
当我删除对 _printf
的调用时,我的代码运行良好。
为什么调用 _printf
会导致分段错误?
我找到了 ABI 调用约定 here,但没有成功调用 C 函数。
我希望打印 Hello World!
,但我得到的是 'Segmentation Fault: 11'。
~~调用前需要设置栈帧_printf
TL;DR: System V AMD64 ABI 要求 stack-pointer 为 16-byte-aligned。在调用 _printf
时,stack-pointer 错位了 8 个字节。
使用 LLDB 调试二进制文件得到:
frame #0: 0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
MacOS 使用 System V AMD64 ABI,因此依赖于 stack-pointer (see this question) 的 16 字节对齐,简而言之,这意味着 stack-pointer (rsp
) 调用函数时应始终能被 16 整除。
调用 _printf
时,stack-pointer (rsp
) 错位了 8 个字节。这是怎么来的?
我在 this page 上找到了答案,调用 _main
函数将 return 地址(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 上测试
我一直在尝试使用 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
时,出现错误
Segmentation fault: 11
当我删除对 _printf
的调用时,我的代码运行良好。
为什么调用 _printf
会导致分段错误?
我找到了 ABI 调用约定 here,但没有成功调用 C 函数。
我希望打印 Hello World!
,但我得到的是 'Segmentation Fault: 11'。
~~调用前需要设置栈帧_printf
TL;DR: System V AMD64 ABI 要求 stack-pointer 为 16-byte-aligned。在调用 _printf
时,stack-pointer 错位了 8 个字节。
使用 LLDB 调试二进制文件得到:
frame #0: 0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
MacOS 使用 System V AMD64 ABI,因此依赖于 stack-pointer (see this question) 的 16 字节对齐,简而言之,这意味着 stack-pointer (rsp
) 调用函数时应始终能被 16 整除。
调用 _printf
时,stack-pointer (rsp
) 错位了 8 个字节。这是怎么来的?
我在 this page 上找到了答案,调用 _main
函数将 return 地址(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 上测试