GNU/Linux xterm-256color bash 144 views

// ****************************************************************************
// * Nombre del archivo: practica.s
// * Descripción: Genera numeros primos
// * Autor: Roldan Castro Luis Alberto
// * Fecha: 07-04-2025
// * Plataforma: Raspberry Pi OS (64 bits)
// * Asciinema: https://asciinema.org/a/bMg5LblZenRBmLIoOkPX8nqH0
// ****************************************************************************

// ****************************************************************************
// Version de Python
//
//def es_primo(n):
//    if n < 2:
//        return False
//    if n in (2, 3):
//        return True
//    if n % 2 == 0 or n % 3 == 0:
//        return False
//    i = 5
//    while i * i <= n:
//        if n % i == 0 or n % (i + 2) == 0:
//            return False
//        i += 6
//    return True
//
//def generar_primos(cantidad):
//    primos = []
//    num = 2
//    while len(primos) < cantidad:
//        if es_primo(num):
//            primos.append(num)
//        num += 1
//    return primos
//
//# Solicitar la cantidad de primos al usuario
//cantidad = int(input("¿Cuántos números primos quieres generar? "))
//primos_generados = generar_primos(cantidad)
//print("Números primos generados:", primos_generados)
// ****************************************************************************

.data
    msg_prompt:     .asciz "Ingrese cantidad de primos a generar: "
    len_prompt = . - msg_prompt
    
    msg_prime:      .asciz "Primo #"
    len_prime = . - msg_prime
    
    msg_colon:      .asciz ": "
    len_colon = . - msg_colon
    
    msg_newline:    .asciz "\n"
    len_newline = . - msg_newline
    
    buffer:         .fill 32, 1, 0  // Buffer para conversión numérica
    
.text
    .global _start
    .align 2

_start:
    // Mostrar mensaje inicial
    mov x0, #1
    adr x1, msg_prompt
    mov x2, len_prompt
    mov x8, #64             // syscall write
    svc #0

    // Leer entrada del usuario (número de primos a generar)
    mov x0, #0              // stdin
    adr x1, buffer          // buffer para almacenar entrada
    mov x2, #12             // longitud máxima a leer
    mov x8, #63             // syscall read
    svc #0

    // Convertir ASCII a número (x19 = cantidad de primos)
    mov x19, #0             // inicializar contador
    adr x20, buffer         // dirección del buffer
    mov x21, #10            // base decimal

convert_loop:
    ldrb w22, [x20], #1     // cargar byte y avanzar puntero
    cmp w22, #0xA           // verificar si es newline
    beq convert_done
    sub w22, w22, #'0'      // convertir ASCII a dígito
    madd x19, x19, x21, x22 // x19 = x19 * 10 + dígito
    b convert_loop

convert_done:
    // Inicializar variables para generación de primos
    mov x23, #2             // primer número primo
    mov x24, #0             // contador de primos encontrados

prime_loop:
    // Verificar si es primo (x23 = número a verificar)
    mov x25, #2             // divisor inicial

check_prime:
    cmp x25, x23            // si divisor >= número, es primo
    bge is_prime
    
    udiv x26, x23, x25      // x26 = x23 / x25
    msub x27, x26, x25, x23 // x27 = resto
    cbz x27, not_prime      // si resto == 0, no es primo
    
    add x25, x25, #1        // incrementar divisor
    b check_prime

is_prime:
    // Mostrar el número primo encontrado
    add x24, x24, #1        // incrementar contador de primos
    
    // Mostrar "Primo #"
    mov x0, #1
    adr x1, msg_prime
    mov x2, len_prime
    mov x8, #64
    svc #0
    
    // Mostrar número de secuencia
    mov x0, x24
    bl print_number
    
    // Mostrar ": "
    mov x0, #1
    adr x1, msg_colon
    mov x2, len_colon
    mov x8, #64
    svc #0
    
    // Mostrar número primo
    mov x0, x23
    bl print_number
    
    // Mostrar nueva línea
    mov x0, #1
    adr x1, msg_newline
    mov x2, len_newline
    mov x8, #64
    svc #0
    
    // Verificar si hemos encontrado suficientes primos
    cmp x24, x19
    bge exit_program
    
not_prime:
    add x23, x23, #1        // probar siguiente número
    b prime_loop

exit_program:
    // Salir del programa
    mov x0, #0              // código de salida 0
    mov x8, #93             // syscall exit
    svc #0

// Función para imprimir número (x0 = número a imprimir)
print_number:
    stp x29, x30, [sp, -16]!
    mov x29, sp
    
    adr x1, buffer + 31     // apuntar al final del buffer
    mov w2, #0              // terminador nulo
    
    mov x3, #10             // base decimal

convert_to_ascii:
    udiv x4, x0, x3         // x4 = cociente
    msub x5, x4, x3, x0     // x5 = resto (dígito)
    add x5, x5, #'0'        // convertir a ASCII
    strb w5, [x1], #-1      // almacenar y retroceder
    
    mov x0, x4              // actualizar cociente
    cbnz x0, convert_to_ascii // continuar si cociente != 0
    
    // Calcular longitud
    adr x2, buffer + 31
    sub x2, x2, x1
    add x2, x2, #1
    
    // Imprimir número
    add x1, x1, #1          // ajustar puntero al inicio
    mov x0, #1              // stdout
    mov x8, #64             // syscall write
    svc #0
    
    ldp x29, x30, [sp], 16
    ret