FORTH para Sinclair ZX-80 1K

dancresp
Mensajes: 5779
Registrado: 13 Nov 2010 02:08
Agradecido : 405 veces
Agradecimiento recibido: 550 veces

FORTH para Sinclair ZX-80 1K

Mensajepor dancresp » 27 Oct 2022 00:12

Forth_Table7.png
Forth_Table7.png (1.98 KiB) Visto 747 veces


EL PROGRAMA
Este programa es un sencillo intérprete de lenguaje FORTH, preparado para ser ejecutado en la versión básica del ZX-80.

El intérprete procesa valores numéricos y ejecuta las siguientes 24 palabras:

Número
Introduce en el stack un número entero de 2 bytes comprendido entre -32768 y 32767.

+
Saca los dos últimos números del stack, los suma y pone el resultado en el stack.

-
Saca los dos últimos números del stack, los resta y pone el resultado en el stack.

*
Saca los dos últimos números del stack, los multiplica y pone el resultado en el stack.

/
Saca los dos últimos números del stack, los divide y pone el resultado en el stack.

.
Saca el último número del stack y lo muestra en pantalla.

EMIT
Saca el último número del stack y muestra su carácter CHR$ en pantalla.

SPACE
Muestra un espacio en la pantalla a continuación del último carácter.

CR
Hace un salto de línea en la pantalla. Si llega a la zona inferior de la pantalla se detiene el programa.

CLS
Borra el contenido de la pantalla.

DUP
Duplica el último número del stack y lo guarda en el stack.

OVER
Duplica el penúltimo número del stack y lo guarda en el stack.

SWAP
Intercambia el orden de los dos últimos números del 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.

I
Guarda en el stack el valor actual del bucle DO.

LOOP
Incrementa en 1 el contador del bucle y vuelve al DO si no ha llegado al valor final.

=
Compara los dos últimos números del stack y guarda en el stack un 1 si son iguales o un 0 si son distintos.

>
Compara los dos últimos números del stack y guarda en el stack un 1 si el penúltimo es mayor que el último o un 0 si no lo es.

<
Compara los dos últimos números del stack y guarda en el stack un 1 si el penúltimo es menor que el último o un 0 si no lo es.

IF
Inicio de un bloque condicional. Saca el último número del stack, si es 1 continúa con la ejecución del programa, y si es 0 salta hasta encontrar la palabra THEN.

THEN
Indica el final de una condición IF.

KEY
Pide la introducción de un carácter y guarda su código CHR$ en el stack.
Por limitaciones en el BASIC del ZX-80, no sigue el funcionamiento estándar y en lugar de pulsar una tecla, hay que introducir la tecla y pulsar ENTER.

RND
Saca el último número del stack, genera un número aleatorio entre 1 y ese número y lo guarda en el stack.

?
Saca el último número del stack y guarda en el stack el valor de esa posición de memoria.
Por limitaciones en el juego de caracteres del ZX-80, no se usa el carácter estándar.

Descargar el intérprete en formato ".o":
Forth.zip
(727 Bytes) Descargado 14 veces

Descargar fichero con 3 ejemplos en formato ".o":
Forth_Samples.zip
(2.27 KiB) Descargado 11 veces


Características del intérprete FORTH:
En un ZX-80 con 1K, quedan unos 200 bytes libres. Esta memoria se debe distribuir entre el código FORTH y la memoria de vídeo. Así, si el código FORTH es corto, podrá mostrar mucha información en pantalla, o menos si el código es más largo.

El código FORTH se debe introducir en la primera línea del programa BASIC, como contenido de un REM. Esto nos permite escribir y editar libremente su contenido. Las diferentes palabras o valores numéricos se deben separar con un espacio. Si se introduce más de un espacio, el intérprete los irá guardando en el stack como un valor numérico 0.

Ejemplo para ejecutar un programa que muestra por pantalla los números del 1 al 10:

1 REM 11 1 DO I . LOOP

Una vez introducido el código FORTH en la primera línea del programa, se ejecutar con un simple RUN. Si todo va bien, acabará la ejecución con un código “2/22” al pie de la pantalla. Se pueden introducir distintas líneas REM entre las líneas 2 y 7, pero el intérprete solo ejecutará el contenido de la primera línea.

El stack está limitado, por defecto a 8 números, pero se puede modificar el tamaño cambiando el valor del DIM de la línea 8.
Si se intentan introducir o sacar del stack más números de los disponibles el intérprete producirá un error 3.

