GNU/Linux xterm bash 85 views

📌 Demostración: Verificador de números primos en ARM64 Assembly

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

🎯 Descripción

Este programa verifica si un número es primo o no.
La implementación se realiza en:

Assembly ARM64 para RaspbianOS en Raspberry Pi

🔧 Compilación en Raspberry Pi (ARM64)

as primo.s -o primo.o  
ld primo.o -o primo

▶️ Ejecución

./primo

👀 Código fuente

🔗 Código fuente en Gist: Programa 17 Verificador de números primos 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/08                                                    | 
| • Descripción: Programa que verifica si un numero es                   | 
|   primo o no en Javascript y Assembly ARM64 para RaspbianOS.           | 
| • Demostración:                                                        |
|   https://asciinema.org/a/713369                                       |
| • Compilación (Raspberry Pi ARM64):                                    |  
|     as primo.s -o primo.o                                              |  
|     ld primo.o -o primo                                                |  
| • Ejecución: ./primo                                                   |  
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄                                        

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

const testNumber = 97;

const msgTesting = "Verificando si el número ";
const msgIsPrime = " es primo: SÍ\n";
const msgNotPrime = " es primo: NO\n";
const msgReason = "Divisible por: ";
const newline = "\n";

function main() {
    process.stdout.write(msgTesting);
    process.stdout.write(testNumber.toString());
    
    if (testNumber <= 1) {
        process.stdout.write(msgNotPrime);
        return;
    }
    
    if (testNumber === 2) {
        process.stdout.write(msgIsPrime);
        return;
    }
    
    if ((testNumber & 1) === 0) {
        process.stdout.write(msgNotPrime);
        process.stdout.write(msgReason + "2" + newline);
        return;
    }
    
    const limit = Math.floor(Math.sqrt(testNumber)) + 1;
    
    for (let factor = 3; factor <= limit; factor += 2) {
        if (testNumber % factor === 0) {
            process.stdout.write(msgNotPrime);
            process.stdout.write(msgReason + factor.toString() + newline);
            return;
        }
    }
    
    process.stdout.write(msgIsPrime);
}

main();

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

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

.global _start      // Punto de entrada global

.data
// Número a verificar
test_number:
    .word 97

// Mensajes
msg_testing:
    .ascii "Verificando si el número "
msg_testing_len = . - msg_testing

msg_is_prime:
    .ascii " es primo: SÍ\n"
msg_is_prime_len = . - msg_is_prime

msg_not_prime:
    .ascii " es primo: NO\n"
msg_not_prime_len = . - msg_not_prime

msg_reason:
    .ascii "Divisible por: "
msg_reason_len = . - msg_reason

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

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

.text
_start:
    // Cargar el número a verificar
    adr x19, test_number
    ldr w19, [x19]       // w19 = número a verificar
    
    // Mostrar mensaje inicial
    mov x0, #1
    adr x1, msg_testing
    mov x2, #msg_testing_len
    mov x8, #64
    svc #0
    
    // Mostrar el número a verificar
    mov x24, x19
    bl num_to_ascii
    
    // Caso especial: si el número es menor o igual a 1, no es primo
    cmp w19, #1
    b.le not_prime
    
    // Caso especial: si el número es 2, es primo
    cmp w19, #2
    b.eq is_prime
    
    // Caso especial: si es par (excepto 2), no es primo
    and w24, w19, #1     // Verificar último bit (0 si es par)
    cbnz w24, check_prime
    
    // Es par y no es 2, así que no es primo
    mov w20, #2          // Factor por el cual es divisible
    b not_prime
    
check_prime:
    // Inicializar para la comprobación
    mov w20, #3          // Empezar a verificar desde 3
    
    // Calcular la raíz cuadrada aproximada para optimizar
    // Usaremos método simplificado: dividir entre 2 y sumar 1
    lsr w21, w19, #1     // w21 = número / 2
    add w21, w21, #1     // Para redondear hacia arriba
    
prime_loop:
    // Comparar si ya hemos llegado al límite
    cmp w20, w21
    b.gt is_prime        // Si superamos la raíz cuadrada, es primo
    
    // Verificar si es divisible por el factor actual
    sdiv w22, w19, w20   // w22 = número / factor
    msub w23, w22, w20, w19 // w23 = número - (factor * (número/factor)) = número % factor
    
    // Si el residuo es 0, no es primo
    cbz w23, not_prime
    
    // Incrementar factor en 2 (saltando números pares)
    add w20, w20, #2
    b prime_loop

is_prime:
    // Mostrar mensaje que es primo
    mov x0, #1
    adr x1, msg_is_prime
    mov x2, #msg_is_prime_len
    mov x8, #64
    svc #0
    
    b exit_program

not_prime:
    // Mostrar mensaje que no es primo
    mov x0, #1
    adr x1, msg_not_prime
    mov x2, #msg_not_prime_len
    mov x8, #64
    svc #0
    
    // Mostrar el factor por el que es divisible
    mov x0, #1
    adr x1, msg_reason
    mov x2, #msg_reason_len
    mov x8, #64
    svc #0
    
    // Mostrar el factor
    mov x24, x20
    bl num_to_ascii
    
    // Mostrar nueva línea
    mov x0, #1
    adr x1, newline
    mov x2, #newline_len
    mov x8, #64
    svc #0

exit_program:
    // Salir del programa
    mov x0, #0
    mov x8, #93
    svc #0

// 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