Jan Wolfram
Jan Wolfram

Reputation: 184

Why do I have a segmentation fault in recursive assembly function?

Hi I write a Fibonacci recursive code in assembly with the amd64 abi calling convention, but I always get segmentation fault :/ I compile it with:

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

ld -o fibo fibo.o

./fibo

I have no compiling errors but a segmentation error, so I guess something went wrong with my Stackframes.

Thanks for any help :)

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


Upvotes: 0

Views: 343

Answers (1)

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32732

You set up the stack frame in f correctly, but then you start going wrong with the addition to rbp. You should leave rbp alone, and add the offset on the variable fetch instead:

push rdi
move rdi,[rbp+16]

You exit sequence is wrong. The addition of 16 to rbp in the entry is a problem here (resolved by not changing rbp) and you have the rsp restoration in the wrong place.

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

However, since you never change rsp to allocate storage for local variables, the move to rsp is unnecessary and can be omitted.

Note that there are other issues with the code not related to the entry/exit sequence and crash.

Upvotes: 2

Related Questions