#macos #printf #x86-64 #memory-alignment #forth
#macos #printf #x86-64 #выравнивание памяти #далее
Вопрос:
Я пытаюсь создать функцию, которая выводит число на экран. В конце концов, я сделаю так, чтобы он мог брать верхний элемент стека, печатать его, а затем вставлять (например, слово «.» в Forth). Но пока я стараюсь сделать это простым. Я думаю, что мне нужно каким-то образом выровнять стек вызовов — и я подумал, что нажатие и нажатие произвольного регистра до и после вызова printf (rbx) сделает свое дело — но я все еще получаю ошибку сегментации. Обратная трассировка в GDB также не помогла мне добиться какого-либо прогресса. Кто-нибудь знает, почему этот код вызывает ошибку сегментации и как это исправить?
Как я собираю (GAS): gcc -masm=intel
.data
format_num: .ascii "%d"
.text
.global _main
.extern _printf
print_num:
push rbx
lea rdi, format_num[RIP]
mov esi, 250
xor eax, eax
call _printf
pop rbx
ret
_main:
call print_num
mov rdi, 0
mov rax, 0x2000001
syscall
Комментарии:
1. В
_main
, вы не выровняли стек перед вызовомprint_num
.2. @NateEldredge Я новичок в сборке, как мне это сделать?
3. Так же, как и в
print_num
: введите произвольный регистр.4. Вы можете отслеживать, мысленно просматривая код. При входе в любую функцию, вызываемую соответствующим кодом, совместимым с ABI, указатель стека будет нечетным кратным 8. Вы должны убедиться, что то же самое верно для любой вызываемой вами функции C, что означает
rsp
, что оно должно быть четным кратным 8 за мгновение до выполненияcall
. Каждыйpush, pop, call, ret
добавляет или вычитает 8 и, таким образом, переключает вас между четным и нечетным.5. @NateEldredge: или завершающий вызов printf с
jmp _printf
помощью вместо push / call / pop / ret . Затем вы вводите_printf
с допустимым макетом стека, точно таким же, какой ваша функция получила при вводе. (Если OP хочет использовать callstack в качестве стека Forth, они могут отказаться от выравнивания стека, за исключением редких случаев, когда они хотят выполнять вызовы библиотечных функций, а затем сохранить RSP, сделав RBP указателем фрейма /and rsp, -16
/call
/leave
/ret
.)