Programación en el Spectrum

z80-asm assembler


En este tutorial vamos a intentar introducir al lector en la creación de nuevos programas en ensamblador para el micro Z80 (y por lo tanto para Spectrum, aunque también podría usarse para Amstrad, MSX, etc.). El tutorial será muy básico porque se sobreentiende que el lector ya tiene ciertos conocimientos de programación o de Informática.

El objetivo de este tutorial no es enseñar ensamblador (aunque a lo largo del mismo hay varios enlaces a pequeños cursos) sino mostrar qué herramientas podemos usar para crear nuestros programas y ejecutarlos en el Spectrum.


Qué es un ensamblador

Un ensamblador es un programa que convierte nuestro programa escrito en lenguaje ensamblador (instrucciones) en los opcodes que el microprocesador debe ejecutar directamente. Es decir, se sigue el siguiente proceso:

1.- Escribimos un programa en ensamblador en nuestro editor de textos favorito en un fichero .asm (como por ejemplo, programa.asm). Un programa en ensamblador de z80 tiene un aspecto similar al siguiente:


; Pruebas de ensamblador para z80-asm
; Santiago Romero aka NoP/Compiler

        ORG 40000
        LD HL, 16384
        LD A, 162
        LD (HL), A
        LD DE, 16385
        LD BC, 6911
        LDIR
        RET
 
Como podeis ver, lo que empieza por el caracter ';' son comentarios (es decir, son para aclarar cosas en el programa pero luego el assembler los ignora al crear el binario). El resto son instrucciones en ensamblador de Z80.

2.- Una vez escrito el programa, lo ENSAMBLAMOS con el ensamblador que usemos. Esto generará código binario (.bin) listo para usar en el ordenador en que lo vayamos a usar. Por ejemplo, yo uso el z80-asm y pondría algo así como:

 
 z80-asm programa.asm 40000:programa.bin
 
Cabe destacar en el ejemplo anterior que programa.asm es el programa escrito en instrucciones de ensamblador, que programa.bin es el código binario resultante que el micro de z80 es capaz de ejecutar, y que el 40000 es la dirección donde queremos colocar ese código (40.000 es una zona libre de los 48K del Spectrum, y podemos poner ahi nuestro programa).

Si tenemos errores (hemos tecleado algo mal, la sintaxis de alguna instrucción es incorrecta, etc.) editamos de nuevo el .asm, corregimos los fallos y lo volvemos a ensamblar.

Otra cosa a destacar es que hay 2 tipos de ensambladores, los nativos y los cruzados. Los nativos los ejecutamos en el mismo ordenador en que editamos el codigo y ejecutamos el programa. Por ejemplo, si programamos para Spectrum, editariamos el fichero con un editor de Spectrum, lo ensamblariamos (a cinta o disco) con un ensamblador de Spectrum, y lo ejecutaríamos en el mismo Spectrum.

Un ensamblador cruzado, por contra, es un programa que corre en un ordenador distinto al que estamos programando. Por ejemplo, yo edito un fichero en mi PC, lo compilo en mi PC, y me genera un fichero que me llevo al Spectrum para ejecutarlo.

3.- Ahora ya tenemos un .bin que es código que directamente entiende el microprocesador destino que estamos programando. Ese .bin lo podríamos llevar (vía cinta o vía emulador) a un Spectrum y meterlo en memoria (con POKES) y saltar a ejecutarlo (con RANDOMIZE USR) o bien simplemente usar el bin2tap que nos generará una cinta (.tap) con nuestro código de forma que al cargarla se ejecuta él solito:

 
 bin2tap programa.bin programa.tap
 
Ahora si cargamos el tap en el emulador o en el Spectrum real, nuestro programa se ejecutará. Y ese programa puede ser una utilidad, un juego, etc.

Posteriormente daré enlaces para descargar todos estos programas.


Descargando el ensamblador

Existen muchísimos ensambladores de Z80, tanto nativos como cruzados.

Nativos

Cruzados


Esqueleto de un programa en assembler

Veamos el esqueleto de un programa en ASM, es decir, el texto básico en el cual pondremos las instrucciones de nuestro programa.


; Cabecera del programa: titulo, fecha, autor...
; También se usa dentro del código para poner comentarios

; El org indica dónde se ubica el codigo cuando lo
; vayamos a cargar en el Spectrum. Puede ser en cualquier
; lugar más allá de la ROM y videomemoria.
        ORG 30000

;
; Aquí va el codigo de nuestro programa
;

        RET
Una vez creado nuestro programa (necesitaremos saber asm para ello, y saber qué queremos hacer, y hacerlo :), lo guardamos como .asm y lo ensamblamos:


 z80-asm programa.asm 30000:programa.bin
Y una vez hecho esto se creará un fichero programa.bin. Si desensamblaramos ese .bin con un desensamblador nos saldría justo el código fuente del programa original del fichero.asm.

