segment .data
x       dq      0
scanf_format   db    "%ld",0
printf_format  db    "fact(%ld) = %ld",0x0a,0

        segment .text
        global  main                ; let the linker know about main
        global  fact                ; tell the world about fact
        extern  scanf               ; resolve write and exit from libc
        extern  printf
main:
        push    rbp
        mov     rbp, rsp
        frame   2, 0, 3
        sub     rsp, frame_size
        lea     rcx, [scanf_format] ; set arg 1 for scanf
        lea     rdx, [x]            ; set arg 2 for scanf
        call    scanf
        mov     rcx, [x]            ; move the value of x to rdi for fact call
        call    fact
        lea     rcx, [printf_format]    ; set arg 1 for printf
        mov     rdx, [x]            ; set arg 2 for printf
        mov     r8, rax             ; set arg 3 to be x!
        call    printf
        xor     eax, eax            ; set rax to 0 for return value
        leave
        ret
fact:                               ; recursive factorial function
n       equ     local1
        push    rbp
        mov     rbp, rsp
        frame   1, 1, 1
        sub     rsp, frame_size             ; make room for storing n
        cmp     rcx, 1              ; compare argument with 1
        jg      greater             ; if n <= 1, return 1
        mov     eax, 1              ; set return value to 1
        leave
        ret
greater:
        mov     [rbp+n], rcx        ; save n
        dec     rcx                 ; call fact with n-1
        call    fact
        mov     rcx, [rbp+n]        ; restore original n
        imul    rax, rcx           ; multiply fact(n-1)*n
        leave
        ret