Skip to content

Instantly share code, notes, and snippets.

@Alex-JAML
Created April 8, 2025 04:43
Show Gist options
  • Save Alex-JAML/1f7738fdb73059c865d031eaa68f3658 to your computer and use it in GitHub Desktop.
Save Alex-JAML/1f7738fdb73059c865d031eaa68f3658 to your computer and use it in GitHub Desktop.
Codigo Assembly ARM64 Hola Mundo para RaspbianOS
/*
* ---------------------------------------------------------------------------------
* Lenguajes de Interfaz en TECNM Campus ITT
* Autor: [Jorge Alejandro Martinez Lopez]
* Fecha: [2025-04-07]
* Descripción: Este programa imprime la tabla de multiplicar del 12 (del 12 x 1 al 12 x 12),
* mostrando cada línea en el formato "12 x b = c".
* Demostración: [ASCIINEMA.ORG/.....]
* ---------------------------------------------------------------------------------
*/
/*
* ----------------------------------------------
* C# "Tabla del 12" para Desarrolladores Embebidos (Referencia)
* ----------------------------------------------
* using System;
*
* class Program {
* static void Main() {
* Console.WriteLine("Tabla del 12:");
* for (int i = 1; i <= 12; i++) {
* Console.WriteLine("12 x {0} = {1}", i, 12 * i);
* }
* }
* }
*/
.global _start
/* --------------------------------------------------------------------
* Sección de datos: Constantes y mensajes fijos
* --------------------------------------------------------------------
*/
.section .data
prefix: .ascii "12x" // Prefijo fijo
prefix_len = . - prefix // Longitud de "12x"
infix: .ascii " = " // Texto intermedio
infix_len = . - infix // Longitud de " = "
newline: .ascii "\n" // Salto de línea
newline_len = . - newline // Longitud de "\n"
/* --------------------------------------------------------------------
* Sección BSS: Buffer para formar la línea de salida.
* Se reserva 64 bytes.
* --------------------------------------------------------------------
*/
.section .bss
.lcomm outBuffer, 64
/* --------------------------------------------------------------------
* Sección de texto: Código principal y subrutinas
* --------------------------------------------------------------------
*/
.section .text
_start:
// x19 = multiplicador (i) comienza en 1
mov x19, #1
print_loop:
// Si se han impreso 12 líneas, salir
cmp x19, #13
beq exit_program
// Calcular el producto: x20 = 12 * (valor en x19)
mov x0, x19 // x0 = multiplicador
mov x1, #12
mul x20, x0, x1 // x20 = producto
// Se arma la línea en outBuffer:
// outBuffer = "12x" + [multiplicador] + " = " + [producto] + "\n"
ldr x9, =outBuffer // x9 apunta al buffer (se reinicia cada iteración)
// 1. Copiar el prefijo "12x" (la subrutina ya incrementa x9)
ldr x1, =prefix // x1 apunta a "12x"
mov x2, prefix_len // longitud = 3
bl memcpy_copy
// 2. Convertir el multiplicador (1 o 2 dígitos) a cadena
// Se pasa el número en x0 y el destino en x1 (x1 se conserva como x9 actual)
mov x0, x19 // multiplicador en x0
mov x1, x9 // x1 = posición actual en el buffer
bl convert_mult // devuelve en x2 la cantidad de dígitos escritos
add x9, x9, x2 // Se avanza x9 según cantidad de dígitos escritos
// 3. Copiar el intermedio " = "
ldr x1, =infix
mov x2, infix_len
bl memcpy_copy
// 4. Convertir el producto (hasta 3 dígitos) a cadena
mov x0, x20 // Producto en x0
mov x1, x9 // x1 = posición actual en el buffer
bl convert_product // Convierte y devuelve la cantidad de dígitos en x2
add x9, x9, x2 // Avanza el buffer
// 5. Copiar el salto de línea "\n"
ldr x1, =newline
mov x2, newline_len
bl memcpy_copy
// Calcular la longitud total de la línea: (x9 - outBuffer)
ldr x3, =outBuffer
sub x3, x9, x3
// Realizar la llamada al sistema para escribir en stdout (fd 1)
mov x0, #1 // stdout
ldr x1, =outBuffer // puntero al buffer
mov x2, x3 // longitud de la línea
mov x8, #64 // syscall: write
svc #0
// Incrementar el multiplicador e iterar
add x19, x19, #1
b print_loop
exit_program:
// Salir con código 0
mov x0, #0
mov x8, #93 // syscall: exit
svc #0
/* --------------------------------------------------------------------
* Subrutina: memcpy_copy
* Copia x2 bytes desde la dirección en x1 al destino apuntado por x9.
* Nota: Esta subrutina avanza el puntero x9 internamente.
* --------------------------------------------------------------------
* Entradas:
* x1 = puntero a la fuente
* x2 = número de bytes a copiar
* x9 = puntero al destino (se actualiza internamente)
* Salida:
* x9 apunta al final del bloque copiado.
* --------------------------------------------------------------------
*/
memcpy_copy:
cmp x2, #0
beq memcpy_done
copy_loop:
ldrb w3, [x1], #1 // Cargar byte y post-incrementar x1
strb w3, [x9], #1 // Almacenar byte y post-incrementar x9
subs x2, x2, #1
bne copy_loop
memcpy_done:
ret
/* --------------------------------------------------------------------
* Subrutina: convert_mult
* Convierte el número en x0 (multiplicador, de 1 a 12) a una cadena ASCII.
* Se asume que el número tiene 1 o 2 dígitos.
* Entrada:
* x0 = número a convertir (multiplicador)
* x1 = puntero al buffer destino donde se escribirá la cadena
* Salida:
* x2 = cantidad de dígitos escritos (1 o 2)
* --------------------------------------------------------------------
*/
convert_mult:
cmp x0, #10
blt cm_one_digit
// Caso de dos dígitos:
mov x3, #10
udiv x4, x0, x3 // x4 = dígito de las decenas
msub x5, x4, x3, x0 // x5 = dígito de las unidades (x0 - x4*10)
// Convertir dígito de las decenas a ASCII usando x10 como temporal
mov w10, w4
add w10, w10, #'0'
strb w10, [x1]
add x1, x1, #1
// Convertir dígito de las unidades a ASCII
mov w10, w5
add w10, w10, #'0'
strb w10, [x1]
mov x2, #2
ret
cm_one_digit:
add w0, w0, #'0'
strb w0, [x1]
mov x2, #1
ret
/* --------------------------------------------------------------------
* Subrutina: convert_product
* Convierte el número en x0 (producto, máximo 144) a su representación ASCII.
* Maneja casos de 1, 2 o 3 dígitos.
* Entrada:
* x0 = número a convertir (producto)
* x1 = puntero al buffer destino donde se escribirá la cadena
* Salida:
* x2 = cantidad de dígitos escritos
* --------------------------------------------------------------------
*/
convert_product:
cmp x0, #10
blt cp_one_digit
cmp x0, #100
blt cp_two_digit
// Caso de tres dígitos:
mov x3, #100
udiv x4, x0, x3 // x4 = dígito de las centenas
msub x5, x4, x3, x0 // x5 = residuo (parte de decenas y unidades)
mov x6, #10
udiv x7, x5, x6 // x7 = dígito de las decenas
msub x8, x7, x6, x5 // x8 = dígito de las unidades
// Escribir dígito de las centenas
mov w10, w4
add w10, w10, #'0'
strb w10, [x1]
add x1, x1, #1
// Escribir dígito de las decenas
mov w10, w7
add w10, w10, #'0'
strb w10, [x1]
add x1, x1, #1
// Escribir dígito de las unidades
mov w10, w8
add w10, w10, #'0'
strb w10, [x1]
mov x2, #3
ret
cp_two_digit:
// Caso de dos dígitos:
mov x3, #10
udiv x4, x0, x3 // x4 = dígito de las decenas
msub x5, x4, x3, x0 // x5 = dígito de las unidades
// Escribir dígito de las decenas
mov w10, w4
add w10, w10, #'0'
strb w10, [x1]
add x1, x1, #1
// Escribir dígito de las unidades
mov w10, w5
add w10, w10, #'0'
strb w10, [x1]
mov x2, #2
ret
cp_one_digit:
// Caso de un dígito:
add w0, w0, #'0'
strb w0, [x1]
mov x2, #1
ret
@IoTeacher
Copy link

Fue agradable su estilo de bloque para documentar el codigo yo le sumaria arriba el "Asciinema" y poner un poco mas de cometnarios

@IoTeacher
Copy link

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment