viernes, 4 de noviembre de 2016

Programación del Sinclair QL (IV): Programando en SuperBASIC con un emulador



Emulación, ventaja o sacrilegio

No tengo operativo mi querido QL actualmente, por tanto para poder programar usaré un emulador en un PC. Los puristas se echarán las manos a la cabeza, pero es el mejor sistema de mantener operativo un sistema hoy día, y además es mucho mas cómodo de manejar para hacer programas, ya que puedes usar un editor de textos normal y no el limitado sistema de edición del QL.

Todos los emuladores disponen de la posibilidad de simular los Microdrivers con directorios en el ordenador, y eso permite escribir los programas en uno y leerlos en el otro de forma cómoda y sencilla. Con la edad me vuelvo cómodo y prefiero usar un editor de textos para crear los programas, luego los leo en el QL, los corrijo, los ejecuto y los depuro de forma similar a como usaría un compilador, lo que para mi es mas cómodo y el desarrollo lo hago mas rápido.

Actualmente los emuladores de QL están un poco parados, aunque se mantienen varios actualizados periódicamente, pero hace tiempo que no salen novedades importantes. En general son bastante buenos y funcionan de maravilla, los hay gratuitos y de pago, hay versiones para MS.DOS, para Windows, para Linux, para Mac, etc.

Particularmente uso Q-Emulator de Daniele Terdina que me ha funcionado bien cuando he querido recordar mi viejo sistema, actualmente lo ejecuto sin problemas bajo Windows 10. Tiene dos versiones, la básica es gratuita y emula un QL estándar sin ampliaciones, a velocidad aproximada del QL, la avanzada es de pago pero funciona a mas velocidad, soporta mas memoria, mas cantidad de periféricos y otros S.O. Yo uso la versión gratuita que es suficiente para seguir estas entradas. Tiene versión para PC y versión para Mac. Ir a su web.

El emulador QPC desarrollado por Marcel Kilgus es también muy buena opción, era de pago pero en 2014 lo pasó a libre, por lo que os recomiendo probarlo y decidir luego. Funciona bien y rápido, ha sido el que tenia la mejor fama hasta hace poco, su versión QPC1 funciona bajo MS.DOS, mientras que la versión QPC2 trabaja tanto en PC bajo Windows como bajo Mac. Ir a su web.

El emulador mas clásico es QLay, el veterano desarrollado por JawVenema emula perfectamente bajo MS.DOS, Windows 95 y Linux, y tuvo versiones mejoradas desarrolladas por otros usuarios bajo versiones mas avanzadas de Windows denominadas QLay2 y QLay2K. Hoy día están superadas, pero para los amantes del retro mas retro podéis buscar aquí la original y aquí las nuevas.

Bajo Linux nació la versión uQLx desarrollada por Richard Zidlicky y basado en Q-emuLator. Ya no se desarrolla, y tuvo ports para Windows y Mac. Esta es la copia de la web original.

Existen emuladores desarrollados para correr en los otros 68000 de la época, si dispones de uno de esos sistemas puedes buscar QDOS4Amiga o QDOS Classic para Amiga, o QLem para ST.

Si buscáis hardware para usar el QL en otros sistemas, atrás quedaron la tarjeta QXL para ordenador PC con bus ISA, y la ST-QL para Atari ST, difíciles de conseguir, o las placas Q40 y Q60, caras pero muy buenas opciones. Hoy día es la época de las FPGA, ya hay una versión disponible para la FPGA MiST que nos permite disponer de un QL con 640Kb de RAM, y con posibilidad de usar tarjetas de memoria para simular disqueteras o microdrivers, mirar esta entrada en los QLforum ingleses.

jueves, 3 de noviembre de 2016

Programación del Sinclair QL (III): Procedimientos y funciones

Procedimientos y Funciones 

Hay lenguajes como el C en que estas dos estructuras de programación no se diferencian entre sí, mientras que en el superBASIC diferenciamos entre ambas según retornen o no un valor, siendo equivalentes el resto de sus características.

Ambas son estructuras recursivas, algo que en el BASIC estándar no existe como tal, aunque se puede hacer uso del GOSUB para conseguir cierta recursividad, es complejo por carecer de variables locales y las limitaciones del tamaño de la Pila de retorno lo hacen inviable en la mayoría de sistemas. Vemos un ejemplo muy sencillo de ambas:


