            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