FORTH-K para ZX-81

dancresp
Mensajes: 5091
Registrado: 13 Nov 2010 02:08
Agradecido : 37 veces
Agradecimiento recibido: 105 veces

FORTH-K para ZX-81

Mensajepor dancresp » 01 Abr 2014 00:19

forth_3.gif
forth_3.gif (39.55 KiB) Visto 2248 veces


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):
FORTH_K.rar
(1.05 KiB) Descargado 98 veces


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
listado.gif


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.

forth_1.gif
forth_1.gif (40.59 KiB) Visto 2248 veces

forth_2.gif
forth_2.gif (40.32 KiB) Visto 2248 veces

Avatar de Usuario
web8bits
Mensajes: 966
Registrado: 31 Oct 2010 10:34
Ubicación: Vigo
Agradecido : 84 veces
Agradecimiento recibido: 53 veces
Contactar:

Re: FORTH-K para ZX-81

Mensajepor web8bits » 01 Abr 2014 10:58

Me quito el sombrero, soberbio y fantásticamente bien explicado, como siempre un gran trabajo.

Avatar de Usuario
wilco2009
Mensajes: 1678
Registrado: 07 Ene 2013 16:48
Ubicación: Valencia
Agradecido : 57 veces
Agradecimiento recibido: 110 veces

Re: FORTH-K para ZX-81

Mensajepor wilco2009 » 01 Abr 2014 18:17

Genial!!!. Muy buen trabajo, si señor.
"Nada viaja a mayor velocidad que luz con la posible excepción de las malas noticias las cuales obedecen a sus propias leyes."

Douglas Adams. Guía de autoestopista galáctico.

Avatar de Usuario
ron
Mensajes: 17753
Registrado: 28 Oct 2010 14:20
Ubicación: retrocrypta
Agradecido : 706 veces
Agradecimiento recibido: 761 veces

Re: FORTH-K para ZX-81

Mensajepor ron » 01 Abr 2014 19:41

Bravo Dancresp !!! ;-)

FloppySoftware

Re: FORTH-K para ZX-81

Mensajepor FloppySoftware » 01 Abr 2014 21:21

Anda qué chulo!

Avatar de Usuario
mj8bit
Mensajes: 183
Registrado: 07 Jul 2011 12:12
Ubicación: Ecija
Agradecido : 10 veces
Agradecimiento recibido: 3 veces

Re: FORTH-K para ZX-81

Mensajepor mj8bit » 01 Abr 2014 22:01

Mi ignorancia no me deja valorar esta exposición. Como todas las que haces. Enhorabuena!!!

Avatar de Usuario
apple2man
Mensajes: 262
Registrado: 03 Jun 2011 13:53
Agradecimiento recibido: 12 veces

Re: FORTH-K para ZX-81

Mensajepor apple2man » 01 Abr 2014 22:19

Como siempre es un placer revisar los desarrollos que presentas, pero una vez más no dejas de sorprenderme. Cuando he empezado a leerlo he pensado "no es posible meter un intérprete de Forth" en el ZX-81, pero cuando he continuado leyendo y me ha parecido cada vez más atractivo e interesante.
Veo que te atrae esta máquina precisamente por lo limitada que es y por el reto que ello supone para programar cualquier cosa. Recuerdo el ajedrez para este micro, metido en menos de 1 Kb y recuerdo el programa Microchess, de Peter Jennings, que salió íntegro para el Kim-1 todo en código del 6502. Me parecía un reto increíble programar un ajedrez sobre 1 Kb. Lo bueno es que juegan aceptablemente!
Comparto contigo el interés por estas máquinas más primigenias, cómo exprimen el ingenio del que las usa!

dancresp
Mensajes: 5091
Registrado: 13 Nov 2010 02:08
Agradecido : 37 veces
Agradecimiento recibido: 105 veces

Re: FORTH-K para ZX-81

Mensajepor dancresp » 02 Abr 2014 00:54

Apple2man escribió:Veo que te atrae esta máquina precisamente por lo limitada que es y por el reto que ello supone para programar cualquier cosa.

Cierto, en este aspecto es una máquina "casi" única.
Los desarrollos son rápidos, pero te destrozan el cerebro. -banghead

De todas formas, tengo casi listo otro programa de 1K... que aún no me lo creo. -shock

Avatar de Usuario
ron
Mensajes: 17753
Registrado: 28 Oct 2010 14:20
Ubicación: retrocrypta
Agradecido : 706 veces
Agradecimiento recibido: 761 veces

Re: FORTH-K para ZX-81

Mensajepor ron » 02 Abr 2014 23:15

Gran hilo !!!

A colación de lo comentado por Apple][Man, en la revista " Your Computer " de febrero de 1983 David Horne publicó el código y su explicación en un artículo extraordinario.

El programa se desarrolló en una máquina dotada con 3KB pero lo fascinante es como lo sintetizó para encajarlo en una sola K. Ya se que la curiosidad mató al gato ---> http://users.ox.ac.uk/~uzdm0006/scans/1kchess/

One further point should be explained. It is not possible to give a good opening or finish to the game because that would require slightly more code than we have available in the 1K game. We actually have only 672 bytes. The game, therefore, starts off with the computer playing white and either the Kings pawn or the Queens pawn moved forward one position. The following describes the machine code and techniques used in the creation of my 1K ZX-81 chess program. In order to produce the code you will require a machine with at least 3K of memory. The code has been created using a 3K machine, there should be no problems using 16K if the procedures given are followed and RAMtop is lowered to 1K before loading from tape.



Imagen

dancresp
Mensajes: 5091
Registrado: 13 Nov 2010 02:08
Agradecido : 37 veces
Agradecimiento recibido: 105 veces

Re: FORTH-K para ZX-81

Mensajepor dancresp » 03 Abr 2014 17:01

ron escribió:A colación de lo comentado por Apple][Man, en la revista " Your Computer " de febrero de 1983 David Horne publicó el código y su explicación en un artículo extraordinario.

El programa se desarrolló en una máquina dotada con 3KB pero lo fascinante es como lo sintetizó para encajarlo en una sola K. Ya se que la curiosidad mató al gato ---> http://users.ox.ac.uk/~uzdm0006/scans/1kchess/

Hombre ron y apple2man, estáis hablando de algo que simplemente creo que es insuperable.

He jugado a ese ajedrez, y no ganará a kasparov, pero está claro que funciona.

Incluso me tomé la libertad de remaquetar el PDF, que tengo impreso en una versión más "ordenada".
Aquí tenéis el enlace:
ZX-81 1K Chess - PDF.rar
(188.73 KiB) Descargado 175 veces


Sea como sea, hoy he subido un ensamblador que funciona con 1K y ensambla el 54% de los mnemotécnicos del Z80.
Lo reconozco, me siento realmente orgulloso. -thumbup

Avatar de Usuario
Chema
Mensajes: 1748
Registrado: 21 Jun 2012 20:13
Ubicación: Gijón
Agradecido : 690 veces
Agradecimiento recibido: 267 veces
Contactar:

Re: FORTH-K para ZX-81

Mensajepor Chema » 03 Abr 2014 17:31

Yo lo flipo contigo. Un intérprete de Forth en ese espacio!! Eres un monstruo.


Volver a “Lenguajes de Programación y herramientas Dev”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado