## System V AMD64 ABI (cdecl): шпаргалка Кратко о соглашении вызова для x86-64 в Unix-подобных ОС (Linux, macOS, BSD) по ABI System V. ### Быстрые правила - Аргументы (целые/указатели): RDI, RSI, RDX, RCX, R8, R9; остальные — на стек (справа налево). - Аргументы с плавающей точкой/векторы: XMM0–XMM7; остальные — на стек. - Возврат значения: целые/указатели — RAX (до 128 бит: RAX/RDX); float/double — XMM0 (до двух — XMM0/XMM1). - Перед call: RSP должен быть выровнен по 16 байт. Внутри функции на входе RSP % 16 == 8 (из-за return address). - Red zone: 128 байт под RSP доступны leaf-функциям; не трогается ОС и обработчиками сигналов. - Нет «shadow space» (он есть только в Windows x64 ABI). ### Сохранность регистров - Caller-saved (clobbered): RAX, RCX, RDX, RSI, RDI, R8–R11, XMM0–XMM15, флаги RFLAGS. - Callee-saved (надо сохранять и восстанавливать в функции): RBX, RSP, RBP, R12–R15. ### Порядок передачи аргументов - 1–6-й целочисленные/указательные: RDI, RSI, RDX, RCX, R8, R9. - Вещественные/векторные: XMM0–XMM7 (независимо от целочисленных). - 7-й и далее, а также переполнение по типам — через стек. Компиляторы обычно размещают их с выравниванием по 8/16. ### Вариативные функции (printf и т.п.) - Перед вызовом variadic-функции младший байт RAX (AL) содержит число использованных XMM-регистров для передачи аргументов с плавающей точкой (0, если их нет). ### Структуры и большие значения - Небольшие структуры (до 16 байт) могут возвращаться через регистры (классы INTEGER/SSE распределяются по RAX/RDX или XMM0/XMM1). - Большие структуры возвращаются через скрытый указатель: вызывающий передаёт адрес буфера (sret), а функция заполняет его. ### Типичный каркас функции на NASM (Linux) ; extern printf ; global main ; section .data ; msg db "x=%d", 10, 0 ; section .text ; main: ; push rbp ; mov rbp, rsp ; ; на входе rsp%16==8 → для вызова нужно выровнять до 16 ; sub rsp, 8 ; выравнивание стека перед call ; lea rdi, [rel msg] ; 1-й аргумент (fmt) → RDI ; mov esi, 42 ; 2-й аргумент (int) → ESI ; xor eax, eax ; AL=0: нет XMM-аргументов (variadic правило) ; call printf ; add rsp, 8 ; вернуть выравнивание ; xor eax, eax ; return 0 ; pop rbp ; ret ### Памятка при написании кода - До call: выровняй стек (RSP%16==0), подготовь регистры аргументов, AL для varargs. - После call: результат смотри в RAX/XMM0; считай, что caller-saved испорчены — сохрани важное заранее. - В своей функции сохраняй/восстанавливай RBX, RSP, RBP, R12–R15.