BASIC     SuperBASIC
100 CLS
110 GOSUB 180
120 LET A=5:GOSUB 230:PRINT A
130 STOP
150 REM ---------------------
160 REM SALUDAR
170 REM ---------------------
180 PRINT "Hola a todos"
190 RETURN
200 REM ---------------------
210 REM INCREMENTAR
220 REM ---------------------
230 LET A=A+1
240 RETURN 
   
100 CLS
110 saluda
120 PRINT incremento(5)
130 REMark ------------------------
140 REMark PROCEDIMIENTO: Saludar
150 REMark ------------------------
160 DEFine PROCedure saluda
170   PRINT "Hola a todos"
180 END DEFine 
190 REMark ------------------------
200 REMark FUNCION:Incrementar
210 REMark ------------------------
220 DEFine FuNction incremento(a)
230   RETurn a+1
240 END DEFine 


En BASIC estándar hay que usar GOSUB para ir a otras partes del programa, para lo que hay que conocer el número de línea en que se encuentra nuestra rutina, y no olvidar el RETURN final pues si no el programa se liará bastante, y como todas las instrucciones son ejecutables, es necesario parar el programa para que no vuelva a ejecutar la primera rutina. En SuperBASIC podemos definir rutinas con nombre, y llamarlas desde cualquier punto del programa por ese nombre, esos trozos no se ejecutarán nunca por si solos, lo que hace que sean mas sencillos de usar.

Además opcionalmente podemos usar todos los parámetros de entrada que deseemos, cuando se llama se deben usar valores o variables para estos parámetros, que son copiados por valor a la rutina, estos parámetros ya no son variables globales sino que se comportan como variables locales en la rutina, por lo que se simplifica mucho el manejo de las variables, en nuestro ejemplo pasamos una variable a la función incremento, esta recibe el valor en una variable que siempre es local, lo que simplifica mucho el diseño de buenas rutinas, que no afecten al resto del programa.

Vemos que el procedimiento no tiene valor alguno de retorno, mientras que la función lo tiene siempre, es importante tenerlo en cuenta, ya que no podemos llamar por ejemplo a PRINT saluda pues no hay valor de retorno, ni llamar directamente a incrementa si no usamos el valor retornado en ningún lugar. En esto se diferencia de C en que se puede no usar el valor de retorno.

El paso de parámetro a nuestras rutinas siempre se realiza por valor, si deseamos modificar el valor de una variable debemos recurrir a usar variables globales para ello. Una función puede retornar solo un valor, pero el tipo de este valor no se define por lo que podemos asignar una variable de cadena a una entera, y esperar que el SuperBASIC nos resuelva la conversión del tipo de la variable. A mi particularmente me gustan los lenguajes fuertemente tipados que me evitan errores, pero en nuestro querido QL no hay otra opción.

Vamos con la recursividad, usando el ejemplo típico del factorial. Ritchie, uno de los creadores del C, dijo que era muy mal ejemplo pues la solución iterativa del factorial es mas rápida y eficiente que la recursiva, y prefería poner como ejemplo la impresión de un número en pantalla, ya entraremos en eso.

BASIC iterativo     SuperBASIC recursivo
100 CLS
110 INPUT "Valor: ";V
120 GOSUB 180
130 PRINT "El factorial es: ";F
140 END
150 REM ---------------------
160 REM FACTORIAL
170 REM ---------------------
180 LET F=1
190 FOR I= V TO 1 STEP -1
200   F=F*I
210 NEXT I
220 RETURN
   
100 CLS
110 INPUT "Valor: ";v
120 PRINT "El factorial es: ";factorial(v)
190 REMark ------------------------
200 REMark FUNCION: Factorial
210 REMark ------------------------
220 DEFine FuNction factorial(a)
230   IF (a = 0) THEN 
231     RETurn 1
232   ELSE 
233     RETurn a * factorial(a-1)
234   END IF 
240 END DEFine


Este ejemplo pone en claro que en caso del BASIC estándar, debemos conocer la dirección del programa en que se encuentra la rutina y los valores de variables que usará, mientras que en SuperBASIC nos vale con saber el nombre de la rutina. Si tenéis curiosidad y ejecutáis en un QL el programa para el valor 200, el resultado tardará un poco pero será 3.060575E614 presentando el resultado en notación científica, si ponéis en marcha un GWBASIC por ejemplo con el DOSBOX, el proceso iterativo dará un error de OverFlow para valores mayores a 33.

Otra característica muy útil es la posibilidad de usar variables locales, lo que evita muchos errores de programación, simplemente definiéndolas como primera instrucción de la función o el procedimiento:

100 b=10 : calculos: PRINT b
200 DEFine PROCedure calculos
210   LOCAL b
220   b = 20
230 END DEFine
 
Si ejecuta este programa tal cual, el valor que imprime es 10, pero si elimina la línea 210, el valor que mostrará será 20. Siempre todos los parámetros que reciba serán tratados como variables locales.

miércoles, 2 de noviembre de 2016

Programación del Sinclair QL (II): Formas estructuradas de intrucciones básicas

Añadido el 30/06/24 ampliaciones y mejoras

Añadido el 19/07/24 ampliación del On Select


Arreglos, mas conocidos como arrays, vectores o matrices

Como ingeniero informático llamaré a las cosas por su nombre. Array es una palabra inglesa que no existe en Español, en su lugar hay que usar la palabra arreglo. Se llama vector a un arreglo de una dimensión, y matriz a un arreglo de dos dimensiones, estos nombres se usan por similitud con las estructuras matemáticas del mismo nombre, pero el nombre que debemos usar debe ser arreglo unidimensional o arreglo bidimensional.


SuperBASIC admite arreglos de una y de dos dimensiones, pero con varias diferencia sobre los del  BASIC estándar.

En superBASIC es posible usar mas de dos dimensiones, no hay más límite que la memoria total disponible, pero en mi larga vida de programador muy pocas veces he usado arreglos de 3 dimensiones (solo recuerdo un caso), podemos pensar que esto se refiere a una colección de matrices, como sería por ejemplo una hoja de cálculo con un conjunto de hojas con sus filas y columnas. Usar mas de 3 es muy complicado de imaginar siquiera su uso, y personalmente nunca lo he necesitado, aunque yo me dedico profesionalmente a la gestión empresarial, quizá en la rama científica sea más factible usarlo.

En un arreglo numérico se incluye siempre el elemento cero, pero por compatibilidad se mantiene que el número sea el máximo elemento del arreglo, de forma que cuando se define un arreglo de 10 elementos estos van del 0 al 10, y no del 1 al 10 como en BASIC estándar, o del 0 al 9 como en C.


Los arreglos de caracteres son siempre de elementos de un solo carácter con la longitud máxima indicada, y guardando en el elemento cero la longitud real de la cadena, de forma que si creamos un arreglo con DIM a$(10), b$(10,5) lo que hacemos es crear en a$ una variable de cadena de diez posiciones máximo, y en b$ creamos ONCE cadenas (recordar que el elemento cero existe) de cinco posiciones máximo. En SuperBASIC el nombre del arreglo es una referencia a su contenido, de esta manera si hacemos a$="Hola" o b$(3)="Otras cadenas", lo que hacemos es usar cadenas de longitud máxima predefinida. 

  • Si hacemos PRINT a$;".";b$(3) en pantalla aparece Hola.Otras sin incluir espacios.
  • Si hacemos PRINT a$(0), en pantalla aparece 4 
  • Si hacemos PRINT a$(1), en pantalla aparece H 

Las cadenas se puede tratar como arreglos unidimensionales, pero en este caso no existe el elemento 0 con su longitud, así podemos hacer LET c$="Hola", si hacemos PRINT c$(1) aparece en pantalla H, si hacemos PRINT c$(0) o si hacemos PRINT c$(5) dará un error en ambos casos.

Podemos usar esto para imprimir todos los elementos de un arreglo numérico o de cadena en un PRINT, o para igualar entre si elementos de arreglos de cadena y usar por ejemplo b$(1)=a$, pero esta asignación no funciona con arreglos numéricos. Podemos dar valor a un arreglo de cadena usando por ejemplo INPUT a$ pero esto no funciona con numéricos.

 

Formas corta y larga de las instrucciones, uso del IF

En el superBASIC hay dos formas de escribir una instrucción, la que denominan forma corta abarca hasta el final de la línea en curso y no necesita cerrarse por tanto, mientras que la forma larga abarca varias líneas. Un ejemplo típico será un pequeño IF que podemos escribir de dos maneras

Forma LARGA     Forma CORTA
130 IF columna > 10 THEN 
140   columna=1
150   linea=linea+1
160 END IF 
   
130 IF columna > 10 THEN columna=1 : linea=linea+1

La forma corta no necesita cierre pues siempre termina en la misma línea en la que está, mientras que la forma larga si necesita siempre cierre. Esto es válido para cualquier instrucción.

En superBASIC existe la forma IF ... THEN ... ELSE ... END IF normal en los BASIC, con la parte ELSE opcional, pero con la particularidad de que el THEN es opcional, por lo que para la forma corta debe reemplazarse por dos puntos, pudiendo escribirse por ejemplo cualquiera de estas dos líneas

IF linea=23 THEN linea=1 : ELSE linea=linea+1
IF linea=23 : linea=1 : ELSE linea=linea+1

Bucle FOR

Los bucles FOR del QL mantienen la compatibilidad con el BASIC estándar pero añaden características adicionales. Veamos un bucle muy básico, presentaremos en pantalla una lista de números del 1 al 20:

BASIC     SuperBASIC
10 FOR i=1 TO 20 
20   PRINT i 
30 NEXT i
   
10 FOR i=1 TO 20
20   PRINT i 
30 END FOR i

Vemos que la única diferencia es como terminamos el bucle, y ya que la instrucción NEXT sigue funcionando en SuperBASIC, aunque añade otro sentido, podemos escribir ambos programas en el QL obteniendo el mismo resultado.

Los bucles en SuperBASIC disponen de dos instrucciones que podemos usar en su interior, la primera es NEXT, que hace que el bucle pase directamente al siguiente ciclo sin pasar por el resto de instrucciones. Si deseamos por ejemplo que el bucle se salte los elementos que sean múltiplos de 3, podemos escribir el código así:

BASIC     SuperBASIC
10 FOR i=1 TO 20 
20   IF (i MOD 3) = 0 THEN GOTO 40
30   PRINT i 
40 NEXT i
   
10 FOR i=1 TO 20
20   IF (i MOD 3) = 0 THEN NEXT i
30   PRINT i 
40 END FOR i

Como vemos ahora se imprimen solo los números 1,2,4,5,7,8,10,11,13,14,16,17,19,20 en ambos casos, pero nos hemos ahorrado el GOTO, y sobre todo, podemos incluir todas las líneas que deseemos en el bucle, sin importarnos cual es la línea que lo termina. Nuevamente podemos teclear ambas variantes del programa en SuperBASIC y funcionan ambas.

La otra instrucción que se puede usar en los bucles es EXIT, que como podemos imaginar hace que nos salgamos del bucle en el lugar en que nos encontremos. Supongamos que deseamos hacer que el bucle termine aleatoriamente, para lo que podemos escribir esto:
BASIC     SuperBASIC
100 CLS
110 FOR i=1 TO 20
120   IF (i MOD 3) = 0 THEN GOTO 160
130   LET a = INT(RND*11)
140   PRINT i, a
150   IF a = 10 THEN GOTO 170
160 NEXT i
170 REM Fin
   
100 CLS
110 FOR i=1 TO 20
120   IF (i MOD 3) = 0 THEN NEXT i
130   a = RND(0 TO 10)
140   PRINT i, a
150   IF a = 10 THEN EXIT i
160 END FOR i

Nuevamente, podemos escribir ambos programas en SuperBASIC con el mismo resultado, pero la segunda forma tiene la ventaja de que no necesitamos conocer donde acaba el bucle para salir de el, ni debe existir siquiera una sentencia posterior. Podemos ver otra característica del lenguaje interesante, la instrucción LET es opcional. Y por último, la instrucción RND es mas completa, si no decimos nada genera un número real entre 0 y 1, pero podemos darle un rango y generará números en ese rango, evitando calcular la parte entera de la multiplicación.

Además el bucle FOR también admite la forma corta en una sola línea, que no requiere añadir al final el End For:

                                FOR i=1 to 10 : PRINT i, : LET j=i*4 : PRINT j


Como característica adicional muy interesante, un bucle FOR puede contener dos formas de marcar los límites, la tradicional del TO-STEP o la posibilidad de indicarle una lista de valores sobre los que iterar, así podemos escribir:


