Me gustaría crear un curso del ensamblador x86_64, es decir de 64 bits. Pero en lugar de ver texto en tu terminal, editar pixeles, viendo cómo puedes colorear pixeles de una ventana.
El curso es similar al del canal “Profesor Retroman”, pero el hizo uno del ensamblador de 8 bits para amstrad cpc (similar al comodoro 64), mientras que yo lo intentaré hacer en 64 bits (para linux).
Requisitos:
Tener make instalado en tu sistema.
Un ensamblador (puede ser nasm o yasm, se consiguen en pacman, apt-get o yay).
Un linker (puede ser ld del linker de gcc).
La biblioteca de gráficos, tinyPTC, puedes compilarla descargando:
Descargas y descomprimes la .zip.
Hacerle make a secas, esto generara una biblioteca estática .a.
Crear la carpeta dónde estaremos trabajando, y mueves la .a ahí.
Para compilar y enlazar:
yasm -f elf64 main.asm
Puede ser con nasm, donde yasm (o nasm) con “-f elf64” para el formato del binario y el punto .asm, dónde estará el código ensamblador.
ld main.o libtinyptc.a -I. -lX11 -lc -lm --dynamic-linker /usr/lib64/ld-linux-x86-64.so.2 -o a
Para enlazar, el linker ld, llamar decir dónde esta libtinyptc.a (puede estar en un directorio) y luego algunas dependencias:
-lc (estandar de c)
-lm (funciones matematicas)
-lX11 (para los graficos)
–dynamic-linker /usr/lib64/ld-linux-x86-64.so.2 (si no nuestro ejecutable no sabrá cómo se cargan las bibliotecas dinámicas .so)
Pues, ahora que tenemos a tinyPTC y el ensamblador, pintemos un pixel.
Empecemos marcando la rutina (función) principal y las funciones externas:
global _start
extern ptc_open
extern ptc_update
extern ptc_process_events
extern ptc_close
Luego la sección .text y punto .bss:
section .text
_start:
mov rdi, title
mov rsi, 640
mov rdx, 360
call ptc_open ;; crea una ventana X11
mainloop: ;; inicio del bucle principal, todo con etiquetas
;; No existen funciones, solo etiquetas
lea rdx, [rel screen + 640 * 1200 + 1200] ;; Calcula la direccion de de memoria de la memoria de video, calculando una cordenada
;; Ya que cada pixel son 4 bytes, 1200 / 4 = 300 por ende, el pixel se dibujará en las coordenadas (300,300)
mov [rdx], DWORD 0x00ff0000 ;; Carga en el primer pixel el color rojo
lea rdi, [rel screen] ;; Calcula la direccion de la memoria de video
call ptc_update ;; actualiza la ventana
call ptc_process_events ;; Revisa si se cierra la ventana
test rax, 0x00 ;; Si ptc_process_events devuelve cero
je mainloop ;; Si el anterior es igual, salta, si no continua abajo
call ptc_close ;; termina con la ventana X11
mov rax, 60 ;; termina con el proceso de nuestro programa
xor rdi, rdi
syscall
section .bss
screen: resd 640*360 ;; Nuestra "memoria de video"
section .data
title: db "My Window!",0x00 ;; Nombre de la ventana, termina en 0x00 (NULL)
Pues en la seccion .bss se creo la “memoria de video” con el ancho y alto de la ventana (cada pixel son 4 bytes).
con lea rdx, [rel screen]
le digo que calcule la dirección de memoria de la etiqueta screen (la de la “memoria de video”) a partir del registro de ejecución del programa y lo guarde en el registro rdx.
Luego, con mov [rdx], DWORD 0x00ff0000
le digo que cargue el valor 0x00ff0000 (hexadecimal) a dónde apunte rdx, el cual equivale al primer pixel, si le sumo 4 (con, por ejemplo add rdx, 4
) llego al siguiente pixel.
El valor 0x00ff0000 significa
0x → que es un valor hexadecimal
00 → alpha
ff → red
00 → green
00 → blue
Del “rgb”
El primero es la transparencia, 00 es desactivado, y los otros 3, de dos digitos en dos, son rgb, representando numeros del 00 al ff para cada color:
00 → sin ese color
0x00ff0000 → rojo
0x0000ff00 → verde
0x000000ff → azul
Para expandir y resolver dudas, puede visitar:
https://cs.lmu.edu/~ray/notes/nasmtutorial/
O, preguntarme por aquí, que estaría encantado de responderlas, si sabes más de ensamblador que yo, puedes aportar.
No puedes usar un call dentro de una rutina que llamaste con un call, hasta que no explique cómo funciona la pila, ya que tras el primer call la pila se te va a desalinear y te tirara una violación de segmento. Solo puedes llamar a una función a la vez, sin funciones dentro de funciones hasta no ver la pila.
Ejercicios:
1_ Colorea todo el fondo
2_ Haz mover el pixel