/*
Autor: Victor Manuel Madrid Lugo
Fecha: 08/04/2025
Descripción: Calcula la secuencia Fibonacci hasta un límite ingresado por el usuario
Demostración: [https://asciinema.org/a/wsOJ9BAXA8rFC7QANIxGeLykN]
*/
/*
# Programa Fibonacci en Python
def fibonacci():
n = int(input("Ingrese el número de términos Fibonacci a generar: "))
if n <= 0:
print("Error: Debe ingresar un número positivo.")
return
a, b = 0, 1
print(a, end=' ')
if n == 1:
print()
return
print(b, end=' ')
for _ in range(2, n):
c = a + b
print(c, end=' ')
a, b = b, c
print() # Nueva línea al final
fibonacci()
*/
.section .data
msg_prompt: .asciz "Ingrese el número de términos Fibonacci: "
msg_error: .asciz "Error: Entrada inválida (debe ser ≥1)\n"
msg_space: .asciz " "
msg_newline: .asciz "\n"
buffer: .skip 32 // Buffer ampliado para entrada
.section .text
.global _start
_start:
// Solicitar entrada
mov x0, #1
ldr x1, =msg_prompt
mov x2, #42 // Longitud exacta del mensaje
mov x8, #64 // syscall write
svc #0
// Leer entrada
mov x0, #0
ldr x1, =buffer
mov x2, #32 // Tamaño del buffer
mov x8, #63 // syscall read
svc #0
// Convertir a entero
ldr x0, =buffer
bl atoi
mov x19, x0 // Guardar n términos en x19
// Validar entrada (n ≥ 1)
cmp x19, #1
b.ge init_fib
mov x0, #1
ldr x1, =msg_error
mov x2, #33 // Longitud del mensaje error
mov x8, #64
svc #0
b exit
init_fib:
// Inicializar Fibonacci
mov x20, #0 // F(0) = 0
mov x21, #1 // F(1) = 1
mov x22, #1 // Contador
// Imprimir F(0)
mov x0, x20
bl print_num
bl print_space
// Si solo quiere 1 término
cmp x19, #1
b.eq finish
// Imprimir F(1)
mov x0, x21
bl print_num
bl print_space
fib_loop:
// Calcular siguiente término
add x23, x20, x21 // F(n) = F(n-1) + F(n-2)
// Imprimir término actual
mov x0, x23
bl print_num
bl print_space
// Actualizar valores
mov x20, x21
mov x21, x23
// Incrementar contador
add x22, x22, #1
cmp x22, x19
b.lt fib_loop
finish:
bl print_newline
exit:
// Salir correctamente
mov x0, #0
mov x8, #93
svc #0
// ========== FUNCIONES AUXILIARES (CORREGIDAS) ==========
// atoi: Convierte string a entero (maneja errores)
atoi:
mov x1, #0 // Resultado
mov x3, #10 // Base 10
mov x4, #0 // Signo (0=positivo)
// Primer carácter
ldrb w2, [x0], #1
cmp w2, #'-'
b.ne check_digit
mov x4, #1 // Es negativo
ldrb w2, [x0], #1 // Siguiente carácter
check_digit:
// Verificar si es dígito
cmp w2, #'0'
b.lt atoi_error
cmp w2, #'9'
b.gt atoi_error
atoi_loop:
// Convertir y acumular
sub w2, w2, #'0'
mul x1, x1, x3
add x1, x1, x2
// Siguiente carácter
ldrb w2, [x0], #1
cmp w2, #10 // Salto de línea
b.eq atoi_done
cmp w2, #0 // Null terminator
b.eq atoi_done
// Verificar dígito
cmp w2, #'0'
b.lt atoi_error
cmp w2, #'9'
b.gt atoi_error
b atoi_loop
atoi_done:
// Aplicar signo
cbz x4, atoi_ok
neg x1, x1
atoi_ok:
mov x0, x1
ret
atoi_error:
mov x0, #-1 // Valor de error
ret
// print_num: Imprime número en x0 (Versión corregida)
print_num:
stp x29, x30, [sp, #-32]! // Ajuste de alineación a 16 bytes
mov x29, sp
// Buffer local (19 dígitos para 64 bits + signo + null)
sub sp, sp, #20
mov x1, sp
// Manejo especial para 0
cbz x0, print_zero
// Manejar negativos
cmp x0, #0
b.gt positive
neg x0, x0
mov w2, #'-'
strb w2, [x1], #1
positive:
mov x2, #10
mov x3, #0 // Contador dígitos
digit_loop:
udiv x4, x0, x2 // Dividir por 10
msub x5, x4, x2, x0 // Obtener residuo
add x5, x5, #'0' // ASCII
strb w5, [x1, x3] // Almacenar
add x3, x3, #1
mov x0, x4
cbnz x0, digit_loop
// Invertir dígitos
mov x4, #0 // Inicio
sub x5, x3, #1 // Fin
reverse:
cmp x4, x5
b.ge print
ldrb w6, [x1, x4]
ldrb w7, [x1, x5]
strb w7, [x1, x4]
strb w6, [x1, x5]
add x4, x4, #1
sub x5, x5, #1
b reverse
print_zero:
mov w2, #'0'
strb w2, [x1]
mov x3, #1
print:
// Imprimir
mov x0, #1 // stdout
sub x1, x1, x3 // Ajustar puntero
add x3, x3, #1 // Incluir posible signo
mov x2, x3 // Longitud
mov x8, #64 // write
svc #0
// Restaurar stack
add sp, sp, #20
ldp x29, x30, [sp], #32
ret
print_space:
stp x29, x30, [sp, #-16]!
mov x0, #1
ldr x1, =msg_space
mov x2, #1
mov x8, #64
svc #0
ldp x29, x30, [sp], #16
ret
print_newline:
stp x29, x30, [sp, #-16]!
mov x0, #1
ldr x1, =msg_newline
mov x2, #1
mov x8, #64
svc #0
ldp x29, x30, [sp], #16
ret