10 FOR i = 1 TO 20 STEP 3
20 FOR i = 1 TO 3, 11 TO 13, 21 TO 23
30 FOR i = 1,3,7,10,20 TO 25,40,50
 

Y el bucle iterará por los valores 1, 4, 7, 10, 13, 16 y 19 en el primer caso, por 1, 2, 3, 11, 12, 13, 21, 22, 23 en sel segundo, y por 1, 3, 7, 10, 20, 21, 22, 23, 24, 25, 40, 50 en el tercero.

Bucle REPeat

En otros lenguajes hay dos construcciones estructuradas para el manejo de los bucles llamadas normalmente:
 
 
                            
WHILE (condición)                 
   ....
   ....
WEND
REPEAT
   .....
   .....
UNTIL (condición)

 
que se diferencian en cuando se verifica que se cumpla la condición, antes de empezar o tras la primera iteración. En SuperBASIC se dispone del REPeat como la otra forma estructurada de iterar en un bucle, que no verifica las condiciones nunca, debemos añadir un EXIT para poder salir del mismo siempre. Cuando tecleamos el programa, solo es necesario escribir la parte en mayúsculas de comando para que el sistema la complete. Este es un bucle básico que cuenta del 1 al 20:

BASIC     SuperBASIC
100 CLS
110 LET I=0
120   LET I=I+1
130   PRINT I
140 IF (I < 20) THEN GOTO 120
   
100 CLS
110 i=0
120 REPeat bucle
130   i = i + 1
140   PRINT i
150   IF i = 20 THEN EXIT bucle
160 END REPeat bucle


Ambas versiones funcionan en SuperBasic nuevamente. Estos bucles son útiles, pero se echa de menos una condición de entrada o de salida que nos ayude un poco mas, aunque podemos poner el EXIT como la primera instrucción del bucle para simular el WHILE, o como la última para el REPEAT. En estos bucles, la instrucción NEXT funciona pero no sirve para seguir iterando sino que es un sinónimo del EXIT para salir de bucle.  

Podemos escribir estas instrucciones en Super-BASIC de la siguiente manera, pero hay que tener en cuenta que el Repeat de otros lenguajes se repite MIENTRAS se cumpla la condición, por tanto para salir en Super-BASIC hay que verificar que NO se cumpla la condición. En caso del Repeat de otros lenguajes, se repite HASTA que se cumpla la condición, por tanto es lo mismo en Super-BASIC.


WHILE (condición)
  ....
  ....
WEND
Repeat bucle
  IF NO_Condición : EXIT bucle
  ....
END REPeat bucle
REPEAT
  ....
  ....
UNTIL (condición)
Repeat bucle
  ....
   IF condición : EXIT bucle
END REPeat bucle

SELect ON

Mientras en BASIC clásico se debe usar ON...GOTO / ON...GOSUB o instrucciones IF, en SuperBASIC se dispone del comando SELect como la forma estructurada de ejecutarlo, con la limitación de que solo se admite para valores numéricos y no de cadena. Veamos un ejemplo en el que decidimos que hace según el valor de una variable

BASIC     SuperBASIC
100 INPUT "Valor: ";VAR
110 ON VAR GOTO 140,160,180
120 PRINT "Valor no válido ";VAR
130 GOTO 200
140 PRINT "Valor 1"
150 GOTO 200
160 PRINT "Valor 2"
170 GOTO 200
180 PRINT "Valor 3"
190 GOTO 200
200 REM fin
   
100 INPUT "Valor: ";valor
110 SELect ON valor
120   ON valor=1
130     PRINT "Valor 1"
140   ON valor=2
150     PRINT "Valor 2"
160   ON valor=3
170     PRINT "Valor 3"
180   ON valor=REMAINDER 
190     PRINT "Valor no válido: ";valor
200 END SELect 

Ambas versiones funcionan en SuperBasic nuevamente, aunque la primera dará un error si el valor introducido no es 1, 2 o 3 dependiendo de la versión del BASIC que usemos, y lo dará en SuperBASIC. El uso de ON en la primera línea es opcional, y el de REMAINDER nos posibilita tratar cualquier caso no contemplado entre los seleccionados. Además, el sistema puede tratar con listas de valores, por tanto podemos poner por ejemplo:

110 SELect valor
120   ON valor=1,3,5
130     PRINT "Valor impar"
140   ON valor=2,4,6
150     PRINT "Valor par"
180   ON valor=REMAINDER 
190     PRINT "Valor fuera de rango"
200 END SELect 


Es posible compactar mas todavía las líneas, eliminando el ON (aunque por costumbre de otros lenguajes lo seguiré usando) y usar la forma corta de las instrucciones:

110 SELect valor
120   =1,3,5     : PRINT "Valor impar"
130   =2,4,6     : PRINT "Valor par"
140   =REMAINDER : PRINT "Valor fuera de rango"
150 END SELect 

Se puede usar la forma corta en una sola línea, lo que usando rangos nos permite reemplazar un IF por un SELect

110 SELect valor=1 TO 5, 11 TO 15 : PRINT "Valor fuera de rango"
Importante el que en el select el valor de control debe ser numérico, NO ES POSIBLE USAR VALORES DE CADENA, así NO podemos hacer un select de esta manera, da un error:

110 SELect valor$
120   ON valor$="1" : PRINT "UNO"
130   ON valor$="2" : PRINT "DOS"
140   ON valor$=REMAINDER : PRINT "OTRO"
150 END SELect 

martes, 1 de noviembre de 2016

Programación del Sinclair QL: INDICE

01. Introducción al Super Basic
02. Formas estructuradas de intrucciones básicas
03. Procedimientos y funciones
04. Programando en SuperBASIC con un emulador
05. Algoritmos de ordenación, clasifición y análisis
06. Procedimientos y funciones, paso de parámetros
07. Algoritmos de ordenación, planteamiento para las pruebas
08. Algoritmos de ordenación por intercambio iterativos. Burbuja
09. Algoritmos de ordenación por intercambio iterativos. Derivados de la Burbuja
10. Algoritmos de ordenación por intercambio recursivos. QuickSort
11. Algoritmos de ordenación por intercambio recursivo, mas sobre el Quicksort
12. Algoritmos de ordenación por intercambio recursivo, Quicksort de tres vías
13. Algoritmos de ordenación por inserción
14. Estructuras de datos. Pilas. QuickSort no recursivo
15. Estructuras de datos. Colas
16. Estructuras de datos. Mas sobre pilas y colas
17. Estructuras de datos. Lista enlazada
18. Algoritmos de ordenación por inserción. Inserción usando una lista enlazada
19. Estructuras de datos. Árbol binario de búsqueda
20. Estructuras de datos. Presentar el árbol
21. Estructuras de datos. Árboles AVL
22. Variables (entrada teórica)
23. Punteros
24. Arboles. Estructura de los nodos en Super Basic
25. Arboles. Pruebas de los nodos
26. Arboles. Rutinas para manejo de memoria y su testeo

27. Arboles. Pruebas de nodos en memoria (próximamente)
28. Calculadora (próximamente)

00. Estructuras de datos. Desarrollo de los árboles AVL
00. Algoritmos de ordenación por mezcla
00. Algoritmos de ordenación por casilleros
00. Algoritmos de ordenación diversos
00. Algoritmos de desordenación 
00. Algoritmos de ordenación en medios externos.
00. Algoritmos de búsqueda

Programación del Sinclair QL (I): Introducción al Super Basic




Contacto conmigo Badaman, el creado de la web mas antigua sobre el QL en castellano, preguntándome sobre mi QL, y si conservo los programas que hice.

Mi QL está de momento inaccesible, ya que se encuentra tras varias filas de cajas en el trastero, tengo que ponerme a vender casi todo, pues he acumulado demasiadas cosas que no utilizo, y rescatarlo. Cuando lo saqué hace unos años por última vez no le funcionaba la membrana del teclado, y los microdrivers fallaban por el tiempo y la maldita espuma, por lo que no tengo esperanza de rescatar lo que programé en su día, pero he quedado con él en reescribirlos y ponerlos a disposición de todos.

Mi QL lo compré en el Corty al poco de salir en España por 125.000 Pesetas de la época, pagándolo en tres veces gracias a que estaba trabajando ya en esa época. Me dediqué a programar sobre todo algoritmos fundamentales, aplicando nuevas técnicas de programación en el Basic, aunque profesionalmente ya programaba en dialectos de Basic, ninguno era tan potente como el SuperBASIC del QL, que permitía usar sintaxis clásica con sus GOTO y GOSUB, o programación estructurada con funciones y recursividad, además de disponer de un S.O. multitarea, cosa no habitual en su momento, se notaba el enfoque profesional del aparato, aunque como en todo lo de Sinclair, por ahorrar costes y que fuera barato se quedó a mitad de camino de todo, podía haber sido un buen ordenador para temas como gestión empresarial, pero no llegó nunca a serlo.

El QL era una maravilla, podía aprender código máquina del 68000, podía trabajar con un S.O. multitarea, y podía trabajar con un BASIC avanzando, pasé buenas horas con el, pero al poco conocí a la que ahora es mi mujer desde hace 28 años, y extrañamente empecé a pasar mas horas con ella que con mi QL. Luego ocurrieron dos cosas que acabaron de arrinconarlo, me casé y un PC entró en casa. Pero como nunca es tarde, a ver si hago una cuantas entradas sobre programación en SuperBASIC sobre los algoritmos que escribí en el QL, reescribiendo un poco el clásico "Algoritmos + Estructuras de Datos = Programas", del profesor Niklaus Wirth, el creador del Pascal entre otros lenguajes.


SuperBASIC

El QL no es un Spectrum mejorado, es bastante mas, comenzando por disponer de un S.O. propio con posibilidades multitarea, y un lenguaje de programación mejorado denominado SuperBASIC, que me enamoró enseguida. Nacido en 1984, a diferencia del GW.BASIC o de los que yo usaba profesionalmente en ese momento, el Bussines Basic de Nixdorf o en BAL de Bull, es un lenguaje estructurado en el que ya no es necesario el uso del GOTO/GOSUB, con manejo de funciones recursivas. Esto lo convierte en un avanzado lenguaje para la época.

SuperBASIC mantiene la compatibilidad con los anteriores BASIC, por tanto soporta el manejo del GOTO, aunque no lo necesita. Para mi su punto flaco es no contar con un mejor editor de programas, ya que ahora los números de línea ya no son necesarios mas que para editar el programa, en la habitual mezcla de características de Sinclair, mejora en muchos aspectos, pero reduce prestaciones por otro. A pesar de ello veremos que SuperBASIC es un gran lenguaje de programación, del que solo echo de menos el no manejar estructuras de datos.

Esto no es un curso de programación en BASIC, ya debes saber programar, voy a daros una introducción a las características principales del lenguaje, comparando  BASIC y SuperBASIC.

Una característica importante es la compatibilidad con el BASIC clásico, casi sin cambiar nada un programa en BASIC para el Spectrum o en GW-BASIC funcionan sin modificaciones. Disponemos de los clásicos GOTO/GOSUB, pero puedes hacer cualquier programa sin utilizarlos. ON GOTO/ON GOSUB se pueden reemplazar por la instrucción SELect. El bucle FOR no solo dispone de mas opciones, sino que se complementa con un nuevo bucle REPeat. Pero lo mejor del SuperBASIC es la posibilidad de usar Procedimientos y Funciones que pueden recibir parámetros y en las que se pueden usar variables locales, siendo además recursivas.

Los nombres de variables empiezan por letra o por subrayado, y pueden tener hasta 256 caracteres de largo. Otra característica es que es un lenguaje poco tipado y con conversión automática entre tipos. Solo soporta variables decimales, enteras (terminan en %) y de texto (terminan en $), si escribimos por ejemplo variable = "12.34", tendremos en la variable decimal un valor de 12.34 mientras que si escribimos variable% = "12.34", tendremos en la variable entera el valor 12 sin dar errores de tipo. Las variables a, a% y a$ son tres variables diferentes.

Se edita en la forma clásica, se introducen líneas con número, se eliminan solo con el número, se editan con EDIT, además de que solo es necesario escribir las primeras letras en mayúsculas de cualquier comando para que el sistema autocomplete su nombre tras guardar la línea. Disponemos de las instrucciones RENUM para renumerar las líneas del programa, y AUTO para introducir nuevos números automáticamente.

domingo, 30 de octubre de 2016

Preservación de máquinas (XII): Kenbak-1, un nuevo comienzo

 Índice de entradas de Preservación de máquinas 
