From 26379ad01fab04b78200c8e3d976397c8b69c53d Mon Sep 17 00:00:00 2001 From: Tijmen van Nesselrooij Date: Tue, 13 Aug 2019 18:59:36 +0200 Subject: [PATCH] non leaf function tutorial added --- x86_64/5_nonleaf.asm | 163 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 x86_64/5_nonleaf.asm diff --git a/x86_64/5_nonleaf.asm b/x86_64/5_nonleaf.asm new file mode 100644 index 0000000..c61bee0 --- /dev/null +++ b/x86_64/5_nonleaf.asm @@ -0,0 +1,163 @@ +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