El intérprete no permite anidar bucles DO ni condiciones IF. Tampoco controla que el código contenga la palabra de cierre de estas estructuras.

Programar un intérprete de FORTH en un BASIC interpretado de un equipo tan “rápido” como el ZX-80... afecta al rendimiento. Con todo, a modo de ejemplo, el código FORTH de la tabla de multiplicar por 7 que ilustra este artículo se ejecuta en 23 segundos. Eso sí, es lento, pero seguro.


BLOQUES
He dividido el listado en 4 bloques:

- Inicialización del programa.
- Bucle principal que va ejecutando las palabras del programa.
- Analizar el contenido de la línea REM.
- Ejecución de las palabras en FORTH.


COMO FUNCIONA
El programa está compuesto por 79 líneas en BASIC.

Se utilizan las siguientes variables:
S(8) – Matriz que contiene los valores del stack. Puede modificar en caso de necesidad, y cada elemento consume dos bytes.
I – Puntero del stack.
P – Puntero a la línea REM que contiene el código en FORTH.
F – Contiene el último valor del stack, entre otras funciones.
Y – Contiene el penúltimo valor del stack, si existe. En caso contrario es 0.
W – Código numérico de la palabra a ejecutar. Puede ser 0 si no se procesa un número.
N – Número a procesar. Se considera que se ha introducido un número cuando W es 0.
T – Valor máximo para un bucle DO.
Q – Posición de retorno para un bucle DO.
A – Valor actual de un bucle DO.
A$ - Carácter introducido en KEY.

Bloque principal:
1 – Línea REM que contiene el código en FORTH.
8 – Declarar el tamaño del stack. Inicialmente es 8.
9 – Inicializar el puntero del stack.
10 – Inicializar el puntero a la línea REM.
11 – Si la posición actual de P contiene un 118 se ha llegado al final de la línea y se detiene el programa provocando un error con el CLEAR, que libera memoria para la posterior edición de la línea con el código en FORTH.
12 – Salta a la rutina que analiza la línea REM hasta encontrar un espacio (0) o un final de línea (118).
13 – Si I es mayor de 0, se guarda en Y el penúltimo número del stack.
14 - Guarda en F el último número del stack.
15 – Salta a la línea que contiene el código que interpreta la instrucción o número leído de la línea REM.
18 – Salta a la línea 11 para seguir procesando la línea REM.

Bloque analizador:
20 – Ponemos el código de la palabra a 0.
21 - Ponemos el valor del número a 0.
22 – Incrementamos en 1 el puntero a la línea REM.
23 – Guardamos en “P” el valor del carácter del puntero P en la línea REM.
24 – Si se detecta un espacio (0) o un final de línea (118) salimos de la subrutina de análisis.
25 – Si el carácter está entre “0” y “9” se salta a 28 para procesarlo como una cifra numérica.
26 – Se guarda en “W” parte del valor de la instrucción según una fórmula.
27 – Saltar a 22 para analizar el siguiente carácter de la línea REM.
28 – Se guarda en “N” una nueva cifra del número.
29 – Saltar a 22 para analizar el siguiente carácter de la línea REM.

Bloque de ejecución de palabras FORTH:
080 – Código de la palabra “LOOP”. Se salta desde la línea 646.
100 – Código de la introducción de un número en el stack.
140 – Código de la palabra “?”.
172 – Código de la palabra “.”.
222 – Código de la palabra “I”.
336 – Código de la palabra “IF”.
346 – Código de la palabra “DO”.
352 – Código de la palabra “CR”.
484 – Código de la palabra “CLS”.
490 – Código de la palabra “RND”.
502 – Código de la palabra “DUP”.
504 – Código de la palabra “KEY”.
532 – Código de la palabra “DROP”.
618 – Código de la palabra “EMIT”.
620 – Código de la palabra “THEN”.
646 – Código de la palabra “LOOP”. (El código realmente está a partir de la línea 80)
648 – Código de la palabra “SWAP”.
652 – Código de la palabra “OVER”.
706 – Código de la palabra “SPACE”.
686 – Código de la palabra “-”.
688 – Código de la palabra “+”.
692 – Código de la palabra “*”.
694 – Código de la palabra “/”.
704 – Código de la palabra “=”.
708 – Código de la palabra “>”.
710 – Código de la palabra “<”


EL PROGRAMA
Imagen


PROGRAMAS DE EJEMPLO

CHARS
Este programa muestra los 32 caracteres correspondientes a los números y letras del charset del ZX-80.

Se muestran en 9 filas de 4 columnas cada una, mostrando primero su código CHR$.

El juego de caracteres del ZX-80 no es ASCII.

Forth_Chars.png
Forth_Chars.png (2.46 KiB) Visto 747 veces


DUMP
Este programa hace un volcado de memoria desde la dirección 16509 a la 17000. En la versión que se incluye se van mostrando de 8 en 8 bytes.

Las direcciones corresponden al BASIC que hay a partir de la línea 8, y sirve para comprobar cómo guarda las líneas el intérprete BASIC del ZX-80. Dos bytes iniciales para el número de línea, el contenido de la línea y un 118 como final de línea.

Forth_Dump.png
Forth_Dump.png (1.9 KiB) Visto 747 veces


En un ZX-80 con más de 1K se puede cambiar el 8 de la segunda línea por un 22 para mostrar más líneas en cada pantalla del volcado.
En el siguiente ejemplo se puede comprobar la equivalencia del volcado en FORTH con el listado en BASIC.

Forth_Dump2.png
Forth_Dump2.png (9.83 KiB) Visto 747 veces


APUNTES FINALES
En el año 2014 desarrollé un pequeño intérprete de FORTH para el ZX-81 con 1K. El programa funcionaba, pero era muy limitado y los bucles DO/LOOP se debían introducir de una forma concreta. Además, el intérprete no guardaba la línea y ante cualquier problema se debía volver a escribir el código FORTH. No quedé especialmente satisfecho.

Con la experiencia en la programación del ZX-80 sabía que en este equipo podría desarrollar una nueva versión, mejor y más completa. La arquitectura interna del BASIC del ZX-80 hace que consuma menos memoria que en un ZX-81. Los valores de las variables numéricas ocupan 3 veces menos que en el ZX-81 e introducir un número en el código 6 bytes menos, entre otras cosas. Como el ZX-80 solo trabaja con números enteros, la memoria que usa las rutinas matemáticas también es menor.

De esta forma he conseguido que el programa ejecute 24 palabras del FORTH en un programa de 79 líneas en BASIC, y que encima me sobren unos 200 bytes para introducir el código FORTH en una línea REM, cosa que nos permite editar el programa para realizar cambios, y mostrar los resultados en la pantalla.

Como es habitual en el ZX-80, durante la ejecución del programa no se visualiza nada en pantalla, pudiendo detener la ejecución del programa FORTH para mostrar resultados mediante la palabra KEY, o hacer un BREAK para detener totalmente el intérprete.

El intérprete ejecuta el código FORTH contenido en la primera línea REM, pero se pueden guardar otras líneas REM en otras líneas del programa por si se quieren ejecutar posteriormente, cambiando su número de línea a la primera del programa.

Trucos varios
Uno de los motivos que han permitido incluir tantas instrucciones en la versión del ZX-80 es el bloque que hay entre las líneas 20 y 29.

Este bloque va leyendo el contenido de la línea REM y se detiene cada vez que encuentra un espacio (0) o un código de final de línea (118).

Durante este proceso va añadiendo los dígitos que encuentra a la variable N y va codificando las letras de las palabran en la variable W.

Al acabar devuelve un valor numérico en N y el código de la instrucción en W. Si W es 0, se interpreta que ha leído un valor numérico y lo ha guardado en N. Si W es distinto de 0 se interpreta que es una palabra y saltará a la línea que la interpreta mediante el GOSUB de la línea 15.

Si se teclean palabras inexistentes puede pasar cualquier cosa ya que en el fondo el sistema no comprueba que las palabras existan.

Por otro lado, se ha intentado generar código para ser aprovechado por el máximo de palabras ya que en general el FORTH lo que hace es añadir o quitar números de un stack.

El hecho de intoducir el código FORTH en una línea REM nos permite editarlo tantas veces como queramos y guardarlo en cinta con SAVE.

Para terminar
Como de costumbre, las adaptaciones de programas previamente realizados en el ZX-81 quedan mucho mejor en el ZX-80. Me sorprende lo que he conseguido hacer en estos 800 bytes y con esta versión he quedado realmente satisfecho.

Prueba superada !!!