Colabora con el proyecto: Simplemente haz click de vez en cuanto en los anuncios, no te cuesta nada y me ayudas con los costes del proyecto. Cada 11 click aportas un euro.

Tengo una mala costumbre, solo hago copias de seguridad de las cosas cuando las termino, y por desgracia el disco duro del ordenador en que tenía los esquemas y el circuito del Kenbak-1 murió, perdiendo el trabajo.

Como buen programador, el perder algo es sinónimo de volver a hacerlo, y siempre sale mejor la segunda vez que la primera. Creo que lo leí de uno de los grandes de la informática, Donald Knuth, en su primer volumen de "El arte de programar ordenadores", hablaba de que la reescritura de un programa no debe considerarse una pérdida de tiempo, ponía el ejemplo de un programa escrito para una máquina A, que se ejecutaba bajo emulación en una maquina B, corriendo en una tercera máquina C que emulaba la B. Cuando se reescribió, se encontró un error que hacía que el programa fuera a la cuarta parte de la velocidad que podía haberse ejecutado.

Al volver a empezar he cambiado la forma de montar las páginas en Eagle, quería tener solo una por cada hoja original, lo que hacía que muchas estuvieran muy llenas de componentes de otras páginas, ahora lo he cambiado y uso dos hojas por cada original, en una los componentes del esquema original, y en la segunda los que deben pasar a otra página, ahora los esquemas creo que son mas claros.

También he cambiado la forma de montar las vías que unen las dos caras para pasar señales de una a otra, las estaba poniendo directamente en el circuito, ahora las estoy añadiendo a los esquemas, ya que el objetivo es reproducir el original al máximo y no hacer un nuevo circuito, prefiero tenerlas en los esquemas y así puedo ir enrutando mejor, no pierdo nunca las vías si tengo que eliminar un enrutado ya efectuado.

Todo esto ha echo que se alargue mas el proyecto, pensaba tener ya la placa diseñada en Eagle y los gerber creados, pero no es así. Paciencia, lo terminaré algún día.

lunes, 5 de septiembre de 2016

Preservación de máquinas (XI): Libro del Kentelec-8 en la biblioteca de la UPV

 Índice de entradas de Preservación de máquinas 
Colabora con el proyecto: Simplemente haz click de vez en cuanto en los anuncios, no te cuesta nada y me ayudas con los costes del proyecto. Cada 11 click aportas un euro.


En la biblioteca de la Universidad Politécnica de Valencia disponen de uno de los manuales del Kentelec-8. Con los cambios de exámenes, ahora cierran en Agosto, por lo que hasta la última semana del mes no he podido ir a verlo.

Tras las expectativas y la espera, la decepción, por desgracia es solo el Manual de Programación que apenas habla del aparato, solo es un manual de programación del Intel 8008 en ensamblador, y hace referencia al manual del operador para eso.

Portada


Índice

Disponen de dos ejemplares, aunque solo he visto uno de momento. Este tiene fecha de edición de 1975. Los sellos indican que el aparato se adquirió para la biblioteca central en 1977, y que pasó en 1984 a la biblioteca de la actual escuela de Arquitectura técnica, que lo devolvió a la central posteriormente, y está en el depósito ya que nadie lo consulta nunca. Aunque lo han mirado muy amablemente, en esa época los registros eran manuales y ya no están disponibles, por lo que no hay forma de saber quien solicito el libro ni de que departamento era, con esa información podría ir a ese departamento a preguntar si saben algo, o si sabes el profesor que lo pidió lo puedes intentar localizar, aunque esté jubilado.

Al ser un manual de programación en código máquina general del Intel 8008, lo mas probable es que no se comprara para el aparato, pues en ese caso tendrían también el manual de operador, seguramente se compraría como manual de programación al ser el único en español del mercado.

Esquema del aparato


Muestra del texto
Manejo de Interrupciones

Se que los dos manuales están en la Biblioteca Nacional de España, ya que aparecen en su catálogo, tendré que ir expresamente algún día a buscarlos, o solicitar fotocopias o escaneados del manual de operador, que es el que de momento me proporcionaría información importante para su reproducción, como el saber para que sirven todos los interruptores por ejemplo.

Tras Agosto y unos días de descanso y de viaje, retomaré el proyecto y a ver si consigo avanzar un poco mas en este aparato.