GNU/Linux xterm-256color bash 135 views

// ****************************************************************************
// * Nombre del archivo: practica.s
// * Descripción: Sumar los numeros anteriores a N
// * Autor: Roldan Castro Luis Alberto
// * Fecha: 07-04-2025
// * Plataforma: Raspberry Pi OS (64 bits)
// * Asciinema: https://asciinema.org/a/ynGRHarvCAYpPRIiwEdwptyPI
// ****************************************************************************

// ****************************************************************************
// Version en python
//
//def suma_anteriores(n):
//    return sum(range(n))
//
//# Ejemplo de uso
//N = int(input("Ingrese un número: "))
//print(f"La suma de los números anteriores a {N} es: {suma_anteriores(N)}")
//
// ****************************************************************************

.section .bss
buffer: .skip 64           // Reservar 64 bytes de memoria para almacenar la entrada del usuario

.section .data
msg_ingrese: .ascii "Ingrese un numero: "  // Mensaje para pedir al usuario un número
len_ingrese = . - msg_ingrese             // Longitud del mensaje "Ingrese un numero: "

msg_resultado: .ascii "Resultado: "       // Mensaje para mostrar el resultado
len_resultado = . - msg_resultado         // Longitud del mensaje "Resultado: "

newline: .ascii "\n"                      // Salto de línea para la salida
len_nl = . - newline                      // Longitud del salto de línea

.section .text
.global _start

_start:
    // Mostrar mensaje para pedir el número
    ldr x0, =msg_ingrese    // Cargar la dirección del mensaje "Ingrese un numero: "
    mov x1, #len_ingrese    // Cargar la longitud del mensaje
    bl print_msg            // Llamar a la función para imprimir el mensaje

    // Leer el número ingresado por el usuario
    mov x0, #0              // Descriptor de archivo para entrada estándar (0 = stdin)
    ldr x1, =buffer         // Dirección del buffer donde se almacenará la entrada
    mov x2, #64             // Tamaño del buffer
    mov x8, #63             // Llamada al sistema para leer desde la entrada (sys_read)
    svc #0                  // Realizar la llamada al sistema

    // Convertir texto ingresado a número
    ldr x1, =buffer         // Dirección del buffer que contiene el texto
    mov x2, #0              // Inicializar el acumulador a 0 (para el número)
parse_loop:
    ldrb w3, [x1], #1       // Cargar un byte del buffer
    cmp w3, #'0'            // Comparar con el carácter '0'
    blt fin_parse           // Si es menor que '0', terminamos
    cmp w3, #'9'            // Comparar con el carácter '9'
    bgt fin_parse           // Si es mayor que '9', terminamos
    sub w3, w3, #'0'        // Convertir el carácter a su valor numérico
    mov w4, #10             // Número por el cual multiplicamos el acumulador
    mul w2, w2, w4          // Multiplicar el acumulador por 10
    add w2, w2, w3          // Sumar el valor del dígito
    b parse_loop            // Continuar con el siguiente carácter

fin_parse:
    mov x10, x2             // Guardar el número final en x10

    // Calcular la sumatoria del 1 al N
    mov x3, #1              // Inicializar i = 1
    mov x4, #0              // Inicializar suma = 0

sum_loop:
    cmp x3, x10             // Comparar i con el número N
    bgt mostrar             // Si i > N, mostrar el resultado
    add x4, x4, x3          // suma += i
    add x3, x3, #1          // Incrementar i
    b sum_loop              // Continuar con la sumatoria

mostrar:
    // Mostrar el mensaje "Resultado:"
    ldr x0, =msg_resultado  // Cargar la dirección del mensaje "Resultado: "
    mov x1, #len_resultado // Cargar la longitud del mensaje
    bl print_msg            // Llamar a la función para imprimir el mensaje

    // Mostrar la suma calculada
    mov x0, x4              // Cargar la suma en x0
    bl print_number         // Llamar a la función para imprimir el número

    // Imprimir un salto de línea
    ldr x0, =newline        // Cargar la dirección del salto de línea
    mov x1, #len_nl         // Cargar la longitud del salto de línea
    bl print_msg            // Llamar a la función para imprimir el salto de línea

    // Salir del programa
    mov x8, #93             // Llamada al sistema para salir del programa
    mov x0, #0              // Código de salida (0 = éxito)
    svc #0                  // Realizar la llamada al sistema

// --- Función: imprimir mensaje ---
print_msg:
    mov x2, x1              // Longitud del mensaje
    mov x1, x0              // Dirección del mensaje
    mov x0, #1              // Descriptor de archivo para salida estándar (1 = stdout)
    mov x8, #64             // Llamada al sistema para escribir (sys_write)
    svc #0                  // Realizar la llamada al sistema
    ret

// --- Función: imprimir número ---
print_number:
    mov x1, x0              // Número a imprimir
    ldr x2, =buffer         // Dirección donde se almacenará el número como texto
    add x2, x2, #63         // Ajustar el puntero para escribir desde el final del buffer
    mov w3, #0              // Contador de dígitos

convert_loop:
    mov x4, #10             // Factor para dividir el número
    udiv x5, x1, x4         // Dividir x1 entre 10
    msub x6, x5, x4, x1     // Resto de la división (x1 % 10)
    add x6, x6, #'0'        // Convertir el resto a un carácter ASCII
    strb w6, [x2], #-1      // Almacenar el carácter en el buffer
    mov x1, x5              // Actualizar x1 para la siguiente iteración
    add w3, w3, #1          // Incrementar el contador de dígitos
    cbnz x1, convert_loop   // Continuar si hay más dígitos

    add x2, x2, #1          // Ajustar el puntero del buffer
    mov x1, x2              // Dirección final del número
    mov w2, w3              // Número de dígitos
    mov x0, #1              // Descriptor de salida (1 = stdout)
    mov x8, #64             // Llamada al sistema para escribir
    svc #0                  // Realizar la llamada al sistema
    ret