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_stringpara 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 sistemawritepara 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:
- Se convierte el número a su representación ASCII.
- Se imprime el número como una cadena en la consola.
- El proceso se repite hasta que el número alcanza 44, momento en el cual el programa termina.