GNU/Linux xterm-256color bash 145 views

//============================================================
// Autor: Madrid Lugo Victor Manuel
// Fecha: 06/04/2025
// Descripción: Suma los dígitos de un número entero ingresado
// Programa: Suma de dígitos en ARM64 Assembly
// Demostración: [https://asciinema.org/a/Rc80se667XY9vH1R65VroaME1]
//============================================================


/* 
Equivalente en Python:

def suma_digitos():
    # Solicitar entrada al usuario
    numero = input("Ingrese un numero entero: ")
    
    # Sumar los dígitos
    suma = 0
    for caracter in numero:
        if caracter.isdigit():
            suma += int(caracter)
    
    # Mostrar el resultado
    print(f"La suma de los digitos es: {suma}")

suma_digitos()
*/

.global _start       // Punto de entrada global

.data
prompt:     .ascii "Ingrese un numero entero: "
prompt_len = . - prompt
result_msg: .ascii "La suma de los digitos es: "
result_len = . - result_msg
buffer:     .fill 20, 1, 0  // Buffer para almacenar la entrada
newline:    .ascii "\n"     // Carácter de nueva línea
result:     .fill 20, 1, 0  // Espacio para el resultado

.text
_start:
    // Mostrar el mensaje de solicitud
    MOV X0, #1            // stdout
    ADR X1, prompt        // dirección del prompt
    MOV X2, prompt_len    // longitud del prompt
    MOV X8, #64           // syscall write
    SVC #0                // llamada al sistema
    
    // Leer la entrada del usuario
    MOV X0, #0            // stdin
    ADR X1, buffer        // dirección del buffer
    MOV X2, #20           // tamaño máximo de lectura
    MOV X8, #63           // syscall read
    SVC #0                // llamada al sistema
    
    MOV X3, X0            // X3 = número de bytes leídos
    
    // Convertir la entrada a número e ir sumando cada dígito
    MOV X4, #0            // X4 = suma de dígitos
    ADR X5, buffer        // X5 = puntero al buffer
    MOV X6, #0            // X6 = contador

read_loop:
    CMP X6, X3            // ¿Hemos leído todos los bytes?
    B.GE print_result     // Si es así, ir a imprimir resultado
    
    LDRB W7, [X5, X6]     // W7 = byte actual
    
    CMP W7, #'\n'         // ¿Es un salto de línea?
    B.EQ print_result     // Si es así, terminamos de leer
    
    CMP W7, #'0'          // ¿Es menor que '0'?
    B.LT next_byte        // Si es así, ignorar
    
    CMP W7, #'9'          // ¿Es mayor que '9'?
    B.GT next_byte        // Si es así, ignorar
    
    SUB W7, W7, #'0'      // Convertir ASCII a valor numérico
    ADD X4, X4, X7        // Sumar a la suma total
    
next_byte:
    ADD X6, X6, #1        // Incrementar contador
    B read_loop           // Continuar con el siguiente byte
    
print_result:
    // Mostrar mensaje de resultado
    MOV X0, #1            // stdout
    ADR X1, result_msg    // dirección del mensaje
    MOV X2, result_len    // longitud del mensaje
    MOV X8, #64           // syscall write
    SVC #0                // llamada al sistema
    
    // Convertir resultado a ASCII
    ADR X1, result        // X1 = buffer de resultado
    MOV X2, #19           // X2 = posición final (dejando espacio para null)
    ADD X1, X1, X2        // Posicionar al final del buffer
    
    MOV X3, #0            // Terminator nulo
    STRB W3, [X1]         // Guardar null al final
    SUB X1, X1, #1        // Mover al último carácter
    
    MOV X7, X4            // X7 = copia de la suma
    
    // Si la suma es 0, manejar especialmente
    CMP X7, #0
    B.NE convert_loop
    
    MOV W3, #'0'          // Carácter '0'
    STRB W3, [X1]         // Guardar '0' en el resultado
    ADD X2, X2, #1        // Ajustar longitud
    B print_sum

convert_loop:
    CBZ X7, check_empty   // Si X7 es 0, terminamos
    
    MOV X9, #10           // Divisor = 10
    UDIV X8, X7, X9       // X8 = X7 / 10
    MSUB X10, X8, X9, X7  // X10 = X7 - (X8 * 10) = X7 % 10
    
    ADD W10, W10, #'0'    // Convertir a carácter ASCII
    STRB W10, [X1], #-1   // Guardar en buffer y retroceder
    
    MOV X7, X8            // X7 = X7 / 10
    ADD X2, X2, #1        // Incrementar longitud
    
    B convert_loop        // Repetir para el siguiente dígito

check_empty:
    ADR X9, result        // Inicio del buffer
    ADD X1, X1, #1        // Mover al primer dígito
    
print_sum:
    // Imprimir el resultado
    MOV X0, #1            // stdout
    // X1 ya tiene la dirección del resultado
    // X2 ya tiene la longitud
    MOV X8, #64           // syscall write
    SVC #0                // llamada al sistema
    
    // Imprimir nueva línea
    MOV X0, #1            // stdout
    ADR X1, newline       // dirección de nueva línea
    MOV X2, #1            // longitud
    MOV X8, #64           // syscall write
    SVC #0                // llamada al sistema
    
    // Salir
    MOV X0, #0            // código de retorno
    MOV X8, #93           // syscall exit
    SVC #0                // llamada al sistema