FORTH-K para ZX-81
-
- Amiga 1200
- Mensajes: 1393
- Registrado: 23 Dic 2008, 17:53
- Sistema Favorito: MSX
- primer_sistema: ZX81
- Primera consola: Atari 2600
- Gracias dadas: 3 veces
- Gracias recibidas: 20 veces
FORTH-K para ZX-81
EL PROGRAMA
Este programa es un pequeño intérprete de lenguaje FORTH, preparado para ser ejecutado en la versión básica del ZX-81.
Este intérprete reconoce las siguientes palabras:
números
Introduce en el stack números enteros y positivos de 1 byte comprendidos entre 0 y 255.
+
Saca los dos últimos números del stack, los suma y deja el resultado en el stack.
-
Saca los dos últimos números del stack, los resta y deja el resultado en el stack.
*
Saca los dos últimos números del stack, los multiplica y deja el resultado en el stack.
/
Saca los dos últimos números del stack, los divide y deja el resultado en el stack.
.
Saca el último número del stack y lo muestra por pantalla.
EMIT
Saca el último número del stack y muestra el carácter CHR$ correspondiente.
DUP
Duplica el último número del stack y lo deja en el stack.
OVER
Duplica el penúltimo número del stack y lo deja en el stack.
DROP
Borra el último número del stack.
DO
Inicio de un bucle desde el valor del último número del stack al del penúltimo. Los saca del stack.
Por temas de memoria, los bucles DO LOOP se deben partir en dos líneas. La primera con el DO y con su rango, y la segunda con la parte que debe ir ejecutando el LOOP hasta el final del bucle.
I
Introduce en el stack el valor del bucle DO.
LOOP
Incrementa en 1 el contador del bucle y vuelve al DO si no ha llegado al valor final.
SP
Cambia el puntero del stack al valor del último número del stack y lo saca del stack.
Ejemplos:
Calcula 10 – 4 y muestra el resultado por pantalla:
10 4 - .
Suma 8 más 8, lo multiplica por 3 y se muestra por pantalla:
8 DUP + 3 * .
Calcula y muestra la tabla del 5:
11 1 DO
I 5 * . LOOP
Calcula y muestra “2X3=6” en pantalla:
2 DUP . 61 EMIT 3 DUP . * 20 EMIT .
Muestra el texto “HELLO” en pantalla:
52 49 49 52 45 5 0 DO
EMIT LOOP
Comentarios y recomendaciones:
- No introducir valores numéricos superiores a 255 o de signo negativo.
- Los valores decimales se redondeados al introducirse en el stack.
- No introducir más de 33 números en el stack ya que puede provocar el cuelgue del equipo.
- No sacar del stack más números de los que se han introducido.
- Al salir del FORTH se pierden los números que haya en el stack.
- Si se ejecuta en un ZX-81 con 1K, intentar que la línea de entrada no tenga más de 35 caracteres para evitar un error 4.
- Si se ejecuta en un ZX-81 con 1K y la ejecución muestra muchos resultados en pantalla puede ocasionar un error 4.
- Con la palabra “SP” se puede modificar el puntero del stack y explorar los primeros 256 bytes de la RAM. Cuidado.
Descargar el juego en formato ".Z81" (Snapshot del EightyOne):
BLOQUES
He dividido el listado en 4 bloques:
- Inicializar variables principales.
- Procesador de la línea de entrada.
- Introducir un valor en el stack.
- Ejecución de las palabras de FORTH.
COMO FUNCIONA
A continuación detallo, línea por línea, el funcionamiento del programa.
Se utilizan las siguientes variables:
U – Variable que contiene el valor “1”.
B – Variable que contiene el puntero al inicio de la RAM a la que podemos acceder.
P – Variable que contiene el puntero del stack.
F – Variable para bucles.
R – Valor del último número del stack.
S – Valor del penúltimo número del stack, o un valor antes de introducirse en el stack
I – Variable para bucles: Valor inicial o actual.
E – Variable para bucles: Valor final.
A$ - Variable donde se guarda la línea que se está procesando.
W$ - Variable donde se guarda la palabra que se esta procesando, o una expresión antes de introducirse en el stack.
1 – Guardamos el valor 1 en la variable “U”. Se usará a lo largo del programa y permite ahorrar memoria.
2 – Guardamos el valor 59 en la variable “P”. Apunta a la posición actual del stack de FORTH.
4 – Guardamos el valor 16384 en la variable “B”. Apunta a la primera posición de memoria a la que podemos acceder.
6 – Inicializamos el valor de W$.
8 – Se guarda en A$ la línea de FORTH que se ha de procesar.
10 – Se borra la pantalla antes de la ejecución de la línea para ahorrar memoria.
12 – Se añade un espacio al final de la línea de entrada.
14 – Inicio del bucle que analiza la línea de entrada.
16 – Analiza la línea carácter a carácter. Si encuentra un espacio salta a la línea 24.
18 – Si hay algo en W$ salta a la línea 40 para procesar la palabra guardada en W$.
20 – Inicializa el valor de W$.
22 – Saltar a la línea 26.
24 – Añadir el carácter en W$.
26 – Si el bucle no ha llegado al final vuelve a la línea 14.
28 – Saltar a la línea 8.
30 – Guarda en W$ el valor de S. Lo usa la palabra “OVER”.
32 – Guarda en R el valor de W$.
34 – Incrementar el puntero del stack (P).
36 – Guarda en el stack el valor de R. Se usa como dirección la suma de los punteros B (memoria) y P (stack).
38 – Se vuelve al procesador de palabras.
40 – Si el primer carácter de W$ está entre “0“ y “9” se considera un número y se introduce en el stack saltando a 32.
42 – Guardamos en R el último número del stack.
44 – Guardamos en S el penúltimo número del stack.
46 – Si procesamos “OVER” saltamos a la línea 30.
48 – Si procesamos “DUP” saltamos a la línea 34.
50 – Si procesamos “DO” saltamos a la línea 80.
52 – Si procesamos “I” saltamos a la línea 84.
54 – Si procesamos “LOOP” saltamos a la línea 86.
60 – Si procesamos “+”, “-”, “ *” ó “/” guardamos en el stack el valor de la operación.
62 – Si procesamos “.” mostramos en pantalla el valor del último número del stack (R).
64 – Si procesamos “EMIT” mostramos en pantalla el carácter del último número del stack (R).
66 – Si procesamos “SP” modificamos el valor del puntero al stack (P) con el valor de (R).
68 – Decrementar el puntero del stack (P).
70 - Se vuelve al procesador de palabras.
80 – Guardamos en (I) el valor de (R). Usado para iniciar un bucle “DO”.
81 – Guardamos en (E) el valor de (S), para indicar el valor final del bucle.
82 – Decrementamos en 2 el valor del puntero al stack (P).
83 - Se vuelve al procesador de palabras.
84 – Guardamos en (R) el valor de (I), que indica el valor actual del bucle.
85 - Se vuelve al procesador de palabras.
86 – Incrementamos (I) en 1, que es el valor actual del bucle.
87 – Si (I) es menor que (E), el bucle no ha terminado y se pone (F) a 0. Es el contador del bucle del procesador.
88 - Se vuelve al procesador de palabras.
EL PROGRAMA
APUNTES FINALES
Después de los juegos “MINEFIELD-1K”, “SUDOKU-1K”, “LIGHTS OUT-1K” y “MAZE-K” le ha llegado el turno a un programa más serio. Esto de hacer programas en un ZX-81 con 1K se está volviendo un vicio.
Desde siempre me había hecho gracia el programa “Trans-Compilador 1K” que apareció en el número 30 de la revista “El Ordenador Personal” (página 135). Es un sencillo compilador que pasaba de BASIC a CM con muchas limitaciones.
Así que me decidí por un intérprete de lenguaje FORTH, pero a diferencia de la versión para CASIO PB-100, en este caso no lo he querido limitar al manejo del stack y he suprimido algunas de estas palabras para poder incluir bucles y una instrucción que nos permite modificar el puntero del stack. Esto hace que su uso sea más interesante, porque entre otras cosas, podemos movernos por la memoria RAM y modificar sus valores, con el riesgo de colgar el ordenador que ello comporta.
Metiendo un FORTH en 600 bytes
El ZX-81 básico dispone de 1024 bytes, de los que descontando los 125 bytes de la zona de variables del sistema y un mínimo de 25 bytes de la memoria de vídeo dejan 874 bytes libres.
El programa necesita 8 variables numéricas que ocupan 56 bytes más, y dos alfanuméricas que ocuparán en función de lo que se escriba en la línea de comandos.
El calculador y el tratamiento de cadenas necesitan memoria para funcionar y lo normal es que en la pantalla acabe apareciendo algún resultado, así que el programa no debería ocupar más de 600 bytes.
¿Y como se hace?
Lo primero ha sido introducir una línea con la que controlo la memoria que ocupa el programa en BASIC:
9999 PRINT (PEEK VAL"16396"+VAL"256"*PEEK VAL"16397")-VAL"16509"
Esta línea ocupa 43 bytes, que ganaré al borrarla al finalizar el desarrollo del programa.
Como siempre, he usado los trucos habituales del ZX-81 para ahorrar memoria en el uso de valores numéricos. Así, "NOT PI" es 0, uso de CODE y VAL, y como el valor 1 se usa varias veces, he asignado ese valor a la variable "U" mediante "SGN PI".
Para el stack aprovecho los 33 bytes del buffer de la impresora que está en la zona de las variables de sistema, a partir de la dirección 16444 de la RAM. Esto limita el tamaño de los números que maneja este FORTH a valores de 1 byte positivos (entre 0 y 255) pero consigo ahorrar mucha memoria. Salirse de este rango puede provocar el cuelgue del ZX-81. Peligroso, pero con su encanto.
A continuación he seleccionado las palabras de FORTH que quería implementar y las he ordenado, poniendo primero las palabras que incrementan los valores del stack y después las que lo decrementan. De esta forma hay una única línea para incrementar (línea 34) o decrementar (línea 68) el puntero del stack (variable P).
La palabra "DROP" funciona pero no está contemplada. Así, cualquier palabra introducida que no se reconozca actúa borrando el último valor del stack.
Antes de ejecutar una línea de comandos borro la pantalla para reducir la memoria de vídeo al mínimo (25 bytes) y se va llenando a medida que imprimimos valores por pantalla. Estos se muestran a uno por línea para evitar el espacio que los separa. De todas formas, si mostramos muchos valores o la línea es muy larga se puede producir un error 4 (falta de memoria) en el equipo básico con 1K. En un ZX-81 ampliado no hay problemas de memoria.
No se controla la posición del puntero del stack (P). Esto puede provocar un “crash” del equipo, pero amplia las posibilidades de este intérprete de FORTH.
Con todo, el intérprete es simple y lento, pero funciona. Así que... Prueba superada ¡!!
Os invito a probarlo.
Buscando la IP de la W.O.P.R.
¿Quién está conectado?
Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 11 invitados