Почему у меня возникает ошибка сегментации в рекурсивной функции сборки?

Привет, я пишу рекурсивный код Фибоначчи в сборке с соглашением о вызовах amd64 abi, но всегда получаю ошибку сегментации:/ Я компилирую его с помощью:

nasm -f elf64 -o fibo.o fibonacci.asm

ld -o fibo fibo.o

./fibo

У меня нет ошибок компиляции, но есть ошибка сегментации, поэтому я думаю, что что-то пошло не так с моими Stackframes.

Спасибо за любую помощь:)

SECTION .data

; define the fibonacci number that should be calculated
n:      dq   10

SECTION .text

global _start

_start:
    ; call Fibonacci function f(n)
    mov     rdi, [n]    ; parameter: fibonacci number to calculate
    call    f           ; call function

    ; print calculated Fibonacci number on stdout
    ;call    printnumber

    ; exit process with exit code 0
    mov     rax, 60
    mov     rdi, 0
    syscall

; f: Calculates a Fibonacci number
;   f(n) = {n, if n<=1; f(n-1)+f(n-2), else}.
;   Parameter: Integer n >= 0, passed on stack
;   Returns:   Fibonacci number f(n), returned in rax
f:
    push rbp            ; neuen stackframe
    mov rbp, rsp        
    push rdi            ; rdi auf stack speichern
    add rbp, 16         ; 
    mov rdi, [rbp]      ; rdi = parameter

    cmp rdi, 1          ; check for base case
    jle base            ; n <= 1

    dec  rdi            ; n-1
    push rdi
    call f              ; f(n-1)
    pop rdi

    dec  rdi            ; n-2
    push rdi
    call f              ; f(n-2)
    pop rdi
    pop rdi
    add rax, rdi

    jmp end
base: 
    mov rax, 1

end:
    pop rdi
    pop rbp
    mov rsp, rbp

    ret


1 ответ

Вы устанавливаете фрейм стека в f правильно, но затем вы начинаете ошибаться с добавлением rbp. Ты должен уйтиrbp в одиночку и вместо этого добавьте смещение к выборке переменной:

push rdi
move rdi,[rbp+16]

Вы выходите из неправильной последовательности. Добавление 16 к rbp в записи является проблемой здесь (решается без изменения rbp), и у вас естьrsp восстановление в неположенном месте.

pop rdi
mov rsp,rbp    ; Unnecessary here (see below)
pop rbp
ret

Однако, поскольку вы никогда не меняетесь rsp чтобы выделить хранилище для локальных переменных, перейдите к rsp не является необходимым и может быть опущено.

Обратите внимание, что есть другие проблемы с кодом, не связанные с последовательностью входа / выхода и сбоя.

Другие вопросы по тегам