|
| 1 | +; https://nasm.us/ |
| 2 | + |
| 3 | +; ==================================================================== |
| 4 | +; Ejercicio 06 - Recursividad |
| 5 | +; ==================================================================== |
| 6 | +; |
| 7 | +; Simplemente aclarar que existen dos tipos de recursividad: Directa e Indirecta. |
| 8 | +; La recursividad directa se da cuando una función se llama a sí misma, y la recursividad indirecta se da cuando una función A llama a una función B |
| 9 | +; que a su vez llama a la función A. |
| 10 | + |
| 11 | + |
| 12 | +SYS_read: equ 0 |
| 13 | +SYS_write: equ 1 |
| 14 | +SYS_exit: equ 60 |
| 15 | +STDIN: equ 0 |
| 16 | +STDOUT: equ 1 |
| 17 | +STDERR: equ 2 |
| 18 | + |
| 19 | + |
| 20 | +global _start |
| 21 | +extern printf |
| 22 | +section .text |
| 23 | + |
| 24 | +_start: |
| 25 | + mov rdi, 100 |
| 26 | + call recursion1 |
| 27 | + |
| 28 | + lea rdi, [LF] |
| 29 | + call printf |
| 30 | + lea rdi, [LF] |
| 31 | + call printf |
| 32 | + |
| 33 | +%define FIB_ELEM 30 |
| 34 | + mov rdi, FIB_ELEM |
| 35 | + call fibonacci |
| 36 | + mov rdx, rax |
| 37 | + mov rsi, FIB_ELEM |
| 38 | + lea rdi, [fibonacci_mask] |
| 39 | + call printf |
| 40 | + |
| 41 | +%define FACT_NUM 10 |
| 42 | + mov rdi, FACT_NUM |
| 43 | + call factorial |
| 44 | + mov rdx, rax |
| 45 | + mov rsi, FACT_NUM |
| 46 | + lea rdi, [factorial_mask] |
| 47 | + call printf |
| 48 | + |
| 49 | +_exit: |
| 50 | + mov rax, SYS_exit |
| 51 | + xor rdi, rdi |
| 52 | + syscall |
| 53 | + |
| 54 | +; En esta función, primero preparamos el stack para poder hacer el CALL tanto a printf, como a la próxima iteración |
| 55 | +; de recursion1. |
| 56 | +; En ensamblador, es necesario que es stack esté alineado a 16 bytes, y cada vez que se usa CALL, el stack se desalinea |
| 57 | +; puesto que CALL guarda en el stack la dirección de retorno, y por consiguiente, se le resta 8 bytes a RSP. |
| 58 | +; Como en este caso tenemos dos llamadas, el stack sigue alineado, pero nesecitamos crear un "STACK FRAME", para que cada llamada |
| 59 | +; guarde su punto de regreso sin corromper el punto guardado por la llamada anterior. |
| 60 | +recursion1: |
| 61 | + push rbp |
| 62 | + mov rbp, rsp |
| 63 | + sub rsp, 16 |
| 64 | + mov rcx, rdi |
| 65 | + mov [rbp - 16], rcx |
| 66 | + lea rdi, [printf_mask] |
| 67 | + mov rsi, rcx |
| 68 | + call printf |
| 69 | + mov rcx, [rbp - 16] |
| 70 | + dec rcx |
| 71 | + mov rdi, rcx |
| 72 | + test rcx, rcx |
| 73 | + jz .done |
| 74 | + call recursion1 |
| 75 | +.done: |
| 76 | + add rsp, 16 |
| 77 | + pop rbp |
| 78 | + ret |
| 79 | + |
| 80 | +; RDI: posición del elemento de la sucesión de Fibonacci a calcular. |
| 81 | +; NOTA: esta función es muy lenta. Se puede optimizar bastante puesto que para cada recursión calcula |
| 82 | +; todos los numeros de fibonacci anteriores. |
| 83 | +fibonacci: |
| 84 | + push rbp |
| 85 | + mov rbp, rsp |
| 86 | + sub rsp, 32 |
| 87 | + mov [rbp - 32], rdi |
| 88 | + |
| 89 | + cmp rdi, 1 |
| 90 | + mov rax, rdi |
| 91 | + jle .return |
| 92 | + sub rdi, 1 |
| 93 | + call fibonacci |
| 94 | + mov [rbp - 16], rax |
| 95 | + mov rdi, [rbp - 32] |
| 96 | + sub rdi, 2 |
| 97 | + call fibonacci |
| 98 | + add rax, [rbp - 16] |
| 99 | + jmp .return |
| 100 | +.return: |
| 101 | + add rsp, 32 |
| 102 | + pop rbp |
| 103 | + ret |
| 104 | + |
| 105 | +; RDI: el número del cual se va a calcular el factorial. |
| 106 | +factorial: |
| 107 | + push rbp |
| 108 | + mov rbp, rsp |
| 109 | + sub rsp, 32 |
| 110 | + mov [rbp - 32], rdi |
| 111 | + cmp rdi, 1 |
| 112 | + jg .calculate |
| 113 | + mov rax, 1 |
| 114 | + jmp .return |
| 115 | +.calculate: |
| 116 | + dec rdi |
| 117 | + call factorial |
| 118 | + inc rdi |
| 119 | + mul rdi |
| 120 | + jmp .return |
| 121 | +.return: |
| 122 | + add rsp, 32 |
| 123 | + pop rbp |
| 124 | + ret |
| 125 | + |
| 126 | +section .data |
| 127 | + printf_mask: db "%d ", 0x00 |
| 128 | + fibonacci_mask: db "El elemento [%d] de fibonacci es: %d", 0x0A, 0x00 |
| 129 | + factorial_mask: db "El factorial de [%d] es: %d", 0x0A, 0x00 |
| 130 | + LF: db 0x0A, 0x00 |
| 131 | + |
| 132 | +section .bss |
0 commit comments