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