global _start section .bss BUF_SIZE: equ 64 buf1: resb 64 buf2: resb 64 section .text _start: ; Calling convention of a non leaf function is the same ; as a leaf function mov rdi, 40579 mov rsi, buf1 mov rdx, BUF_SIZE call uint2str ; write result to stdout mov rdx, rax mov rax, 1 mov rdi, 1 mov rsi, buf1 syscall ; Calculate !5 mov rdi, 5 call factorial ; Convert result to string mov rdi, rax mov rsi, buf2 mov rdx, BUF_SIZE call uint2str ; Write !5 to stdout mov rdx, rax mov rax, 1 mov rdi, 1 mov rsi, buf2 syscall ; Exit mov rax, 60 xor rdi, rdi syscall ; size_t uint2str(unsigned number, char * buffer, size_t bufferSize) ; Returns the number of bytes written to the buffer uint2str: push rbp ; Store the rbp register on the stack mov rbp, rsp ; Overwrite rbp with the function local stack pointer ; Backup the remaining callee saved registers push rbx push r12 push r13 push r14 push r15 ; Overwrite the saved registers for demonstration purposes mov r12, rdi ; number mov r13, rsi ; buffer mov r14, rdx ; bufferSize xor r15, r15 ; counter mov rax, r12 ; working copy of number .loop: cmp rax, 0 je .done ; n == 0 cmp r15, r14 jge .done ; i > BUF_SIZE ; n % 10 xor rdx, rdx mov rdi, 10 div rdi ; rax = rax / rdi add dl, '0' ; rdx = rax % rdi mov byte [r13 + r15], dl inc r15 jmp .loop .done: mov byte [r13 + r15], 0x0a ; append newline inc r15 ; Call reverse string routine to fix the order mov rdi, r13 ; buffer lea rsi, [r15 - 1] ; number of characters written, excluding newline call revstr mov rax, r15 ; Restore saved registers pop r15 pop r14 pop r13 pop r12 pop rbx ; restore rsp from rbp mov rsp, rbp pop rbp ; restore rbp ret ; unsigned factorial(unsigned n) ; recursive! factorial: ; save registers push rbp mov rbp, rsp push rbx push r12 push r13 push r14 push r15 mov r12, rdi; n cmp r12, 0 je .zero mov rbx, rdi dec rdi call factorial ; recursion! xor rdx, rdx mul rbx jmp .done .zero: mov rax, 1 ; !0 = 1 .done: ; Restore saved registers pop r15 pop r14 pop r13 pop r12 pop rbx ; restore rsp from rbp mov rsp, rbp pop rbp ; restore rbp ret ; void revstr(char * s, size_t size) revstr: xor r8, r8 ; lowerbound lea r9, [rsi - 1] ; upperbound .loop: cmp r8, r9 jge .done mov cl, byte [rdi + r8] ; tmp = s[lowerbound] xchg cl, byte [rdi + r9] ; tmp <-> s[upperbound] mov byte [rdi + r8], cl ; s[lowerbound] = tmp inc r8 dec r9 jmp .loop .done: ret