~~ Вам необходимо установить кадр стека перед вызовом _printf
TL; DR: Системный V AMD64 ABI требует, чтобы указатель стека был выровнен по 16 байтов. Ко времени вызова _printf
указатель стека смещается на 8 байт.
Отладка двоичного файла с помощью LLDB дает:
frame # 0: 0x00007fff527d430a libdyld.dylib`stack_not_16_byte_aligned_error
MacOS использует ABI System V AMD64 и поэтому использует 16-байтовое выравнивание для указателя стека ( см. Этот вопрос ), короче говоря, это означает, что указатель стека (rsp
) должен всегда делится на 16 при вызове функции.
Ко времени вызова _printf
указатель стека (rsp
) смещается на 8 байтов. Как это случилось?
Я нашел ответ на этой странице , вызов функции _main
помещает адрес возврата (8 байт) в стек и, следовательно, смещает его.
Моя первоначальная идея - установка фрейма стека - поместила еще один адрес в стек, и поэтому rsp
снова делился на 16.
Однако более простое решение будет просто 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