009:iniciacion

Microhobby 9. Año II, del 1 al 7 de enero de 1985

José M. Fraile

Un ordenador no entiende más que de números y, concretamente, sólo de números en notación binaria. ¿Cómo es posible entonces que nos comuniquemos con él medíante palabras y comandos de Basic?

Un ordenador, cualquiera que sean el tipo y la marca, puede dividirse en dos parte fundamentales: el microprocesador, verdadero corazón de la máquina, que se encarga de gestionar el inmenso trasiego de cifras y operaciones que pasan por él, y la memoria, almacén de ingentes cantidades de datos que, más tarde, serán utilizados por el microprocesador.

La información se almacena en la memoria siempre en forma de unos y ceros. Son los denominados «bits». Un «bit», por definición, sólo puede ser un «1» o un «0». Estas unidades mínimas de información, se agrupan en bloques de ocho «bits» a las que llamamos «bytes». Un «byte» son, por tanto, ocho «bits».

La memoria de nuestro Spectrum consiste en 65536 imaginarias casillas, en cada una de las cuales puede almacenarse un byte. Las 16384 primeras son de ROM (Read Only Memory), por lo que resultan inalterables desde que las fabricó SINCLAIR, mientras que las 49152 restantes posiciones son de RAM (Random access memory) y pueden escribirse y borrarse tantas veces como queramos. Este planteamiento sólo es válido para un Spectrum completo (con 48 K de RAM) ya que a la versión de 16K le faltan las 32768 últimas posiciones, con lo que sólo dispone de 16384 casillas utilizables.

Todos los ordenadores, incluido el nuestro, pueden ser programados en distintos lenguajes: Basic, Cobol, Forth, etc. pero, ¿cómo es posible si por principio cualquier ordenador sólo entiende de «bits», es decir, de unos y ceros?

La explicación está en el «intérprete». En la memoria ROM reside, además del sistema operativo, el intérprete que se encarga de «traducir» a bits toda la información que entra en el microprocesador. Es decir, nosotros hablamos al intérprete en Basic y éste a su vez, al microprocesador en bits. Cuando el microprocesador responde —en bits, por supuesto—, el intérprete adapta su respuesta al Basic que es lo que finalmente nos llega.

El programa Basic también reside en memoria, pero en la parte de RAM, por lo que puede ser alterado en todo momento. La forma en que está almacenado es un tanto peculiar. No puede ser directamente «digerido» por el microprocesador, sino que tiene que pasar a través del intérprete.

10 REM "DEMOSTRACION"
15 LET z=0
20 FOR X=10 TO 200 STEP 6
30 FOR y=10 TO 20 STEP 4
40 CIRCLE x, y + 60 + 10 * SIN x, z
50 NEXT y: LET z=z + 1: NEXT x
70 PRINT AT 0, 11; PAPER 1; INK 7; FLASH 1; "FINAL"

Vamos a realizar un pequeño experimento en este sentido que nos clarificará las ideas.

Teclee cuidadosamente el programa demostración, respetando todos los números de instrucción, sentencias REM, espacio con blanco, etc.

Lo primero que tenemos que hacer para ver la estructura interna del programa Basic, es averiguar dónde se encuentra éste. El programa no está siempre situado en la misma zona, ya que el sistema operativo lo desplaza por la memoria según sus propias necesidades de espacio. Al final de cualquier desplazamiento, siempre se acuerda de apuntar dónde lo ha puesto en las posiciones de memoria 23635 y 23636 que están exclusivamente reservadas para este fin. Es la variable del sistema llamada «PROG».

A partir de este momento, es conveniente tener a la vista el manual de instrucciones del Spectrum abierto por la página 174. Allí se relacionan las variables del sistema y sus respectivos cometidos.

Puesto que el Spectrum sólo puede almacenar un byte (ocho bits) en cada casilla de memoria, y toda la información que es capaz de manejar un microprocesador está en notación binaria (unos y ceros), ésto quiere decir que el menor número que puede haber en una posición de memoria es el 00000000 (0 en decimal) y el mayor el 11111111 (255 en decimal). Cualquier número que supere este valor, ha de ser almacenado en memoria utilizando técnicas especiales. En este caso concreto, cuando el Spectrum precisa anotar un número comprendido entre 0 y 65535 (todos los valores que comprenden las direcciones de memoria) lo divide en dos bytes (que llamamos «más significativo» y «menos significativo») utilizando las siguientes fórmulas:

Fórmula 1:

  • byte menos significativo=número-256*INT (número/256)
  • byte más significativo=INT (número/256)

Para restituir el número a su valor original, utiliza esta otra fórmula:

Fórmula 2:

  • número=byte menos significativo+256*byte más significativo

Vamos ahora con el ejemplo práctico. Ya hemos visto que el principio de nuestro programa Basic no es siempre el mismo. Vamos a averiguar dónde se encuentra en este caso. La dirección de comienzo está contenida en la variable PROG y, para restituir su valor original (no olvidemos que está partido en dos bytes), hay que teclear lo siguiente:

PRINT PEEK 23635+256*PEEK 23636

(Hay que tener en cuenta que por lo general, el octeto menos significativo se almacena en primer lugar).

Una vez hecho esto sabremos dónde comienza exactamente nuestro programa. Anote ese número.

