GNU/Linux xterm-256color bash 138 views

// Programa: Invertir un número en ARM64 Assembly
// Autor: Victor Manuel Madrid Lugo
// Fecha: 03/04/2025
// Descripción: Este programa captura un número entero ingresado por el usuario,
//              lo invierte y lo muestra en pantalla.
// Demostración: [  https://asciinema.org/a/thjmidqNkgmtu3f1V4KmWyCcV ]

// Código equivalente en C++:
/*
#include <iostream>
#include <string>
using namespace std;

int main() {
    string num;
    cout << "Ingresa un número: ";
    cin >> num;
    reverse(num.begin(), num.end());
    cout << "Número invertido: " << num << endl;
    return 0;
}
*/


.section .data
    msg_input:    .asciz "Ingresa un número: "
    msg_output:   .asciz "Número invertido: "
    msg_error:    .asciz "Error en la entrada.\n"

.section .bss
    input:  .skip 12   // Espacio para el número (máx 11 dígitos + '\n' + null)

.section .text
    .global _start

_start:
    // 1. Mostrar mensaje de entrada
    mov x0, 1            // File descriptor 1 (stdout)
    ldr x1, =msg_input   // Dirección del mensaje
    mov x2, 18           // Longitud del mensaje
    mov x8, 64           // syscall write
    svc 0                // Llamar al sistema

    // 2. Leer número desde stdin
    mov x0, 0            // File descriptor 0 (stdin)
    ldr x1, =input       // Dirección del buffer
    mov x2, 12           // Tamaño máximo de entrada
    mov x8, 63           // syscall read
    svc 0                // Llamar al sistema

    // Verificar si la lectura falló (x0 < 1)
    cmp x0, 1           
    blt error_exit       // Si x0 < 1, error de lectura

    // 3. Encontrar longitud del número sin incluir '\n'
    ldr x1, =input       // Dirección base del buffer
    mov x2, 0            // Contador de longitud

find_length:
    ldrb w3, [x1, x2]    // Cargar byte actual
    cmp w3, 10           // ¿Es '\n'?
    beq remove_newline   // Si sí, terminar conteo
    cmp x2, 10           // ¿Máximo permitido?
    bge remove_newline   // Si sí, cortar aquí
    add x2, x2, 1        // Incrementar contador
    b find_length        // Repetir

remove_newline:
    mov w3, 0            // Reemplazar '\n' con null '\0'
    strb w3, [x1, x2]    

    // 4. Invertir la cadena
    sub x2, x2, 1        // Posición final válida
    mov x4, 0            // Índice inicial
    ldr x1, =input       // Dirección base

reverse:
    cmp x4, x2           // ¿Índices se cruzaron?
    bge print_result     // Si sí, saltar a imprimir

    ldrb w5, [x1, x4]    // Leer inicio
    ldrb w6, [x1, x2]    // Leer fin
    strb w6, [x1, x4]    // Intercambiar
    strb w5, [x1, x2]    // Intercambiar
    add x4, x4, 1        // Avanzar inicio
    sub x2, x2, 1        // Retroceder fin
    b reverse            // Repetir

print_result:
    // 5. Agregar '\n' al final
    add x2, x4, 1        // Posición después del último caracter
    mov w3, 10           // '\n'
    strb w3, [x1, x2]    

    // 6. Imprimir mensaje de salida
    mov x0, 1            // stdout
    ldr x1, =msg_output  // Dirección del mensaje
    mov x2, 18           // Longitud del mensaje
    mov x8, 64           // syscall write
    svc 0                

    // 7. Imprimir número invertido
    mov x0, 1            // stdout
    ldr x1, =input       // Dirección del buffer
    add x2, x4, 2        // Longitud real + '\n'
    mov x8, 64           // syscall write
    svc 0                // Llamar al sistema

    // 8. Salir
    mov x8, 93           // syscall exit
    mov x0, 0            // Código de salida 0
    svc 0                // Llamar al sistema

error_exit:
    mov x0, 1            // stdout
    ldr x1, =msg_error   // Dirección del mensaje de error
    mov x2, 21           // Longitud del mensaje
    mov x8, 64           // syscall write
    svc 0                

    mov x8, 93           // syscall exit
    mov x0, 1            // Código de salida de error
    svc 0                // Salir