GNU/Linux xterm bash 92 views

📌 Demostración: Generador de números primos hasta n número en ARM64 Assembly

💻 Lenguajes de Interfaz en TECNM Campus ITT
👨‍💻 Autor: Alejandro Suarez Sandoval
📅 Fecha: 2025/04/09

🎯 Descripción

Este programa genera números primos hasta n número y los muestra en la terminal.
La implementación se realiza en:

Assembly ARM64 para RaspbianOS en Raspberry Pi

🔧 Compilación en Raspberry Pi (ARM64)

as generador-primos.s -o generador-primos.o  
ld generador-primos.o -o generador-primos

▶️ Ejecución

./generador-primos

👀 Código fuente

🔗 Código fuente en Gist: Programa 30 Generador de numeros primos hasta n numero Código Assembly ARM64 para RaspbianOS

/*
 ______  ____               ____  __ __      
/\  _  \/\  _`\   /'\_/`\  /'___\/\ \\ \     
\ \ \L\ \ \ \L\ \/\      \/\ \__/\ \ \\ \    
 \ \  __ \ \ ,  /\ \ \__\ \ \  _``\ \ \\ \_  
  \ \ \/\ \ \ \\ \\ \ \_/\ \ \ \L\ \ \__ ,__\
   \ \_\ \_\ \_\ \_\ \_\\ \_\ \____/\/_/\_\_/
    \/_/\/_/\/_/\/ /\/_/ \/_/\/___/    \/_/  
                                             
♡ ∩_∩ 
(„• ֊ •„)♡
| ̄U U ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| 
| • Lenguajes de Interfaz en TECNM Campus ITT                            |   
| • Autor: Alejandro Suarez Sandoval                                     | 
| • Fecha: 2025/04/09                                                    | 
| • Descripción: Programa que genera numeros primos hasta n              | 
|   numero en Ruby y Assembly ARM64 para RaspbianOS.                     | 
| • Demostración:                                                        |
|   https://asciinema.org/a/713735                                       |
| • Compilación (Raspberry Pi ARM64):                                    |  
|     as generador_primos.s -o generador_primos.o                        |  
|     ld generador_primos.o -o generador_primos                          |  
| • Ejecución: ./generador_primos                                        |  
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄                                        

⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════•°• Demostración Código en lenguaje Ruby •°•═══════

def es_primo?(numero)
  return false if numero <= 1
  return true if numero <= 3
  
  return false if numero % 2 == 0 || numero % 3 == 0
  
  i = 5
  w = 2
  
  while i * i <= numero
    return false if numero % i == 0
    i += w
    w = 6 - w 
  end
  
  true
end

def encontrar_primos_hasta(n)
  (2..n).select { |num| es_primo?(num) }
end

n = 100

puts "Números primos hasta #{n}:"
primos = encontrar_primos_hasta(n)
puts primos.join(' ')

════════════════════•°• ☆ •°•══════════════════════════════
/*

/* ⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════════•°• Código en ARM64 Assembly •°•═════════════ */

.global _start      // Punto de entrada global

.data
// Valor máximo hasta el que buscar números primos
n_value:
    .word 100      // Buscar primos hasta este número

// Mensajes
msg_intro:
    .ascii "Números primos hasta "
msg_intro_len = . - msg_intro

msg_colon:
    .ascii ":\n"
msg_colon_len = . - msg_colon

space:
    .ascii " "
space_len = . - space

newline:
    .ascii "\n"
newline_len = . - newline

// Búfer para convertir números a texto
buffer:
    .skip 20

.text
_start:
    // Cargar el valor N
    adr x19, n_value
    ldr w19, [x19]       // w19 = valor máximo N

    // Mostrar mensaje introductorio
    mov x0, #1           // stdout
    adr x1, msg_intro
    mov x2, #msg_intro_len
    mov x8, #64          // syscall write
    svc #0

    // Mostrar el valor N
    mov x24, x19
    bl num_to_ascii
    
    // Mostrar dos puntos y nueva línea
    mov x0, #1
    adr x1, msg_colon
    mov x2, #msg_colon_len
    mov x8, #64
    svc #0

    // Empezar a generar primos desde 2
    mov w20, #2          // w20 = contador actual (comienza en 2)

