GNU/Linux xterm-256color bash 171 views

Este código en ARM64 Assembly calcula el factorial de un número (en este caso, 5), lo convierte en una cadena de texto, y lo imprime por pantalla usando llamadas al sistema (syscalls).


📦 .section .data

buffer: .space 20  // Reservamos espacio para un buffer de 20 bytes

Aquí se declara un espacio de memoria llamado buffer de 20 bytes. Este se usará para guardar el número convertido en string.


⚙️ .section .text y _start

.global _start
_start:
    mov x0, #5       // Número cuyo factorial queremos calcular
    mov x1, #1       // Acumulador (resultado)
  • x0 = 5: el número del cual se calculará el factorial.
  • x1 = 1: será el acumulador del resultado (1 * 2 * 3 * ... * x0).

🔁 Bucle para calcular el factorial

factorial_loop:
    cmp x0, #1
    ble end_factorial
    mul x1, x1, x0
    sub x0, x0, #1
    b factorial_loop
  1. Compara x0 con 1.
  2. Si x0 ≤ 1, termina el bucle (ble end_factorial).
  3. Multiplica el acumulador (x1) por x0.
  4. Decrementa x0.
  5. Repite.

✅ Resultado: el factorial de 5 (5×4×3×2×1 = 120) estará en x1.


🔢 Convertir el entero en x1 a string

end_factorial:
    mov x0, x1       // Pasamos el resultado a x0
    ldr x1, =buffer  // Dirección del buffer
    bl int_to_str    // Llamamos a la función de conversión
  • Prepara los argumentos para la función int_to_str(x0, x1):
    • x0: número a convertir
    • x1: puntero al buffer donde guardar la cadena

🖨️ Escribir el string en pantalla

    mov x0, #1       // stdout (fd = 1)
    ldr x1, =buffer  // puntero al string
    mov x2, #20      // Longitud máxima estimada
    mov x8, #64      // syscall write
    svc #0
  • Realiza una syscall para escribir en stdout:
    • x0: descriptor de archivo (1 = stdout)
    • x1: puntero al mensaje
    • x2: longitud máxima (20)
    • x8: número de syscall 64 (write)
    • svc #0: realiza la syscall

🛑 Salida del programa

    mov x8, #93      // syscall exit
    svc #0
  • x8 = 93: syscall exit.
  • svc #0: llamada al sistema.

🧠 Función: int_to_str

Convierte un número (en x0) a cadena en el buffer (x1).

int_to_str:
    mov x2, x1
    add x1, x1, #19  // Final del buffer
    strb wzr, [x1]   // Escribe terminador nulo '\0'
    sub x1, x1, #1   // Retrocede para empezar a escribir

    mov x5, #10      // Para división por 10

Ahora entra en un bucle:

int_to_str_loop:
    mov x3, x0
    udiv x0, x3, x5      // Cociente
    msub x4, x0, x5, x3  // Resto (x4 = x3 - x0 * 10)
    add x4, x4, #48      // Convierte a ASCII
    strb w4, [x1]        // Guarda carácter
    sub x1, x1, #1       // Retrocede el puntero
    cmp x0, #0
    bne int_to_str_loop

Este bucle:

  • Divide el número por 10 (x0 = x0 / 10).
  • Obtiene el dígito más a la derecha (x4 = resto).
  • Lo convierte a su equivalente ASCII (+48).
  • Lo guarda en el buffer.
  • Se repite hasta que el número sea 0.

Finalmente:

    add x1, x1, #1   // Ajusta el puntero al inicio del string
    ret

🧪 Ejemplo de ejecución

  • Calcula factorial(5) = 120
  • Convierte 120 a string: '120\0'
  • Lo escribe en pantalla.