Ahora supongamos que queremos llevar ese código a un emulador o Spectrum real para probarlo. Usaremos para ello bin2tap, que coge un código binario, le pone un cargador en BASIC (para meterlo en memoria y saltar a él) y nos crea un tap listo para cargar en el emulador o pasar a cinta.


 bin2tap programa.bin programa.tap
Cargamos el .tap en el emulador y... se ejecuta nuestro programa.


Aprendiendo ensamblador

Para poder programar en ensamblador de z80 necesitaremos aprender ensamblador antes. Veamos algunos tutoriales de Internet:

Vamos a analizar un poco mejor el programa original (o parecido) que hemos ensamblado al principio de este artículo...:


; Pruebas de ensamblador para z80-asm
; Santiago Romero aka NoP/Compiler

        ORG 40000
        LD HL, 16384
        LD A, 162
        LD (HL), A
        LD DE, 16385
        LD BC, 6911
        LDIR
        RET
¿Qué hace este programa? Bajároslo como ejemplo1.asm, ensambladlo con z80-asm ejemplo1.asm 40000:ejemplo1.bin, convertidlo a tap con bin2tap ejemplo1.bin ejemplo1.tap y cargadlo en un emulador (podeis obtener el tap directamente aquí).

(Nota: Para los que trabajen en otros formatos y no quieran usar bin2tap pueden crearse un cargador que contenga código como:

 
   LOAD "codigo.bin" CODE 40000
   RANDOMIZE USR 40000
 
)

Su resultado es, como vereis al cargarlo en el Spectrum o en un emulador, que llena la pantalla de pixels extraños y de colores. Esto es así porque el programa lo que hace es llenar la videomemoria del Spectrum con el valor 162. Es decir, le pone el valor 162 a los 6912 bytes que hay a partir de 16384 (la memoria de vídeo del Spectrum) con lo cual ese valor 162 aparece en pantalla como pixels, y es que 162 = 10100010 en binario, y como en Spectrum cada bit equivale a un pixel, tendremos un pixel encendido, otro apagado, otro encendido, 3 seguidos apagado, otro encendido y el ultimo apagado, y así todo el rato y para toda la pantalla.


ejemplo1


A  = 162    ; esto es lo que escribiremos en memoria

HL = 16384  ; Donde escribiremos inicialmente eso

[HL] = A    ; Escribimos A en la dirección apuntada por HL

DE = 16385  ; 16384 es donde empieza la memoria de vídeo del
            ; Spectrum, al escribir ahi estamos modificando
            ; el contenido de la pantalla, por eso luego salen
            ; caracteres extraños y colores en pantalla
            
BC = 6911   ; cuantos bytes vamos a escribir

LDIR        ; Esta instrucción repite BC veces (es decir, 6911
            ; veces en nuestro caso) lo siguiente:
            ;
            ; Poner en la dirección de memoria apuntada por DE
            ; el valor que esté en la direccion de memoria
            ; apuntada por HL, e incrementar DE y HL.
            ; 
            ; Esto pondría el valor de A (162) en la dirección
            ; 16384, incrementaría DE y decrementaría BC, con
            ; lo cual la siguiente escritura se haría en 16385,
            ; y así hasta que BC sea cero. Es decir, llenamos
            ; 6912 bytes a partir de 16384 con el valor 162.

RET         ; Fin del programa, volvemos :)

Podeis ver todas las instrucciones que soporta z80-asm en el fichero z80asm.txt donde se ven ejemplos de uso de etiquetas, instrucciones aceptadas, opciones de línea de comandos y el formato del binario resultante creado.

Para que puedas apreciar la diferencia de velocidad con BASIC he reescrito el mismo programa que antes pero en BASIC (usando POKE para escribir en memoria). Con el programa bas2tap he creado el fichero ejemplo1-bas.tap de forma que puedas comprobar la diferencia de velocidad con la versión ASM que hemos visto antes (ejemplo1.tap).

  10 FOR n=16384 TO 23295
  20 POKE n, 162
  30 NEXT n
 

Ejecutad ambos códigos (cargando los 2 taps) y notad la "diferencia" (por llamarlo de alguna forma) de velocidad entre ambos.


Programas de ejemplo

Algunos ejemplos de código ASM en Internet:

Si quieres contribuir con algún programa de ejemplo contacta con el autor de esta página :-)


En resumen

Este tutorial muestra cómo podemos ensamblar un listado en .asm y ejecutarlo en el Spectrum con herramientas de PC (o de Spectrum). El resto ahora lo debes aportar tú, es decir, hacer buenos programas para Spectrum utilizando las herramientas que hemos visto.




Subir al principio de esta página

Santiago Romero alias NoP
sromero©gmail·com
Ultima actualización : 11-03-2005