Реализация слова «.» из Forth в сборке x86

#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 .)