prime_loop:
    // Si contador > N, termina
    cmp w20, w19
    b.gt end_prime_loop

    // Verificar si el número actual es primo
    mov x24, x20         // Pasar número actual como parámetro
    bl is_prime

    // Si w0 = 1, el número es primo, mostrarlo
    cmp w0, #1
    b.ne not_prime

    // Es primo, mostrar número
    mov x24, x20
    bl num_to_ascii

    // Mostrar espacio
    mov x0, #1
    adr x1, space
    mov x2, #space_len
    mov x8, #64
    svc #0

not_prime:
    // Incrementar contador y continuar
    add w20, w20, #1
    b prime_loop

end_prime_loop:
    // Mostrar nueva línea final
    mov x0, #1
    adr x1, newline
    mov x2, #newline_len
    mov x8, #64
    svc #0
    
    // Salir del programa
    mov x0, #0
    mov x8, #93          // syscall exit
    svc #0

// Subrutina para verificar si un número es primo
// Entrada: x24 = número a verificar
// Salida: w0 = 1 si es primo, 0 si no lo es
is_prime:
    // Si el número es <= 1, no es primo
    cmp w24, #1
    b.le not_prime_ret

    // Si el número es 2 o 3, es primo
    cmp w24, #3
    b.le is_prime_ret

    // Verificar si es divisible por 2
    and w0, w24, #1          // w0 = n % 2
    cmp w0, #0
    b.eq not_prime_ret       // Si es par (excepto 2), no es primo

    // Comprobar divisibilidad desde 3 hasta sqrt(n) en pasos de 2
    mov w21, #3              // w21 = divisor de prueba

check_divisibility:
    // Calcular aproximadamente si divisor > sqrt(n)
    mul w22, w21, w21        // w22 = divisor^2
    cmp w22, w24             // Comparar con n
    b.gt is_prime_ret        // Si divisor^2 > n, es primo

    // Comprobar si n es divisible por el divisor actual
    sdiv w22, w24, w21       // w22 = n / divisor
    mul w22, w22, w21        // w22 = (n / divisor) * divisor
    cmp w22, w24             // Si w22 == w24, entonces n es divisible por divisor
    b.eq not_prime_ret       // No es primo

    // Incrementar divisor en 2 y comprobar siguiente
    add w21, w21, #2
    b check_divisibility

is_prime_ret:
    mov w0, #1               // Es primo
    ret

not_prime_ret:
    mov w0, #0               // No es primo
    ret

// Subrutina para convertir número a ASCII y mostrarlo
num_to_ascii:
    // Preparar para convertir el número a texto
    mov x25, x24           // Copiar número a x25
    adr x26, buffer        // x26 = puntero al búfer
    add x26, x26, #19      // Empezar desde el final del búfer
    mov x27, #10           // x27 = base 10 para división
    
    // Caso especial si el número es 0
    cbnz x25, convert_loop
    mov w28, '0'           // Carácter ASCII '0'
    strb w28, [x26]
    sub x26, x26, #1
    b end_convert

convert_loop:
    // Comprobar si el número es 0
    cbz x25, end_convert
    
    // Obtener el último dígito (número % 10)
    udiv x28, x25, x27     // x28 = x25 / 10
    msub x29, x28, x27, x25 // x29 = x25 - (x28 * 10) = x25 % 10
    
    // Convertir dígito a ASCII y guardarlo
    add w29, w29, #'0'     // Convertir a carácter ASCII
    strb w29, [x26]        // Guardar en búfer
    sub x26, x26, #1       // Mover puntero
    
    // Actualizar número para siguiente iteración
    mov x25, x28           // Número = número / 10
    b convert_loop

end_convert:
    // Calcular longitud de la cadena resultante
    add x26, x26, #1       // Ajustar puntero al primer dígito
    adr x25, buffer
    add x25, x25, #20
    sub x2, x25, x26       // x2 = longitud de la cadena
    
    // Imprimir número
    mov x0, #1             // File descriptor: 1 para stdout
    mov x1, x26            // Dirección del búfer
    mov x8, #64            // Syscall número 64: write
    svc #0                 // Llamada al sistema
    
    ret