GNU/Linux xterm bash 91 views

📌 Demostración: Suma de los dígitos de un número dado en ARM64 Assembly

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

🎯 Descripción

Este programa imprime los números impares comprendidos entre 5 y 75.
La implementación se realiza en:

Assembly ARM64 para RaspbianOS en Raspberry Pi

🔧 Compilación en Raspberry Pi (ARM64)

as suma_digitos.s -o suma_digitos.o  
ld suma_digitos.o -o suma_digitos

▶️ Ejecución

./suma_digitos

👀 Código fuente

🔗 Código fuente en Gist: Programa 39 Suma los digitos de un numero mostrando resultado en terminal 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/10                                                         |
| • Descripción: Programa que suma los digitos de un numero y muestra el      |
|   resultado en terminal en C++ y Assembly ARM64 para RaspbianOS.            |
| • Demostración:                                                             |
|   https://asciinema.org/a/714712                                            |
| • Compilación (Raspberry Pi ARM64):                                         |
|     as suma_digitos.s -o suma_digitos.o                                     |
|     ld suma_digitos.o -o suma_digitos                                       |
| • Ejecución: ./suma_digitos                                                 |
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

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

#include <iostream>
using namespace std;

int main() {
    long long n;
    cout << "Ingrese un número: ";
    cin >> n;
    
    int suma = 0;
    for (n = abs(n); n > 0; n /= 10) {
        suma += n % 10;
    }
    
    cout << "Suma de dígitos: " << suma << endl;
    return 0;
}

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

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

// Programa ARM64 para calcular la suma de los dígitos de un número
// Para ensamblar y enlazar:
// as -o suma_digitos.o suma_digitos.s
// ld -o suma_digitos suma_digitos.o

.global _start      // Punto de entrada para el enlazador

.data
mensaje_input:  .ascii "Ingrese un número: "
len_input:      .quad 19
mensaje_output: .ascii "La suma de los dígitos es: "
len_output:     .quad 27
buffer:         .skip 20       // Búfer para almacenar la entrada del usuario
nuevalinea:     .ascii "\n"

.text
_start:
    // Imprimir mensaje de solicitud
    mov x0, #1                  // File descriptor: 1 es stdout
    adr x1, mensaje_input       // Puntero al mensaje
    ldr x2, len_input           // Longitud del mensaje
    mov x8, #64                 // syscall write
    svc #0                      // Llamada al sistema

    // Leer la entrada del usuario
    mov x0, #0                  // File descriptor: 0 es stdin
    adr x1, buffer              // Puntero al búfer
    mov x2, #20                 // Máximo número de bytes a leer
    mov x8, #63                 // syscall read
    svc #0                      // Llamada al sistema

    // Calcular la longitud de la entrada (sin incluir \n)
    mov x3, x0                  // Guardar número de bytes leídos
    sub x3, x3, #1              // Restar 1 para excluir el \n final

    // Inicializar suma de dígitos
    mov x4, #0                  // x4 = suma = 0
    mov x5, #0                  // x5 = índice del búfer

sumar_loop:
    cmp x5, x3                  // Comparar índice con longitud
    b.ge fin_suma               // Si índice >= longitud, salir del bucle

    // Cargar el dígito actual
    adr x6, buffer              // Obtener dirección del búfer
    add x6, x6, x5              // Añadir el índice
    ldrb w7, [x6]               // Cargar el byte (carácter) en w7

    // Verificar si es un dígito (ASCII 48-57)
    cmp w7, #48                 // Comparar con '0'
    b.lt no_digito              // Si < '0', no es un dígito
    cmp w7, #57                 // Comparar con '9'
    b.gt no_digito              // Si > '9', no es un dígito

    // Convertir de ASCII a valor numérico y sumar
    sub w7, w7, #48             // Convertir ASCII a valor (restar 48)
    add x4, x4, x7              // Sumar el dígito a la suma total

no_digito:
    add x5, x5, #1              // Incrementar índice
    b sumar_loop                // Repetir bucle

fin_suma:
    // Convertir la suma a ASCII para mostrarla
    mov x5, #0                  // Índice para el búfer de salida
    adr x6, buffer              // Reutilizar el búfer para la salida
    
    // Si la suma es 0, directamente escribimos '0'
    cmp x4, #0
    b.ne convertir_suma
    
    mov w7, #48                 // ASCII '0'
    strb w7, [x6]               // Almacenar el byte en el búfer
    mov x5, #1                  // Longitud = 1
    b fin_conversion

convertir_suma:
    // Primero, encontramos cuántos dígitos tiene la suma
    mov x7, x4                  // Copia de la suma para contar dígitos
    mov x9, #0                  // Contador de dígitos
    mov x11, #10                // Cargar constante 10 en registro

contar_digitos:
    cmp x7, #0                  // Verificar si hemos terminado
    b.eq fin_contar_digitos     // Si suma = 0, terminar
    
    udiv x7, x7, x11            // Dividir por 10 (en x11)
    add x9, x9, #1              // Incrementar contador de dígitos
    b contar_digitos            // Repetir

fin_contar_digitos:
    // Ahora x9 contiene el número de dígitos
    // Convertir dígitos de derecha a izquierda (en orden inverso)
    add x6, x6, x9              // Apuntar al final del búfer
    sub x6, x6, #1              // Retroceder una posición
    mov x7, x4                  // Copia de la suma para convertir
    mov x11, #10                // Cargar constante 10 en registro

convertir_digitos:
    cmp x7, #0                  // Verificar si hemos terminado
    b.eq fin_conversion         // Si suma = 0, terminar
    
    udiv x8, x7, x11            // x8 = x7 / 10 (cociente)
    msub x10, x8, x11, x7       // x10 = x7 - (x8 * 10) (resto)
    
    add w10, w10, #48           // Convertir dígito a ASCII
    strb w10, [x6]              // Almacenar dígito en búfer
    
    mov x7, x8                  // Actualizar suma para próxima iteración
    sub x6, x6, #1              // Mover puntero hacia atrás en el búfer
    b convertir_digitos         // Repetir

fin_conversion:
    add x6, x6, #1              // Ajustar puntero al inicio de los dígitos
    mov x5, x9                  // x5 = longitud de la cadena de resultado
    
    // Imprimir mensaje de salida
    mov x0, #1                  // File descriptor: 1 es stdout
    adr x1, mensaje_output      // Puntero al mensaje
    ldr x2, len_output          // Longitud del mensaje
    mov x8, #64                 // syscall write
    svc #0                      // Llamada al sistema

    // Imprimir el resultado
    mov x0, #1                  // File descriptor: 1 es stdout
    mov x1, x6                  // Puntero al resultado
    mov x2, x5                  // Longitud del resultado
    mov x8, #64                 // syscall write
    svc #0                      // Llamada al sistema

    // Imprimir nueva línea
    mov x0, #1                  // File descriptor: 1 es stdout
    adr x1, nuevalinea          // Puntero a la nueva línea
    mov x2, #1                  // Longitud de la nueva línea
    mov x8, #64                 // syscall write
    svc #0                      // Llamada al sistema

    // Salir del programa
    mov x0, #0                  // Código de salida 0 (éxito)
    mov x8, #93                 // syscall exit
    svc #0                      // Llamada al sistema