Por otra parte, resulta también necesario conocer dónde acaba el programa. Este detalle puede saberse sólo de forma aproximada, ya que el ordenador cuenta como programa algunos de los bytes que en realidad utiliza para almacenar las variables, pila de cálculo, etc. De todas formas, resulta bastante aproximado basarnos en el dato almacenado en la variable STKEND y que indica el comienzo de la zona libre de RAM. Para conocer este valor hay que aplicar de nuevo la fórmula 2 teniendo en cuenta que el byte menos significativo es el almacenado en primer lugar (PEEK 23653) y el más significativo es el que está en la posición de memoria 23654.

Ahora sólo nos queda analizar el contenido de la memoria a partir de esa posición. Para ello, en primer lugar abra el manual de instrucciones por la página 183, donde están reflejados todos los caracteres y comandos al lado de sus correspondientes códigos.

A continuación, debe introducir la siguiente instrucción:

FOR n=comienzo TO comienzo + 21: PRINT n, PEEK n: NEXT n

Esto hará que se impriman en pantalla las primeras posiciones de memoria del programa y sus correspondientes contenidos.

Veamos su significado. Las dos primeras posiciones contienen el número de la primera instrucción, pero en este caso y como excepción, primero el byte más significativo y luego el menos significativo.

Aplique la fórmula 2 y el resultado será 10, que en efecto corresponde al número de la primera línea. Para cerciorarse de que esto es así, vamos a gastarle una broma a nuestro ordenador. Hagamos que la primera línea de nuestro programa sea la 5000. Para ello, en primer lugar, hemos de descomponer este número en sus octetos más y menos significativos. Utilizando para ello la fórmula 1, obtendremos el siguiente resultado: byte más significativo = 19, byte menos significativo = 136.

Ahora hay que introducir estos valores en la memoria:

POKE comienzo, byte más significativo POKE comienzo+1, byte menos significativo

Haga un listado (LIST) y se sorprenderá al ver lo que ha sucedido. Por supuesto que, en estas circunstancias, el programa no podría funcionar correctamente, por lo que hay que restituir los primitivos valores.

Los dos bytes siguientes indican al ordenador la longitud de la instrucción. Dejémoslos por el momento. El siguiente, tendrá el valor de 234 que corresponde (página 188 del manual) con el comando REM. Si lo desea, puede cambiarlo por cualquier otro que no provoque error en la sintaxis. Por ejemplo, el código 245 imprimirá la palabra DEMOSTRACION y el código 248 salvará en cinta el programa con este mismo nombre.

Haga la prueba haciendo un cambio en esta posición de memoria. Utilice la instrucción:

POKE posición de memoria, 248

Cuando liste de nuevo el programa se encontrará con que la instrucción es distinta pero si intenta ejecutar el programa este dará el mensaje «No sense in Basic». El problema no es propiamente del procedimiento empleado para efectuar el cambio, sino que el error viene dado por que el texto «DEMOSTRACION» tiene más de 10 letras y el sistema no admite que se grabe en cinta un programa con un nombre de más de 10 caracteres.

A continuación, está el código 34 que pertenece a las comillas y, a partir de aquí, comienza el letrero DEMOSTRACION. Después de cerrar de nuevo las comillas, se encuentra el código 13 que indica siempre al ordenador que ha finalizado la instrucción en curso. Esta instrucción tiene, por tanto, 16 bytes (sin contar los cuatro primeros bytes que corresponden al número de instrucción y a la longitud de la misma). Compruebe que esto es así aplicando la fórmula 2 a los bytes que indican la longitud de la instrucción, teniendo en cuenta que, en este caso, el primero es el menos significativo y el segundo el más.

Cada vez que encuentre un número en el programa basic, verá cómo detrás del código 14 (que indica al ordenador que se trata de un valor con el que probablemente tenga que operar), hay 5 bytes que carecen de significado aparente pero que son, en realidad, la representación en coma flotante del mismo número. Es la que el Spectrum utiliza para realizar los cálculos matemáticos que le indica el propio programa.

El proceso se repite para cada línea de programa hasta el final.

Para poder aplicar lo visto hasta ahora a cualquiera de sus programas, puede utilizar la siguiente rutina que ha de incorporar al final del mismo, tecléandola directamente o bien mediante MERGE. Eso sí, asegúrese de que su programa no contiene líneas a partir de la 9900. Para hacerla funcionar haga GO TO 9900.

9900 LET a = (PEEK 23635+256*PEEK 23636)-1: GO SUB 9925: LET a=a+l
9904 FOR a = a TO (PEEK 23653+256*PEEK 23654)
9905 LET a$=CHR$ 63: IF PEEK a>31 THEN LET a$=CHR$ PEEK a
9910 PRINT a; CHR$ 32; PEEK a, a$
9916 IF PEEK a=13 THEN BEEP .5,0: GO SUB 9925
9920 NEXT a
9925 LET linea=256*PEEK (a+l)+PEEK (a+2)
9926 IF linea=9900 THEN PRINT FLASH l: "se acabo el programa": GO TO 9999
9927 PRINT FLASH 1; "comienza la linea "; 256*PEEK (a+1)+PEEK (a+2): RETURN
  • 009/iniciacion.txt
  • Última modificación: d/m/Y H:i
  • por miguel