Os invito a probarlo.
Adjuntos
Forth_Listado.png
(6.71 KiB) No descargado aún
Buscando la IP de la W.O.P.R. he encontrado mi índice

garillete
Mensajes: 1983
Registrado: 30 Oct 2010 20:58
Agradecido : 363 veces
Agradecimiento recibido: 784 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor garillete » 27 Oct 2022 09:23

Impresionante... Yo ni idea de Forth pero hay que reconocer que exprimes los bytes a mas no poder...

Gracias como siempre por hacerlo y explicarlo paso a paso...

jltursan
Mensajes: 4879
Registrado: 20 Sep 2011 13:59
Ubicación: Madrid
Agradecido : 739 veces
Agradecimiento recibido: 1644 veces
Contactar:

Re: FORTH para Sinclair ZX-80 1K

Mensajepor jltursan » 27 Oct 2022 11:06

¡Quién da menos señores!, 200 bytes disponibles a compartir -507

Elurdio
Mensajes: 604
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 145 veces
Agradecimiento recibido: 112 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor Elurdio » 27 Oct 2022 11:26

Muy interesante. -drinks

He probado algunos programas cortos y muy bien.

Lo difícil ha sido pelearme con el ZX80 emulado... falta de costumbre.

dancresp
Mensajes: 5779
Registrado: 13 Nov 2010 02:08
Agradecido : 405 veces
Agradecimiento recibido: 550 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor dancresp » 27 Oct 2022 11:48

Elurdio escribió:He probado algunos programas cortos y muy bien.

Ya hice bastantes pruebas y no me falló nada.

Se toma su tiempo, pero lo hace bien.

Como no, si emulas el equipo con 16K puedes hacer cosas más complejas.

Elurdio escribió:Lo difícil ha sido pelearme con el ZX80 emulado... falta de costumbre.

Yo antes usaba el "EightyOne" de Windows, pero como me he divorciado de ese SO, ahora uso el "sz81" que está en Linux (y Windows) y cuando te acostumbras funciona a las mil maravillas, aunque visualmente no lo clava como el otro. Pero es que el "EightyOne" se ve como en una TV real... con sus tembleques y otros detalles.
Buscando la IP de la W.O.P.R. he encontrado mi índice

Avatar de Usuario
javier2112
Mensajes: 164
Registrado: 20 Ene 2020 08:26
Agradecido : 39 veces
Agradecimiento recibido: 27 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor javier2112 » 27 Oct 2022 14:49

Como siempre impresionante y gracias por el emulador para Linux, que no conocía ninguno.

Por cierto, según he odio, la ROM del ZX-80 (como la del ZX-81 y ZX Spectrum) ¡implementa un intérprete de Forth!

dancresp
Mensajes: 5779
Registrado: 13 Nov 2010 02:08
Agradecido : 405 veces
Agradecimiento recibido: 550 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor dancresp » 27 Oct 2022 15:42

javier2112 escribió:Por cierto, según he odio, la ROM del ZX-80 (como la del ZX-81 y ZX Spectrum) ¡implementa un intérprete de Forth!

Creo que te confundes.
Existen versiones de FORTH que reemplazarían la ROM que traen con el BASIC.

De chiquitines con 40 teclas, el único que trae FORTH es el Jupiter Ace.
Buscando la IP de la W.O.P.R. he encontrado mi índice

zxpope
Mensajes: 266
Registrado: 02 Ene 2018 02:25
Agradecido : 100 veces
Agradecimiento recibido: 104 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor zxpope » 27 Oct 2022 15:45

mucho vicio veo por aquí
voy a contarselo a un amigo que lee piensa y respira en forth

Avatar de Usuario
javier2112
Mensajes: 164
Registrado: 20 Ene 2020 08:26
Agradecido : 39 veces
Agradecimiento recibido: 27 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor javier2112 » 27 Oct 2022 17:19

dancresp escribió:
javier2112 escribió:Por cierto, según he odio, la ROM del ZX-80 (como la del ZX-81 y ZX Spectrum) ¡implementa un intérprete de Forth!

Creo que te confundes.
Existen versiones de FORTH que reemplazarían la ROM que traen con el BASIC.

De chiquitines con 40 teclas, el único que trae FORTH es el Jupiter Ace.

No, no me refiero a eso. Escuha la sección "Misterios de 8 bits y menos" de Retro entre amigos, Episodio 7x07.

