ZX-LEARN para ZX-81

Foro dedicado a la programación en todo tipo de sistemas clásicos.
dancresp
Amiga 1200
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

ZX-LEARN para ZX-81

Mensajepor dancresp » 10 Ene 2015, 21:43

Screen-1.gif
Screen-1.gif (1.09 KiB) Visto 4494 veces

EL PROGRAMA
Este programa es un intérprete del lenguaje de programación LEARN que viene con las calculadoras programables CASIO FX-180P y derivadas.

Los primeros modelos disponen de una memoria total de 38 pasos de programa, permiten almacenar hasta dos programas, 6 registros K (K1-K6) y un registro M, más el registro principal X. Los programas no se pueden editar.

En modelos más avanzados la programación no ha evolucionado pero disponen de hasta 300 pasos de programa, permiten almacenar hasta 4 programas y estos se pueden consultar y editar, ya que disponen de una pantalla más completa.

Calculadoras.jpg
Calculadoras.jpg (237.33 KiB) Visto 4495 veces

Distintos modelos de calculadoras que incorporan LEARN

El LEARN es un sencillo lenguaje de programación compuesto básicamente por 5 instrucciones. Estas permiten la entrada de un valor numérico (ENT), mostrar un valor numérico (HLT), volver al principio del programa (RTN) y saltos condicionales al principio del programa (X>0 y X<=M).

Estas cinco instrucciones junto con todas las funciones disponibles de la propia calculadora configuran en equipo ideal para programar fórmulas o incluso juegos sencillos.

Estas calculadoras permiten el uso de 8 registros:
- X: Registro principal de la calculadora usado como acumulador de las operaciones.
- M: El Registro de Memoria típico de las calculadoras.
- K: Seis registros extras a nuestra disposición, numerados del 1 al 6.

Cada paso de programa se compone de una instrucción o de la pulsación de una tecla, excepto al usar los registros K con “Kin” y “Kout” en que hasta 3 teclas ocupan un único paso.

La versión del ZX-81
Esta versión solo permite un único programa de hasta 32 pasos de programa y el uso de los registros X y M, quedando descartados los 6 registros K.

Al ejecutar el programa se entra en el editor, donde debemos ir entrando los distintos pasos del programa, uno tras otro, validándolos con la tecla ENTER.

Así, para entrar el valor 100 hay que seguir la siguiente secuencia: 1 [ENTER] 0 [ENTER] 0 [ENTER]

Para ejecutar el programa simplemente hay que pulsar ENTER con el campo de entrada vacío.

Para detener el programa:
- Al finalizar la ejecución del programa se vuelve al editor, conservando el valor del registro “M”.
- Si se usa la instrucción RTN el programa entra en un bucle infinito. Para detener el programa de debe hacer BREAK y RUN. En ciertos casos, el uso de los saltos condicionales pueden provocar el mismo efecto.
- Para detener el intérprete estando en el editor: EDIT (SHIFT+1) STOP (SHIFT+A) ENTER

Si al finalizar la ejecución del programa LEARN se quiere volver a ejecutar, simplemente hay que volver a pulsar ENTER. Si se introduce cualquier cambio desde el editor, se borrará el programa actual y se entenderá que se está entrando uno nuevo.

Instrucciones reconocidas
Las cinco instrucciones principales del LEARN funcionan exactamente igual que en las calculadoras originales, pero por motivos evidentes la mayoría de las funcionalidades propias de la calculadora no se han podido incluir.

Durante la introducción del programa se pueden introducir únicamente sus dos primeras letras para que el analizador las reconozca. Así “ENT” y “EN” o “X<=M” y “X<” funcionan exactamente igual.

ENT
Detiene el programa para introducir un valor numérico. Al pulsar ENTER sigue con la ejecución.
El valor numérico se debe introducir completo, a diferencia del modo de programación.

HLT
Detiene la ejecución del programa y muestra el valor del registro X.
Recomendable hacerlo después de obtener un resultado con “=”.

RTN
Salta al primer paso del programa.

X>0
Salta al primer paso del programa si el valor del registro X es mayor de 0. En caso contrario sigue con la ejecución del programa.

X<=M
Salta al primer paso del programa si el valor del registro X es menor o igual al valor del registro M. En caso contrario sigue con la ejecución del programa.

MIN
Almacena en el registro M el valor del registro X.

MR
Recupera el valor del registro M.

RAN#
Genera un número aleatorio entre 0 y 1.

RND
Redondea el valor del registro X.

=
Calcula el resultado de la operación introducida y guarda el resultado en el registro X.

números
Se puede introducir cualquier número que sea capaz de manejar el ZX-81, entero o real.
Durante la fase de programación cada dígito o signo introducido debe ir seguido de un ENTER.

operaciones
Permite el cálculo de sumar, restas, multiplicaciones, divisiones y potencias, permitiendo el uso de paréntesis.


Programas de ejemplo
Calcula 10 – 4 y muestra el resultado en pantalla:
[1][0][-][4][=]

Calcular el 21% de IVA de distintos precios:
[ENT][*][2][1][/][1][0][0][=][HLT][RTN]

Simula un Bingo mostrando números entre 1 y 90:
[RAN#][*][9][0][+][1][=][RND][HLT][RTN]


Comentarios y recomendaciones:
- No introducir más de 32 pasos de programa ya que el editor no lo controla y puede provocar el cuelgue del equipo.
- Es recomendable que los saltos condicionales estén después de un “=” para una correcta evaluación.
- Al detener un programa o volver al BASIC se pierden los pasos del programa.

Descargar el juego en formato ".P" y ".z81" (Snapshot de EightOne):
ZX-Learn.rar
(1.56 KiB) Descargado 306 veces


BLOQUES
He dividido el listado en 4 bloques:

- Inicialización de variables.
- Entrada del programa.
- Ejecución del programa.
- Rutinas de LEARN y otras.


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”.
P – Variable que contiene el puntero a la memoria del buffer de la impresora.
A – Guarda una copia del valor inicial de P, ya que va variando en el editor o durante la ejecución.
X – Variable que contiene el valor del registro X.
M – Variable que contiene el valor del registro M.
F – Variable para bucles.
A$ - Variable usada para la entrada del editor o del valor a calcular durante la ejecución.

2 – Guardamos el valor 1 en la variable “U”. Se usará a lo largo del programa y permite ahorrar memoria.
4 – Inicializamos el valor de la variable “M” a 0.
5 – Inicializamos el valor de la variable “X” a 0.
6 – Guardamos el del buffer de la impresora en la variable “P”.
7 – Guardamos el valor inicial de “P” en la variable “A” para recuperarlo posteriormente.
8 – Mostramos el valor de la variable “X”.
10 – Introducir en A$ el paso del programa.
12 – Si no se introduce nada en A$ salta a 30 para ejecutar el programa introducido.
14 – Inicio del bucle que trata de identificar si se ha introducido una instrucción.
16 – Se comparan los dos primeros caracteres de A$ con la lista de instrucciones aceptadas, y si coincide salta a la línea 22.
18 – Final del bucle.
20 – Si no se identifica ninguna instrucción se guarda en F el código del carácter introducido.
22 – Guardar en la memoria el valor de “F”.
24 – Incrementamos el puntero “P”.
26 – Saltar a la línea 10 para entrar otro paso del programa.
30 – Guardamos en la posición actual del puntero “P” un 0 que indicará el último paso del programa.
32 – Inicializamos “P” con el valor inicial del buffer de impresora, guardado previamente en “A”.
36 – Se borra la pantalla.
38 – Se guarda en “F” el valor del paso de programa indicado por “P”.
40 – Si el valor de “F” es 0 se vuelve al editor saltando a la línea 6. Se mostrará el valor de “X” y se conserva el de “M”.
42 – Se incrementa el puntero “P” para apuntar al siguiente paso.
44 – Se simula un ON GOTO saltando a líneas múltiplos de 50 para ejecutar las distintas rutinas de las instrucciones.
46 – Si el valor de la instrucción es menor o igual a 5 concatena en A$ el valor de “X”.
48 – Saltar a la línea 36.
50 – Rutina de “ENT” (Enter).
150 – Rutina de “RAN#” (Random).
250 – Rutina de “MR” (Memory Read).
350 – Rutina de “RTN” (Return).
450 – Rutina de “X>0”.
550 – Rutina de “X<=M”.
650 – Rutina de “HLT” (Halt).
750 – Rutina de “=”.
850 – Rutina de “Min” (Memory Input).
950 – Rutina de “RND” (Round).
9000 – Si el paso no corresponde a ninguna instrucción se concatena el valor en la variable A$.


EL PROGRAMA
ZX-Learn.gif
ZX-Learn.gif (12.1 KiB) Visto 4495 veces


APUNTES FINALES
Un proyecto similar a éste, bastante limitado, ya lo había llevado a cabo para las CASIO PB.

Anteriormente ya me había planteado realizar una versión para el ZX-81, pero no acababa de ver como encajar el intérprete en su único KB de memoria.

Pensando en los 38 pasos de programa disponibles en el equipo original me vino a la cabeza el poder usar los 32 bytes del buffer de la impresora para poder almacenar allí el programa. Y a partir del analizador de instrucciones que había usado previamente en el “K-Assembler “decidí asignar un valor a cada instrucción y para el resto guardar directamente su CHAR, de forma que realmente cada paso ocupa un byte, igual que en la calculadora original.

Entrando el programa
La introducción del programa es “relativamente lenta” ya que por cada instrucción o tecla que se pulsa (como un dígito o un signo), una rutina se encarga de identificarla y numerarla, pero posteriormente esto hace que ahorremos memoria y que la ejecución sea mucho más rápida.

Codificación de las instrucciones:
01 : ENT
03 : RAN#
05 : MR
07 : RTN
09 : X>0
11 : X<=0
13 : HLT
15 : MIN
17 : =
19 : RND

El resto de pasos contienen simplemente el valor CHAR de la tecla pulsada.

Ejecutando el programa
Inicialmente el programa se ejecutaba entrando “P1”, pero opté por dejarlo en “” ya que de esta forma ya tengo la variable A$ inicializada.

A la hora de ejecutar el programa el proceso es mucho más rápido porque no hay que realizar ningún análisis sintáctico, y simulando un ON GOTO en la línea 44 saltamos directamente a la rutina de la instrucción correspondiente.

Las rutinas de las 10 instrucciones reconocidas están comprendidas entre las líneas 50 y 952, agrupándose en 3 grupos:
1. Instrucciones que asignan un valor al registro X. (ENT, RAN# y MR)
2. Instrucciones de salto. (RTN, X>0 y X<=M)
3. Instrucciones que calculan un resultado. (=, MIN y RND)

Si el código del paso es superior a 19 se asume que es un carácter correspondiente a un dígito, separador decimal o de una operación matemática y se concatena en la variable A$.

Gracias a la potencia de la instrucción VAL del BASIC de los equipos SINCLAIR se ha podido realizar este proyecto, ya que nos permite procesar una expresión numérica compleja y devolvernos el resultado correspondiente. En otro equipo no se como lo habría podido solucionar, especialmente con tan poca memoria...

Lamentablemente el ZX-81 es muy lento presentando valores numéricos por pantalla. Esto provoca la sensación de que el intérprete de LEARN es más lento de lo que realmente es.

Y por desgracia, el ZX-81 borra el contenido del buffer de la impresora al detener un programa y volver al editor BASIC. Esto provocará la pérdida del programa LEARN almacenado.

Metiendo un intérprete de LEARN en 47 líneas de código BASIC y 524 bytes
Esta vez me ha sorprendido lo rápido y bien que funciona, pero especialmente lo poco que ocupa... y que lo haya conseguido meter en el KB del ZX-81. Aquí ha estado la gracia.

Como siempre, lo primero ha sido introducir una línea con la que voy controlando la memoria que ocupa el programa:
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.

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 VAL, y como el valor 1 se usa varias veces he asignado ese valor a la variable "U" mediante "SGN PI". He prescindido de CODE para dejar el programa más comprensible porque solo habría conseguido ahorrar unos 6 bytes. Por otro lado, todo el proyecto usa simplemente 7 variables, 6 numéricas y una alfanumérica.

La segunda parte se encarga de interpretar el programa LEARN. Como el BASIC de los SINCLAIR permite saltar a una línea producto de un cálculo, he hecho que la rutina este en la línea del código de instrucción multiplicado por 50, y después con un simple RETURN se vuelve al bucle principal. Esto a ahorrado mucha memoria.

Las rutinas del calculador de la ROM del ZX-81 pueden consumir una buena cantidad de memoria RAM al realizar cálculos complejos. Como el programa solo ocupa 524 bytes y apenas hace uso de la memoria de vídeo, en principio no debería haber problemas de memoria durante la realización de los cálculos.


Para terminar
Tengo en mente un nuevo proyecto basado en el lenguaje protagonizado por una tortuga.

Próximamente en sus ZX-81 de 1KB... ZX-LOGO !!!


Os invito a probarlo.
Buscando la IP de la W.O.P.R.

Avatar de Usuario
scooter
Amiga 1200
Amiga 1200
Mensajes: 1031
Registrado: 17 Jul 2012, 09:25
primer_sistema: C64
Ubicación: Alicante

Re: ZX-LEARN para ZX-81

Mensajepor scooter » 11 Ene 2015, 15:34

OMG! Como se os va la cabezaaaaa.

Me encanta.

Avatar de Usuario
pinace
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 149
Registrado: 07 May 2012, 22:38

Re: ZX-LEARN para ZX-81

Mensajepor pinace » 11 Ene 2015, 22:48

Que bueno :)
Tengo todavía en casa de mis padres la FX180A con su caja e instrucciones... la de caña que le di en la FP :D
¡¡Enhorabuena por el resultado!!


Volver a “Programación”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados