GNU/Linux xterm bash 165 views

Este código en ensamblador ARM64 tiene como objetivo leer una cadena de caracteres desde la entrada estándar, contar el número de vocales y consonantes en la cadena y luego imprimir los resultados. A continuación, te explico el código detalladamente:

Sección de Datos (.data):

  • msg_ingreso: Mensaje que se muestra al usuario pidiendo que ingrese una cadena de texto.
  • msg_vocales: Mensaje que se imprimirá mostrando el número de vocales.
  • msg_consonantes: Mensaje que se imprimirá mostrando el número de consonantes.
  • buffer: Un espacio de 100 bytes en memoria para almacenar la cadena ingresada por el usuario.
  • formato_str: Especifica el formato para leer una cadena de caracteres hasta que se encuentre un salto de línea (\n).
  • vocales: Cadena que contiene las vocales tanto en minúsculas como en mayúsculas (para poder comparar caracteres con ambas formas).

Sección de Código (.text):

La ejecución comienza en la función main.

1. Prologo (Preparación de la pila):

stp x29, x30, [sp, -32]!  // Guardar el puntero de marco (x29) y el enlace de retorno (x30) en la pila
mov x29, sp                // Establecer el puntero de marco
  • stp x29, x30, [sp, -32]!: Guarda los registros x29 (puntero de marco) y x30 (registro de enlace de retorno) en la pila.
  • mov x29, sp: Establece el puntero de marco al valor actual del puntero de pila (sp), que se usa para gestionar el contexto de la función.

2. Inicialización de los contadores:

str xzr, [sp, 16]  // Inicializar contador de vocales en 0 (xzr es el registro que contiene 0)
str xzr, [sp, 24]  // Inicializar contador de consonantes en 0
  • str xzr, [sp, 16]: Guarda el valor 0 en la dirección sp + 16, que es el contador de vocales.
  • str xzr, [sp, 24]: Guarda el valor 0 en la dirección sp + 24, que es el contador de consonantes.

3. Mostrar mensaje de ingreso y leer la cadena:

adr x0, msg_ingreso  // Cargar la dirección del mensaje de ingreso
bl printf            // Llamar a printf para mostrar el mensaje

adr x0, formato_str  // Cargar el formato para leer una cadena
adr x1, buffer       // Dirección de memoria donde se almacenará la cadena
bl scanf             // Llamar a scanf para leer la cadena
  • adr x0, msg_ingreso: Carga la dirección del mensaje “Ingrese una cadena” en x0 para que sea usado por printf.
  • bl printf: Llama a printf para imprimir el mensaje de ingreso.
  • adr x0, formato_str: Carga el formato para leer una cadena (usando %[^\n] para leer hasta el salto de línea).
  • adr x1, buffer: Carga la dirección del buffer donde se almacenará la cadena ingresada.
  • bl scanf: Llama a scanf para leer la cadena de caracteres del usuario.

4. Procesar cada carácter de la cadena:

El ciclo principal procesar_char recorre cada carácter de la cadena ingresada y realiza el conteo de vocales y consonantes.

procesar_char:
    ldrb w2, [x0, x1]      // Cargar el carácter en w2
    cbz w2, fin_conteo     // Si es 0 (fin de la cadena), salimos del ciclo

    // Verificar si el carácter es una letra
    cmp w2, #'A'
    b.lt siguiente_char
    cmp w2, #'z'
    b.gt siguiente_char
    cmp w2, #'Z'
    b.le es_letra
    cmp w2, #'a'
    b.ge es_letra
    b siguiente_char
  • ldrb w2, [x0, x1]: Carga el carácter de la cadena en el registro w2 (un byte).
  • cbz w2, fin_conteo: Si el valor de w2 es 0 (fin de la cadena), salta a fin_conteo para terminar el procesamiento.
  • cmp w2, #'A': Compara el carácter con 'A' (mayúsculas).
  • b.lt siguiente_char: Si el carácter es menor que 'A', no es una letra, por lo que se salta al siguiente carácter.
  • cmp w2, #'z': Compara con 'z' (minúsculas).
  • b.gt siguiente_char: Si el carácter es mayor que 'z', no es una letra y se pasa al siguiente.
  • cmp w2, #'Z': Compara con 'Z' (mayúsculas).
  • b.le es_letra: Si el carácter está entre 'A' y 'Z', es una letra.
  • cmp w2, #'a': Compara con 'a' (minúsculas).
  • b.ge es_letra: Si el carácter está entre 'a' y 'z', es una letra.

5. Verificar si la letra es una vocal:

es_letra:
    adr x3, vocales          // Cargar la dirección de la cadena de vocales
    mov x4, #0               // Iniciar el índice de vocales en 0

check_vocal:
    ldrb w5, [x3, x4]        // Cargar una vocal
    cbz w5, es_consonante    // Si llegamos al final de la cadena de vocales, es consonante
    cmp w2, w5               // Comparar el carácter con la vocal
    b.eq es_vocal            // Si es igual, es una vocal
    add x4, x4, #1           // Incrementar el índice
    b check_vocal            // Continuar verificando con la siguiente vocal
  • adr x3, vocales: Carga la dirección de la cadena de vocales.
  • mov x4, #0: Inicializa el índice x4 a 0 para recorrer las vocales.
  • ldrb w5, [x3, x4]: Carga una vocal de la cadena de vocales en w5.
  • cbz w5, es_consonante: Si w5 es 0 (llegamos al final de la cadena de vocales), salta a es_consonante.
  • cmp w2, w5: Compara el carácter actual con la vocal.
  • b.eq es_vocal: Si es una vocal, salta a es_vocal.
  • add x4, x4, #1: Incrementa el índice x4 y continúa con la siguiente vocal.

6. Incrementar el contador de vocales o consonantes:

es_vocal:
    ldr x4, [sp, 16]       // Cargar contador de vocales
    add x4, x4, #1         // Incrementar el contador
    str x4, [sp, 16]       // Guardar el nuevo contador
    b siguiente_char

es_consonante:
    ldr x4, [sp, 24]       // Cargar contador de consonantes
    add x4, x4, #1         // Incrementar el contador
    str x4, [sp, 24]       // Guardar el nuevo contador
  • Si el carácter es una vocal, se incrementa el contador de vocales. Si no es una vocal, se incrementa el contador de consonantes.

7. Mostrar los resultados:

fin_conteo:
    adr x0, msg_vocales    // Cargar mensaje de vocales
    ldr x1, [sp, 16]       // Cargar el número de vocales
    bl printf              // Imprimir número de vocales

    adr x0, msg_consonantes  // Cargar mensaje de consonantes
    ldr x1, [sp, 24]        // Cargar el número de consonantes
    bl printf               // Imprimir número de consonantes
  • Al finalizar el procesamiento, el programa imprime los resultados de las vocales y consonantes usando printf.

8. Epílogo (Restaurar la pila y retornar):

mov w0, #0              // Establecer el valor de retorno a 0
ldp x29, x30, [sp], 32  // Restaurar los registros x29 y x30 desde la pila
ret                      // Retornar al sistema operativo
  • mov w0, #0: Establece el valor de retorno a 0.
  • ldp x29, x30, [sp], 32: Restaura el puntero de marco y el enlace de retorno desde la pila.
  • ret: Finaliza el programa y retorna al sistema operativo.

Resumen:

Este programa en ensamblador ARM64:

  1. Solicita al usuario que ingrese una cadena de texto.
  2. Recorre cada carácter de la cadena, contando las vocales y consonantes.
  3. Imprime el número de vocales y consonantes en la cadena.

Es un ejemplo interesante de cómo manejar cadenas de texto y realizar comparaciones y manipulaciones en ensamblador ARM64.