Ojo, que quizá solo sea para ZX-81 y el Spectrum, porque se usa internamente para manipular números reales y el ZX-80 no los maneja (creo). Es lo que en la MH llamaban "el calculador".


Saludos.

zxpope
Mensajes: 266
Registrado: 02 Ene 2018 02:25
Agradecido : 100 veces
Agradecimiento recibido: 104 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor zxpope » 27 Oct 2022 17:59

efectivamente, recuerdo ese podcast, donde un profesor de sevilla (el del zxuno)
explica que habian implementado un interprete fortth para manipular numeros en coma flotante
pero no da detalles, y la verdad, es que me gustaria conocerlos

recordad que sir clive era matemático
y venia del mundo de las calculadoras,
asi que no parece raro que hiciese eso en el zx81

dancresp
Mensajes: 5779
Registrado: 13 Nov 2010 02:08
Agradecido : 405 veces
Agradecimiento recibido: 550 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor dancresp » 27 Oct 2022 23:57

zxpope escribió:efectivamente, recuerdo ese podcast, donde un profesor de sevilla (el del zxuno)
explica que habían implementado un interprete fortth para manipular numeros en coma flotante
pero no da detalles, y la verdad, es que me gustaria conocerlos

¿El profesor de Sevilla puede ser mcleod?
Menudo crack...
Buscando la IP de la W.O.P.R. he encontrado mi índice

dancresp
Mensajes: 5779
Registrado: 13 Nov 2010 02:08
Agradecido : 405 veces
Agradecimiento recibido: 550 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor dancresp » 28 Oct 2022 00:01

javier2112 escribió:No, no me refiero a eso. Escuha la sección "Misterios de 8 bits y menos" de Retro entre amigos, Episodio 7x07.

Ojo, que quizá solo sea para ZX-81 y el Spectrum, porque se usa internamente para manipular números reales y el ZX-80 no los maneja (creo). Es lo que en la MH llamaban "el calculador".

En cuanto pueda lo escucho, no sabía de su existencia.

Con todo, supongo que el tema del FORTH lo deben haber aplicado solo en la parte de las rutinas encargadas de hacer cálculos, mediante un stack, ya que en un ZX-81 con sus 8 KB de ROM, ya es sorprendente lo que llega a hacer. Y en un ZX-80, con sus 4 KB de ROM, no te digo...
Buscando la IP de la W.O.P.R. he encontrado mi índice

Elurdio
Mensajes: 604
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 145 veces
Agradecimiento recibido: 112 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor Elurdio » 28 Oct 2022 00:45

zxpope escribió:efectivamente, recuerdo ese podcast, donde un profesor de sevilla (el del zxuno)
explica que habian implementado un interprete fortth para manipular numeros en coma flotante
pero no da detalles, y la verdad, es que me gustaria conocerlos

recordad que sir clive era matemático
y venia del mundo de las calculadoras,
asi que no parece raro que hiciese eso en el zx81


En un desensamblado parcial de la ROM del ZX81 hay esto con respecto a la rutina de cálculo en coma flotante:

; ---------------------------------------
; THE 'FLOATING POINT CALCULATOR' RESTART
; ---------------------------------------
; this restart jumps to the recursive floating-point calculator.
; the ZX81's internal, FORTH-like, stack-based language.

;
; In the five remaining bytes there is, appropriately, enough room for the
; end-calc literal - the instruction which exits the calculator.

;; FP-CALC
L0028: JP L199D ; jump immediately to the CALCULATE routine.

; ---

;; end-calc
L002B: POP AF ; drop the calculator return address RE-ENTRY
EXX ; switch to the other set.

EX (SP),HL ; transfer H'L' to machine stack for the
; return address.
; when exiting recursion then the previous
; pointer is transferred to H'L'.

EXX ; back to main set.
RET ; return.



Es un desensamblado actualizado por última vez en dic-2004 (aquí)

zxpope
Mensajes: 266
Registrado: 02 Ene 2018 02:25
Agradecido : 100 veces
Agradecimiento recibido: 104 veces

Re: FORTH para Sinclair ZX-80 1K

Mensajepor zxpope » 31 Oct 2022 20:34

eso parece ser
desafortunadamente no conozco forth, y no puedo valorar la "belleza" de esa solución,
pero seguro que la debe tener


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

¿Quién está conectado?

Usuarios navegando por este Foro: Jack y 1 invitado