GNU/Linux xterm bash 164 views

Este código en ARM64 tiene como objetivo imprimir números del 9 al 43, uno por línea, en formato de texto. El programa convierte cada número a su representación en ASCII, imprime la cadena resultante y luego continúa con el siguiente número hasta llegar a 43. A continuación, te explico el funcionamiento del código en detalle:

1. Sección de datos

.section .data
buffer: .skip 16            // Buffer para almacenar el número convertido
  • buffer: Se reserva un espacio de 16 bytes en la sección de datos para almacenar el número convertido a su representación en cadena ASCII.

2. Sección de texto (código)

.section .text
.global _start
  • _start: Define el punto de entrada del programa. El código ejecutado empieza desde aquí.

3. Inicio del programa (_start)

_start:
    mov x19, #9             // Contador: i = 9
  • x19: Se inicializa con el valor 9. Este es el primer número que se convertirá a texto y se imprimirá.

4. Bucle principal (loop)

loop:
    // Convertir número a ASCII
    mov x0, x19             // Número actual
    ldr x1, =buffer         // Dirección del buffer
    bl int_to_ascii
  • x0 = x19: El número actual a convertir se pasa en x0.
  • x1 = buffer: La dirección del buffer donde se almacenará la cadena de caracteres resultante.
  • bl int_to_ascii: Llama a la subrutina int_to_ascii, que convierte el número en x0 a su representación en ASCII y lo almacena en el buffer apuntado por x1.

5. Imprimir la cadena convertida

    ldr x0, =buffer
    bl print_string
  • ldr x0, =buffer: Carga la dirección del buffer que contiene la cadena convertida.
  • bl print_string: Llama a la subrutina print_string para imprimir la cadena en la consola.

6. Incrementar contador y continuar el bucle

    add x19, x19, #1        // i++
    cmp x19, #44            // ¿i <= 43?
    blt loop
  • add x19, x19, #1: Incrementa el valor de x19 en 1.
  • cmp x19, #44: Compara el valor de x19 con 44.
  • blt loop: Si x19 es menor que 44, salta de nuevo al inicio del bucle y continúa con el siguiente número.

7. Salir del programa

    mov x8, #93             // syscall exit
    mov x0, #0              // código de salida 0
    svc 0
  • mov x8, #93: Prepara la llamada al sistema para salir del programa (código de salida 93).
  • mov x0, #0: Especifica que el estado de salida será 0 (indicado como “exit status”).
  • svc 0: Realiza la llamada al sistema para salir del programa.

8. Subrutina: int_to_ascii (convertir entero a ASCII)

int_to_ascii:
    stp x2, x3, [sp, #-16]!
    stp x4, x5, [sp, #-16]!
  • Se guardan los registros x2, x3, x4 y x5 en la pila para preservarlos, ya que se modificarán durante la ejecución de la subrutina.
    mov x2, x1              // x2 = puntero al buffer
    mov x3, #10             // divisor base 10
    mov x5, #0              // contador de dígitos
  • x2: Dirección del buffer donde se almacenará la cadena resultante.
  • x3: Se configura x3 con 10, que es el divisor para convertir el número a su representación decimal.
  • x5: Inicializa un contador de dígitos en 0.
.convert_loop:
    udiv x4, x0, x3         // x4 = x0 / 10 (cociente)
    msub x0, x4, x3, x0     // x0 = x0 % 10 (residuo)
    add x0, x0, #'0'        // convertir a ASCII
    strb w0, [x2, x5]       // guardar carácter
    mov x0, x4              // preparar para próxima división
    add x5, x5, #1          // incrementar contador de dígitos
    cmp x0, #0              // ¿quedan más dígitos?
    b.ne .convert_loop
  • udiv x4, x0, x3: Divide el número x0 entre 10 y almacena el cociente en x4.
  • msub x0, x4, x3, x0: Calcula el residuo de la división (x0 % 10) y lo almacena en x0.
  • add x0, x0, #’0’: Convierte el residuo (un dígito) a su valor ASCII.
  • strb w0, [x2, x5]: Almacena el carácter ASCII en el buffer en la posición indicada por x5.
  • Se repite el proceso hasta que el número sea reducido a 0.

9. Invertir la cadena (porque los dígitos se generan en orden inverso)

.rev_loop:
    cmp x0, x4              // ¿ya se invirtió toda la cadena?
    b.ge .add_newline       // si sí, saltar a agregar salto de línea
    ldrb w2, [x1, x0]       // cargar carácter desde el inicio
    ldrb w3, [x1, x4]       // cargar carácter desde el final
    strb w3, [x1, x0]       // intercambiar caracteres
    strb w2, [x1, x4]
    add x0, x0, #1          // mover inicio hacia adelante
    sub x4, x4, #1          // mover final hacia atrás
    b .rev_loop
  • Después de generar los dígitos en el orden inverso, se invierte la cadena para que los dígitos estén en el orden correcto.

10. Agregar salto de línea y terminador nulo

.add_newline:
    mov w3, #10             // ASCII para '\n'
    strb w3, [x1, x5]      // almacenar después de los dígitos
    add x5, x5, #1          // incrementar longitud

    // Agregar terminador nulo
    mov w3, #0              // ASCII para '\0'
    strb w3, [x1, x5]       // almacenar al final
  • Se agrega un salto de línea (\n) al final de la cadena.
  • Se agrega un terminador nulo (\0) al final de la cadena para marcar el final de la cadena de caracteres.

11. Subrutina: print_string (imprimir cadena)

print_string:
    mov x1, x0              // dirección de la cadena
    mov x2, #0              // contador de longitud

.count_loop:
    ldrb w3, [x1, x2]       // cargar byte actual
    cbz w3, .print          // si es cero (terminador nulo), terminar
    add x2, x2, #1          // incrementar contador
    b .count_loop

.print:
    mov x8, #64             // syscall write (64)
    mov x0, #1              // stdout (1)
    svc 0                   // llamada al sistema
    ret
  • print_string: Esta subrutina imprime una cadena que termina en un byte nulo (\0) en la consola. El proceso consiste en contar los bytes de la cadena hasta el terminador nulo y luego usar una llamada al sistema write para imprimir la cadena en la consola.

Resumen:

Este programa imprime los números del 9 al 43, uno por uno, cada uno en su propia línea. Para cada número:

  1. Se convierte el número a su representación ASCII.
  2. Se imprime el número como una cadena en la consola.
  3. El proceso se repite hasta que el número alcanza 44, momento en el cual el programa termina.