GNU/Linux xterm-256color bash 148 views

// ****************************************************************************
// * Nombre del archivo: practica.s
// * Descripción: Calcular la suma de los números primos que se encuentran en las posiciones de la secuencia de  Fibonacci
// * Autor: Roldan Castro Luis Alberto
// * Fecha: 08-04-2025
// * Plataforma: Raspberry Pi OS (64 bits)
// * Asciinema: https://asciinema.org/a/nEqGXpPsbIHAhcztKUPyk3tLH
// ****************************************************************************

// ****************************************************************************
// Version en python
//
//# Función para verificar si un número es primo
//def is_prime(num):
//    if num < 2:
//        return False
//    for i in range(2, int(num ** 0.5) + 1):
//        if num % i == 0:
//            return False
//    return True
//
//# Función para generar la secuencia de Fibonacci hasta N
//def generate_fibonacci(N):
//    fibs = [0, 1]
//    for i in range(2, N):
//        fibs.append(fibs[i - 1] + fibs[i - 2])
//    return fibs
//
//# Función para convertir un número a una cadena (para mostrar)
//def number_to_string(num):
//    return str(num)
//
//# Función principal
//def main():
//    # Solicitar al usuario el número N
//    N = int(input("Ingresa un número: "))
//    
//    # Generar la secuencia de Fibonacci hasta N
//    fibonacci = generate_fibonacci(N)
//    
//    # Sumar los términos en posiciones primas
//    total_sum = 0
//    for i in range(2, N):  # Comienza desde 2 porque los primeros números (0, 1) no son primos
//        if is_prime(i):
//            total_sum += fibonacci[i]
//    
//    # Mostrar el resultado
//    print(f"Suma de Fibonacci en posiciones primas: {number_to_string(total_sum)}")
//
//if __name__ == "__main__":
//    main()
// ****************************************************************************

.section .data
msg_input: .ascii "Ingresa las posiciones: "
len_input = . - msg_input

msg_result: .ascii "Suma de Fibonacci en posiciones primas: \n"
len_result = . - msg_result

newline: .ascii "\n"    // Salto de línea
len_newline = . - newline

.section .bss
buffer: .skip 16          // espacio para entrada del usuario
fibs: .skip 8 * 64        // espacio para hasta 64 términos
result: .skip 8           // acumulador de la suma

.section .text
.global _start

_start:
    // Mostrar mensaje de entrada
    ldr x0, =msg_input
    mov x1, #len_input
    bl print_msg

    // Leer número desde consola
    mov x0, #0          // stdin
    ldr x1, =buffer
    mov x2, #16
    mov x8, #63         // syscall read
    svc #0

    // Convertir a número
    ldr x1, =buffer
    bl atoi             // devuelve número en x0
    mov x21, x0         // guardar N en x21

    // Generar Fibonacci hasta N
    mov x0, #0
    ldr x1, =fibs
    str x0, [x1], #8     // fib[0] = 0

    mov x0, #1
    str x0, [x1], #8     // fib[1] = 1

    mov x2, #2
gen_fib_loop:
    cmp x2, x21
    bge done_fib

    sub x4, x2, #1
    sub x5, x2, #2
    ldr x6, =fibs
    ldr x7, [x6, x4, LSL #3]
    ldr x8, [x6, x5, LSL #3]
    add x9, x7, x8
    str x9, [x6, x2, LSL #3]

    add x2, x2, #1
    b gen_fib_loop

done_fib:
    // Sumar solo los términos en posiciones primas
    mov x19, #0       // acumulador
    mov x20, #1       // posición

sum_loop:
    cmp x20, x21
    bgt end_prog

    mov x0, x20
    bl is_prime
    cbz x0, not_prime

    // Sumar fib[x20] a x19
    ldr x1, =fibs
    ldr x2, [x1, x20, LSL #3]
    add x19, x19, x2

not_prime:
    add x20, x20, #1
    b sum_loop

end_prog:
    // Mostrar mensaje
    ldr x0, =msg_result
    mov x1, #len_result
    bl print_msg

    // Convertir x19 a ASCII y mostrar
    mov x0, x19
    bl print_number

    // Imprimir salto de línea
    ldr x0, =newline        // Cargar el salto de línea
    mov x1, #len_newline    // Longitud del salto de línea
    bl print_msg            // Imprimir salto de línea

    // Salir
    mov x8, #93
    mov x0, #0
    svc #0

// ------------ Funciones auxiliares ------------

// print_msg(x0 = ptr, x1 = len)
print_msg:
    mov x2, x1
    mov x1, x0
    mov x0, #1      // stdout
    mov x8, #64     // syscall write
    svc #0
    ret

// atoi(x1 = ptr a buffer) -> x0 = número
atoi:
    mov x0, #0
    mov x3, #10
atoi_loop:
    ldrb w2, [x1], #1
    cmp w2, #'0'
    blt atoi_done
    cmp w2, #'9'
    bgt atoi_done
    sub w2, w2, #'0'
    mul x0, x0, x3
    add x0, x0, x2
    b atoi_loop
atoi_done:
    ret

// is_prime(x0) -> x0 = 1 si es primo, 0 si no
is_prime:
    cmp x0, #2
    blt not_prime_ret
    mov x1, #2
prime_check_loop:
    mul x2, x1, x1
    cmp x2, x0
    bgt prime_yes
    udiv x3, x0, x1
    msub x4, x3, x1, x0
    cbz x4, not_prime_ret
    add x1, x1, #1
    b prime_check_loop
prime_yes:
    mov x0, #1
    ret
not_prime_ret:
    mov x0, #0
    ret

// print_number(x0 = número a imprimir)
print_number:
    mov x1, x0          // número original
    mov x2, #10         // divisor
    ldr x3, =buffer
    add x3, x3, #15     // apuntar al final
    mov x4, #0

print_num_loop:
    udiv x5, x1, x2
    msub x6, x5, x2, x1
    add x6, x6, #'0'
    strb w6, [x3], #-1
    mov x1, x5
    add x4, x4, #1
    cbz x1, print_num_done
    b print_num_loop

print_num_done:
    add x3, x3, #1
    mov x0, #1      // stdout
    mov x1, x3
    mov x2, x4
    mov x8, #64     // syscall write
    svc #0
    ret