            segment .data
    x       dq      0
    prompt: db     "Enter n: ",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
    ;
    ;       printf("Enter n: ");
    ;
            segment .text
            lea     rdi, [prompt]      ; set arg 1 for printf
            xor     eax, eax            ; 0 float parameters
            call    printf
    ;
    ;       scanf("%ls", x);
    ;
            lea     rdi, [scanf_format] ; set arg 1 for scanf
            lea     rsi, [x]            ; set arg 2 for scanf
            xor     eax, eax            ; set rax to 0 (2 byte instruction)
            call    scanf

    ;
    ;       printf("fact(%ld) = %ld\n",x,fact(x));
    ;
            mov     rdi, [x]            ; move the value of x to rdi for fact call
            call    fact
            lea     rdi, [printf_format]    ; set arg 1 for printf
            mov     rsi, [x]            ; set arg 2 for printf
            mov     rdx, rax            ; set arg 3 to be x!
            xor     eax, eax            ; set rax to 0
            call    printf

    ;
    ;       return 0
    ;
            xor     eax, eax            ; set rax to 0 for return value
            leave
            ret

    ;   long fact ( long n )
    ;
    fact:                               ; recursive factorial function
    n       equ     local1
            push    rbp
            mov     rbp, rsp
            frame   1, 1, 1             ; need 1 local variable
            sub     rsp, frame_size
    ;
    ;       if ( n < 1 ) return 1;
    ;
            cmp     rdi, 1              ; compare argument with 1
            jg      greater             ; if n <= 1, return 1
            mov     eax, 1              ; set return value to 1
            leave
            ret
    ;
    ;       else return fact(n-1) * n;
    ;
    greater:
            mov     [rbp+n], rdi        ; save n
            dec     rdi                 ; call fact with n-1
            call    fact
            mov     rdi, [rsp+n]        ; restore original n
            imul    rax, rdi           ; multiply fact(n-1)*n
            leave
            ret