GNU/Linux xterm-256color bash 145 views

// ****************************************************************************
// * Nombre del archivo: practica.s
// * Descripción: Determinar si un numero es narcicista
// * Autor: Roldan Castro Luis Alberto
// * Fecha: 08-04-2025
// * Plataforma: Raspberry Pi OS (64 bits)
// * Asciinema: https://asciinema.org/a/iyXl3cAxT7AtITL2Rrt8mfdnS
// ****************************************************************************

// ****************************************************************************
// Version en JAVA
//
//import java.util.Scanner;
//
//public class ArmstrongNumber {
//    public static void main(String[] args) {
//        Scanner scanner = new Scanner(System.in);
//        
//        // Solicitar entrada del usuario
//        System.out.print("Ingresa un numero: ");
//        int num = scanner.nextInt();
//        scanner.close();
//        
//        // Verificar si el número es de Armstrong
//        if (isArmstrong(num)) {
//            System.out.println("Es un numero de Armstrong");
//        } else {
//            System.out.println("No es un numero de Armstrong");
//        }
//    }
//    
//    public static boolean isArmstrong(int number) {
//        int original = number;
//        int sum = 0;
//        
//        while (number > 0) {
//            int digit = number % 10;
//            sum += Math.pow(digit, 3);
//            number /= 10;
//        }
//       
//        return sum == original;
//    }
//}
// ****************************************************************************

.section .data
    msg_input: .ascii "Ingresa un numero: "
    len_input = . - msg_input

    msg_yes: .ascii "Es un numero de Armstrong\n"
    len_yes = . - msg_yes

    msg_no: .ascii "No es un numero de Armstrong\n"
    len_no = . - msg_no

.section .bss
    buffer: .skip 16      // Espacio para guardar la entrada del usuario (hasta 15 caracteres + '\n')

.section .text
.global _start

_start:
    // --- Mostrar mensaje de entrada ---
    ldr x0, =msg_input      // Dirección del mensaje
    mov x1, #len_input      // Longitud del mensaje
    bl print_msg            // Llama a la función para imprimir

    // --- Leer entrada del usuario ---
    mov x0, #0              // stdin
    ldr x1, =buffer         // Dirección donde guardar entrada
    mov x2, #16             // Tamaño máximo a leer
    mov x8, #63             // syscall read
    svc #0

    // --- Convertir cadena a número ---
    ldr x1, =buffer         // Dirección del buffer con texto
    bl atoi                 // Convierte a número (resultado en x0)
    mov x19, x0             // Guardamos el número original en x19

    // --- Verificar si es número de Armstrong ---
    mov x1, x19             // Copiamos el número a x1 para trabajarlo
    mov x2, #0              // Acumulador para la suma de cubos
    mov x3, #10             // Constante 10 para extraer dígitos

loop_digits:
    udiv x4, x1, x3         // x4 = x1 / 10 (número sin el último dígito)
    msub x5, x4, x3, x1     // x5 = x1 - x4 * 10 → último dígito (módulo)
    
    // Calcular el cubo del dígito: x5^3
    mov x6, x5
    mul x6, x6, x5
    mul x6, x6, x5

    // Sumar a la suma total de cubos
    add x2, x2, x6
    mov x1, x4              // Reducimos el número (quitamos el último dígito)
    cbz x1, end_loop        // Si x1 == 0, terminamos el ciclo
    b loop_digits

end_loop:
    // Comparamos suma de cubos con número original
    cmp x2, x19
    b.eq print_yes          // Si son iguales, es un número de Armstrong

print_no:
    ldr x0, =msg_no
    mov x1, #len_no
    bl print_msg
    b end_prog

print_yes:
    ldr x0, =msg_yes
    mov x1, #len_yes
    bl print_msg

end_prog:
    // Salida del programa (sys_exit)
    mov x8, #93
    mov x0, #0
    svc #0

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

// print_msg(x0 = dirección del mensaje, x1 = longitud)
print_msg:
    mov x2, x1          // Longitud
    mov x1, x0          // Dirección del mensaje
    mov x0, #1          // stdout
    mov x8, #64         // syscall write
    svc #0
    ret

// atoi(x1 = dirección del buffer) → x0 = número entero
atoi:
    mov x0, #0          // Resultado acumulado
    mov x3, #10         // Base decimal

atoi_loop:
    ldrb w2, [x1], #1   // Cargar siguiente byte del buffer y avanzar el puntero
    cmp w2, #'0'        // ¿Es menor que '0'?
    blt atoi_done       // Sí: fin
    cmp w2, #'9'        // ¿Es mayor que '9'?
    bgt atoi_done       // Sí: fin

    sub w2, w2, #'0'    // Convertir carácter a dígito (ASCII → número)
    mul x0, x0, x3      // Multiplicar acumulador por 10
    add x0, x0, x2      // Sumar el nuevo dígito
    b atoi_loop

atoi_done:
    ret