0

I am trying to print out every fibonacci number in assembly with a printf implementation. But I keep getting a segmentation fault everytime the Instruction Pointer reaches call printf. I have already used printf in a few other files but for some reason it throws an error in this one. I have already debugged the file with GDB and it throws the error when call printf is reached.

I have also tried removing anything that pushes anything onto the stack, but alas this also did not work.

Execution: nasm -felf64 fib.asm && gcc -no-pie fib.o && ~/a.out

Architecture: Linux x86_64

Code:

        global  main
        extern  printf

        section .data
formatStr:
        dd "%i",0xA,0

        section .text
main:   
        push    rbx             ; Push default RBX
        push    rbp             ; Push Base Pointer
        mov     rbp,rsp
        sub     rsp,32          ; Reverse 32 Bytes for local variables

        mov     rax,0           ; A
        mov     rbx,1           ; B
        mov     rcx,1           ; Counter
fib:    
        mov     rdx,rbx         ; Temp = A
        add     rbx,rax         ; A += B
        mov     rax,rdx         ; B = Temp

        mov     QWORD[rbp-8],rax
        mov     QWORD[rbp-16],rbx
        mov     QWORD[rbp-24],rcx

        mov     rdi,formatStr
        mov     rsi,rbx
        xor     rax,rax
        call    printf

        mov     rax,QWORD[rbp-8]
        mov     rbx,QWORD[rbp-16]
        mov     rcx,QWORD[rbp-24]

        dec     rcx
        jnz     fib

        ; Exit Program
        mov     rsp,rbp ; Return to Base Pointer
        pop     rbp     ; Get Ret Address
        pop     rbx     ; Get Default RBX
        ret

Debugger Image:

gdb

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Yukera
  • 71
  • 5
  • 1
    Apparently newer builds of glibc include compiler-generated code that depend on the ABI-guaranteed 16-byte stack alignment on calls to printf, not just scanf. You have an even number of pushes, and `sub` an even multiple of 8 bytes from RSP, so the stack stays misaligned. Use `layout asm` or `disas` to see the faulting instruction in `__GI__tcgetattr`. – Peter Cordes Sep 05 '21 at 00:37
  • @PeterCordes I don't understand, I just commented out every push/sub from RSP, and added an `sub rsp,8 & add rsp,8`. What is the difference between doing this and doing `sub rsp,32`? EDIT: I think I get it, I'm misaligned on 16 instead of 8. But still, how am I supposed to know this information beforehand? – Yukera Sep 05 '21 at 00:48
  • Your own caller follows the same rules: RSP was aligned by 16 before a `call main` pushed a return address. On function entry, RSP%16 == 8. – Peter Cordes Sep 05 '21 at 01:02
  • @Yukera If you really want an answer, I suggest "Introduction to assembly language programming" 2nd edition "Springer" PDF book, thank me later because getting downvoted is easier than getting an answer. – metablaster Sep 05 '21 at 06:34
  • @metablaster I'll go give it a read, it looks pretty interesting. Thanks! – Yukera Sep 05 '21 at 11:31

0 Answers0