Un compilador de ZX Spectrum BASIC

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Responder
Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Un compilador de ZX Spectrum BASIC

Mensaje por na_th_an » Sab Feb 02, 2008 12:46 am

Los gráficos, pues con el maravilloso Deluxe Paint y muuucha paciencia :)

Por cierto, mucha suerte con el tema del doctorado. Has elegido una materia muy bonita :)

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Rafa » Sab Feb 02, 2008 1:04 pm

Cuando yo entré en este hilo, en ningún momento se había hablado ni de compiladores cruzados, ni de lenguajes nuevos, ni nada por el estilo.
Pensé que se refería a un Basic que corriera en un Spectrum normal y con programas escritos en Sinclair Basic. Ese fue mi error.
Pero el rodillo ha pasado por encima de mí como si de una inquisición :evil: se tratase... ¡¡ Viva el totalitarismo !! :mrgreen:
¡ Si es que no se puede pensar diferente a los demás !... ¡ Quién me manda ! :(

Algún día terminaré mi proyecto (espero más opiniones que en el hilo que existe sobre Los Menús de los Spectrum de Amstrad para todos los modelos)
RANDOMIZE USR 0

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Boriel » Sab Feb 02, 2008 3:43 pm

Rafa escribió:Cuando yo entré en este hilo, en ningún momento se había hablado ni de compiladores cruzados, ni de lenguajes nuevos, ni nada por el estilo.
Pensé que se refería a un Basic que corriera en un Spectrum normal y con programas escritos en Sinclair Basic. Ese fue mi error.

Cualquier aportación es buena, incluida la tuya. En el primer mensaje que puse dejaba entrever que se trataba de un compilador cruzado: Una herramienta hecha en python (luego se puede convertir a .exe, pero eso es otra historia), que funciona en un PC bajo Windows, Linux y sobre otras muchas plataformas que tengan el intérprete de Python instalado. Por otra parte, compiladores de BASIC de ZX Spectrum ya exiten (el propio de HiSoft)

Por otra parte, estamos hablando de compilación, no de intérprete de BASIC. Algunas de las ideas que tú has expuesto, son interesantes, pero sólo se aplican a intérpretes, y no a compiladores. El programa que se almacena en memoria, nunca será BASIC sino código máquina directo. Se trata de un traductor (en el PC) de BASIC (o un dialecto del mismo) del ZX a ASM para Z80 que corra en el Spectrum.

Por ejemplo: La expresión (3 + 5) / 2, la tendrías que interpretar como tú has expuesto previamente. Pero para un compilador, esa expresión siempre es constante, y se reduce directamente a 4 (lo que significa que en tiempo de ejecución nunca se harán los cálculos de suma y división). Y siempre será así.

Para variables, la expresión 2 * (3 + x) se puede traducir (si x es una variable de tipo byte) como:

Código: Seleccionar todo

LD a, (0xFEFF) ;  0xFEFF es la dirección de memoria donde se almacena X
ADD a, 3
SLR a

Que, desde luego, es mucho más eficiente que operarlo todo en punto f*llante (que es como lo llamo a veces). El punto flotante está muy bien para operaciones matemáticas precisas (sobre todo en ámbito científico), y también se contempla. Pero poder declarar, por ejemplo, que algunas variables siempre serán enteras (las operaciones no enteras se redondean por truncamiento decimal, generalmente) es mucho más eficiente.

Si te fijas, el orden de las operaciones (debido a los paréntesis) ya ha sido ordenado previamente, en la fase de compilación (antes de generar la salida ASM), y nunca más se tiene que hacer ningún tipo de análisis de sintaxis ni precedencia. Ahí es donde se ahorra tiempo. Con un intérprete, siempre que entremos en una linea BASIC se hace una comprobación sintáctica.

En cualquier caso, las opiniones, sugerencias e ideas de todo el mundo son interesantes (lo que incluye a las tuyas).
Rafa escribió:Algún día terminaré mi proyecto (espero más opiniones que en el hilo que existe sobre Los Menús de los Spectrum de Amstrad para todos los modelos)

Le echaré un vistazo. Lo cierto es que apenas he mirado el foro (siempre estaba en el grupo de noticias de usenet).

Gandulf
Nonamed
Mensajes: 1067
Registrado: Lun May 07, 2007 10:06 pm

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Gandulf » Sab Feb 02, 2008 4:14 pm

De la gente que va a usar este compilador, caso de que llegue a terminarse, me parece que los números reales (coma flotante) van a usarse de tarde en tarde, si es que alguna vez se usan. Yo no me preocuparía mucho por ello. En todo caso intentaría escaquearlo y pasarlo al calculador de la ROM de alguna forma, sin importar que sea lento, porque ya te digo que de los posibles usuarios de este compilador (no nos vamos a engañar, cuatro gatos) diría que todos lo usaran para juegos y no van a usar operaciones en coma flotante en la vida.
Un saludo,

Gandulf

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Rafa » Sab Feb 02, 2008 6:43 pm

OK. Yo nunca he hablado de intérprete y considero un compilador de basic como una herramienta que traduce un programa basic a C.M. para que sea más rápido, y ahí es donde se pueden añadir nuevas sentencias y funciones.
Cuando digo traducir, no considero que haya que hacer ninguna comprobación sintáctica. El código generado se queda como está, una sola vez. Y al ser el código generado C.M., POR SUPUESTO que desaparecen los números de línea. Comparto 100 % tu idea del 2*(3+5) y con variables, pero lo dificil es decirle al programa:vete primero a los paréntesis, haz el cálculo y luego lo multiplicas por dos. Luego hay líneas que se complican:

10 LET A=(INT(RND*49)+1)*6 o

20 PRINT AT (N*3)+8, S-(I=1);"ODIO EL LENGUAJE C"

Si, en mi programa, soy capaz de traducir esto, lo más dificil está hecho.
RANDOMIZE USR 0

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Boriel » Sab Feb 02, 2008 8:17 pm

Rafa escribió: [...]
Cuando digo traducir, no considero que haya que hacer ninguna comprobación sintáctica. El código generado se queda como está, una sola vez. Y al ser el código generado C.M., POR SUPUESTO que desaparecen los números de línea. Comparto 100 % tu idea del 2*(3+5) y con variables,
pero lo dificil es decirle al programa:vete primero a los paréntesis, haz el cálculo y luego lo multiplicas por dos.

Eso es lo que hace mi programa precisamente. Para parsear (analizar sintácticamente) una expresión matemática, se definen unas reglas gramaticales (esto es muy largo de poner aquí). Mi herramienta lo que hace es que, al definirle la gramática del BASIC (por ej. de ZX), sabe qué pasos tiene que seguir para leer esas expresiones. Para ello utiliza una pila (stack) y otras estructuras (un array de salida), donde guarda la información y la reordena de forma que sea correcta (como en el ejemplo que te puse).
Rafa escribió:Luego hay líneas que se complican:

Código: Seleccionar todo

10  LET A=(INT(RND*49)+1)*6       o
20 PRINT AT (N*3)+8, S-(I=1);"ODIO EL LENGUAJE C"

Si, en mi programa, soy capaz de traducir esto, lo más dificil está hecho.

Eso ya lo entiende mi programa, por ejemplo. La cuestión que se debatió más arriba es que método de traducción es el más adecuado, puesto que se trata de un programa compilado. Por ponerlo de forma corta, para la línea 10, la expresión después del '=', produciría un esquema de traducción como este:

'(INT(RND*49)+1)*6'
1 Traducir RND (lo mete en el stack)
2 Traducir 49 (lo mete en el stack)
3 Traducir "*" (sacaría y multiplicaría los dos valores anteriores, por ej. en una calculadora de STACK, y dejaría el resultado en el stack )
4 Traducir INT (redondearía el valor del STACK)
5 Traducir 1 (lo mete en el stack)
6 Traducir '+' (Sacaría y sumaría los dos ultimos valores del stack y dejaría el resultado en el mismo)
7 Traducir 6 (mete 6 en el stack)
8 Traducir '*' (hace como en el paso 3)
La herramienta 'sabe' (porque conoce la gramática) que tiene que empezar por los paréntesis interiores, y luego ir hacia atrás. Hacer esto como tu lo planteas (y que es como lo hace el intérprete de BASIC de la ROM) es tedioso, difícil y lento para el ordenador.

Respecto a la pregunta que planteas, se sale un poco del tema aquí, ya que sería hablar de analizadores léxicos y sintácticos. Quizá podríamos hablar de eso en otro lado. En cualquier caso, analizar sintácticamente es costoso tanto en ejecución, como hacerlo a mano. Es un programa complejo (por eso me hice la herramienta). Es encomiable que la ROM del ZX lo haga (se nota que fue hecho a mano), pero también es verdad que el BASIC, por su sencillez lo permite. Hacer un analizador sintáctico de, por ejemplo, C de la misma manera que la ROM del ZX sería una locura.

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Boriel » Sab Feb 02, 2008 8:27 pm

Gandulf escribió:De la gente que va a usar este compilador, caso de que llegue a terminarse, me parece que los números reales (coma flotante) van a usarse de tarde en tarde, si es que alguna vez se usan. Yo no me preocuparía mucho por ello. En todo caso intentaría escaquearlo y pasarlo al calculador de la ROM de alguna forma, sin importar que sea lento, porque ya te digo que de los posibles usuarios de este compilador (no nos vamos a engañar, cuatro gatos) diría que todos lo usaran para juegos y no van a usar operaciones en coma flotante en la vida.

Totalmente de acuerdo. Es más, ya he estado experimentando con rutinas de punto fijo de 32 bits (16 para la parte entera, 16 para la parte decimal). Me ha sorprendido saber que la PSX, gameboy y otras lo usan para dibujar gráficos a gran velocidad, y seguramente era un truco que usaban muchos programadores de ZX en aquella época y que no conocíamos. Con 32 bits de punto fijo, se pueden expresar números negativos y positivos con precisión decente para juegos. Usando el 1er bit para signo, tenemos un rango de: -32768 a 32767 en pasos de 1/65536 (.0000152587), que como se ve, son 4 decimales de precisión, aproximadamente. Es más, es relativamente sencillo de programar, e incluso se podría generalizar a precisión infinita (variable), si se quisiera. Además, he encontrado algoritmos de seno y coseno para punto fijo que usan sólo sumas, restas y desplazamientos.

Si alguien tiene python y quiere probar con punto fijo, me he hecho un programa de prueba, que muestra los resultados de algunas operaciones.

El programa tiene un fallo. El número negativo del final no sale en complemento a 2. Y eso es una duda que tengo: ¿Al hacer una resta binaria, el ZX hace automáticamente la conversión a C2? Si alguien me puede explicar un poco (ya he estado leyendo sobre Complemento a 2, y el NEG del Z80). Lo que no sé, por ejemplo, es si al hacer una resta binaria y dar resultado negativo, el numero ya está en C2 o no, etc.

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Un compilador de ZX Spectrum BASIC

Mensaje por na_th_an » Dom Feb 03, 2008 5:41 am

Exacto, la parte de la CPU de la PSX que se encargaba de hacer la transformación de texturas empleaba punto fijo por motivos de eficiencia (por eso ocurría el famoso "warping" de las texturas de los juegos de esta consola). Para juegos tiene mil aplicaciones. Yo lo suelo emplear mucho porque obtienes movimientos muy suaves (pudiendo emplear ecuaciones de movimiento normales y corrientes) sin perder demasiado tiempo.

sromero
Nonamed
Mensajes: 1221
Registrado: Mar Abr 17, 2007 12:35 pm
Ubicación: Valencia
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por sromero » Dom Feb 03, 2008 8:23 am

na_th_an escribió:Exacto, la parte de la CPU de la PSX que se encargaba de hacer la transformación de texturas empleaba punto fijo por motivos de eficiencia (por eso ocurría el famoso "warping" de las texturas de los juegos de esta consola).


Cosa que, con los juegos 2D del Spectrum (y los 3D que se puedan hacer), no tiene la más mínima relevancia...


Sobre el hilo, me alegro de que Boriel mire "hacia adelante" y su propósito sea el crear un BASIC "como el del Spectrum, pero mejor". Porque para crear un BASIC como el del Spectrum, y atarnos a las mismas limitaciones, ya tenemos el MCODER o el HISOFT.

Además, haciendo eso no está cerrándose a nada, sólo está sacando adelante el subconjunto de operaciones BASIC más útil para los juegos ... nada le impide después ir agregando esas instrucciones que ha dejado atrás, si alguien encuentra que necesita alguna de ellas para usar el programa.

Eso le permitirá sacar algo usable ANTES, y extenderlo después si fuera necesario, en lugar de tardar más en hacer algo que ya tenemos con los compiladores que había en el Spectrum hace 20 años...
NoP / Compiler

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Un compilador de ZX Spectrum BASIC

Mensaje por na_th_an » Dom Feb 03, 2008 1:32 pm

Exacto, no afecta para nada a juegos 2D. Phantomasa 2 por ejemplo usa punto fijo en todas las coordenadas de los sprites, y así puedo conseguir esos movimientos en curvas. Y no se nota que la precisión sea relativamente baja (1/64 de precisión estoy usando) por la "baja" resolución del Spectrum.

¡FIXED es el futuro! :D

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Boriel » Dom Feb 03, 2008 6:18 pm

Bueno, he estado pensando (raro en mí, por otra parte, dicen... :?) una forma de programar subrutinas en básic, con variables en ámbito local. El caso es que, en el PC, el esquema típico de llamadas en un compilador C es algo así (Nota: MOV es el equivalente al LD del Z80):

LLAMADOR:

Código: Seleccionar todo

push <param 1>
push <param 2>
...
push <param n>
call Function:
pop <param n>  |
...                    | ; O bien incrementa el stack N posiciones
pop <param 1>  |


Y el código de la subrutina LLAMADA suele ser:

Código: Seleccionar todo

:Function
push bp
mov bp, sp
mov dx, (bp + 4)  ; Operacion con el parametro 2, por ejemplo
...

pop bp ; fin de subrutina
ret

Ejemplos de este código se pueden ver aquí. La desventaja del esquema de llamada de C es que es el llamador el que siempre tiene que quitar los parámetros que puso del Stack. La ventaja es que permite número variables de parámetros (el llamador sabe cuántos parámetros metió en la pila antes de la llamada). Por contra, en PASCAL es siempre el llamado el que quita los parámetros de la pila y coloca allí el resultado. Este esquema es más eficiente (en tiempo y en espacio), pero no permite parámetros variables (siempre hay trucos). En cualquier caso, el ahorro de memoria es un plus, si tenemos en cuenta lo escasa que es en el ZX.

Había pensado algo así para Z80. Es obvio que "bp" se puede simular con IX. Y tenemos algo como:
SUBRUTINA LLAMADA (CALLEE)

Código: Seleccionar todo

:Funcion
push ix
ld ix, 0
add ix, sp  ;  "ld ix, sp"
ld d, (ix + 4) ; operación con el parámetro 2, por ejemplo
...
pop ix ; Comienzo del código de retorno
ex (sp), hl ; HL es la dirección de retorno
ex hl, de ; La guardamos en DE
ld hl, XX + 2 ; XX es el numero de bytes que se metió en la pila
add hl, sp
ld sp, hl    ; hemos hecho SP = SP + XX + 2
ex hl, de
jp (hl)       ; "Ret"

Los parámetros se referencian con IX+n, las variables declaradas locales, con IX-n. El problema es que no podríamos declarar muchas, y dependería del tipo (nunca he hecho funciones de más de 10 parámetros, pero nunca se sabe). Los registros hl y de se pierden. El llamador tiene que haberlos guardado previamente si los necesita. Otra opción es ver el código ASM que genera le compilador de C del z80. ¿Bueno, qué pensáis?
Otros trozos de código: El punto fijo (16bit.16bit) que creo que ya lo tengo, y algún que otro más:

¿Sería interesante pasar del "print" de la ROM o no? Había pensado que, de ser así, no habría "channels" ni nada. Todo va pantalla (24 filas x 32 columnas -segun recuerdo- y punto). De resto se usaría AT, y los colores, usando las mismas variables que la ROM: DF CC o S POSN (creo recordar que es la posición en pantalla, pero no se cuál de ellas), así como ATTR T y P. Por lo visto, debido a la versatilidad de los canales, estas rutinas son bastante lentas (es relativamente sencillo hacer un print de un caracter). De hecho hay algún listado por ahí de MicroHobby con algun "procesador de pantalla".

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Un compilador de ZX Spectrum BASIC

Mensaje por na_th_an » Dom Feb 03, 2008 6:45 pm

Sobre las subrutinas, y que yo sepa, los compiladores de BASIC que soportan SUBs y FUNCTIONs emplean exactamente el mismo paradigma que se emplea en PASCAL. Opino que, por tradición (y coherencia), debería usarse ese método. Si estamos más o menos de acuerdo en que vamos a orientar el tema a juegos, creo que no es necesario dotar de facilidades para incluir un número de parámetros variable (al menos, ningún dialecto de BASIC que yo conozca lo permite sin artificios del tipo pasar el puntero a una estructura).

Por eso opino que deberías pasar del PRINT de la rom y de los canales. A fin de cuentas, el tema de los canales no tiene demasiada aplicación para hacer juegos. Además, podría mejorarse de forma que PRINT pudiese imprimir en cualquiera de las 24 filas sin tener que hacer de forma explícita la orientación al canal de pantalla superior (por defecto) o al de pantalla inferior (PRINT #0;). Con soportar los AT y todos los atributos de color y mezcla (OVER), y los códigos de control embebidos en las cadenas, creo que es suficiente.

A colación, creo que el compilador debería ser capaz de entender secuencias de escape para representar a esos códigos de contro embebidos y ya de paso a los carácteres gráficos. Si recuerdas, el set de carácteres del Speccy contiene códigos de control para especificar posición o color, o para hacer desplazamientos en el rango de códigos ASCII 0-31, y además tenemos que considerar los GDU y los gráficos de bloques. Propongo la siguiente sintaxis:

\XXX, con XXX un número de 0 a 255, representa a CHR$ XXX.
[XY], con X e Y pudiendo valer ., ', :, o espacio, para representar a los bloques gráficos (por ejemplo: [ ] [ '] [.'] [::] [:.],...)
[A], con A un carácter de la A a la U para representar a los GDU ([A][B][C]...).
{COMAND}, sería un atajo por si no queremos acordarnos de los códigos de los comandos de color (PAPER, INK ...) o posición (AT).
{N}, con N un número de 0 a 9, para ser usado en conjunción con el otro.

El compilador debería entender estas secuencias y codificarlas en el binario con su código ASCII correspondiente. Por ejemplo, debería poder traducir la cadena

Código: Seleccionar todo

"{PAPER}{1}{INK}{6}[..][..][.:][::][::][:']['']['']"
a códigos del set de carácteres del Spectrum. Y la rutina impresora, debería entenderlos y hacer los cambios de color, posición, etcétera de acuerdo a lo que va leyendo de la cadena.

Además no hay que olvidar que el set de carácteres hay que buscarlo en PEEK(23606)+256*PEEK(23607)+256 y que los UDGs hay que buscarlos en PEEK(23675)+256*PEEK(23676).

Parecen muchas cosas, pero sólo quitando el tema de los canales y la comprobación de SCROLL? ya estamos ganando muchísimo tiempo.

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

La base, lo primero

Mensaje por Boriel » Dom Feb 03, 2008 8:48 pm

Bueno, antes de empezar a hacer cosas más bestias, vayamos a lo más básico.
Tengo que construirme una serie de rutinas básicas antes de hacer lo demás. Esas rutinas, evidentemente, están en ASM. No conozco mucho del ASM Z80 (bueno, hice mis tonterías de pequeño, con las MicroHobby :(). Así que si alguien me puede ayudar con algunas rutinas, se lo agradecería (son sencillas).

Aquí va la primera:

RUTINA que hace un NEG (complemento a 2) de un número de 32 bits apuntado por HL:
El contenido de los registros AF y AF' quedan alterado tras llamar a esta rutina.

Código: Seleccionar todo

:NEGATE_HL                            ; Negates 32 bit value pointed by HL, +2, +3, +4
      push hl                         ; Saves HL and BC
      pusb bc
     
      ld b, 4                         ; Repeats 4 times
      scf                             ; CF = 1
     
:C2LOOP                               ;
      ex af, af'                      ; saves Carry Flag
      ld a, (hl)
      xor FFh                         ; A <- Inverted bit values at (HL)
      ld c, a                         ; Saves A in C
      ex af, af'                      ; Restores Carry Flag
      ld a, c                         ; Restores A
      adc a, 0                        ; Adds Carry Flag
      ld (hl), a                      ; Saves value to memory
      inc hl                          ; Points HL to next location
      djnz C2LOOP                     ; Repeat until ZERO
     
      pop bc                          ; Restores BC and HL
      pop hl
      ret

Esta rutina es interesante para trabajar con números negativos. Los enteros de 32 bits y Punto Fijo de 32 bits se niegan de la misma manera. Así que sirve para todas ellas. Lo que hace es hallar el Complemento a 2 de la dirección de memoria apuntada por HL (los siguientes 4 bytes). Si alguien cree que se puede mejorar, pues se lo agradecería.
Otra opción es hacerlo directamente sobre los registros (se supone que es más rápido). Por ejemplo, negar el numero de 32 bits formado por HL HL' o negar HL DE. Pero no sé si se puede hacer, ni si será más eficiente.
ACTUALIZACIÓN: El archivo asm se puede ver aquí
Última edición por Boriel el Mar Feb 05, 2008 8:35 pm, editado 3 veces en total.

sromero
Nonamed
Mensajes: 1221
Registrado: Mar Abr 17, 2007 12:35 pm
Ubicación: Valencia
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por sromero » Dom Feb 03, 2008 10:17 pm

Boriel escribió:Bueno, he estado pensando (raro en mí, por otra parte, dicen... :?) una forma de programar subrutinas en básic, con variables en ámbito local.

(...)

Había pensado algo así para Z80.


Hombre, es lo que se hace en el compilador Z88DK ... voy a pegar un ejemplo con varios tipos de parámetros:

Código: Seleccionar todo

//----------------------------------------------------------------------------
void Funcion1( char dato1 )
{
  #asm
     ld hl, 2
     add hl, sp
     ld a, (hl)   ; A = dato1
     (resto funcion)
   #endasm
}


//----------------------------------------------------------------------------
void Funcion( char *puntero, int entero, char dato_a, char dato_b )
{
#asm
 
   ld hl, 2
   add hl, sp
 
   ld a, (hl)   ; a = dato_b
   inc hl        ; ignoramos parte alta del byte
   inc hl
   ld c, (hl)   ; c = dato_a
   inc hl       ; ignoramos parte alta del byte
   inc hl
 
   ex af, af    ; save A (attr) for later
 
   ld e, (hl)
   inc hl
   ld d, (hl)
   inc hl        ; DE = entero

  ld (meloguardo), de

   ld e, (hl)
   inc hl
   ld d, (hl)
   inc hl        ; DE = puntero
 

  (Aqui la funcion)
 
   ret
 
.meloguardo defw 0
 
#endasm
 }



Más o menos es lo que quieres hacer, ¿no?

Para las llamadas, sólo tendrías que pulsar en la pila los parámetros en orden inverso, y ya está. Los punteros no son más que ints 0-65535 referenciando a una posición de memoria, y los chars (aunque en tu basic yo no pondría chars, sólo ints), solo 16 bits con 0 en el byte alto y el valor en el bajo...

saludos.

PD: Recuerda popear lo que pushees :-)
NoP / Compiler

Boriel
Sabreman
Mensajes: 351
Registrado: Lun May 28, 2007 9:55 am
Ubicación: Tenerife
Contactar:

Re: Un compilador de ZX Spectrum BASIC

Mensaje por Boriel » Lun Feb 04, 2008 12:17 am

sromero escribió: Hombre, es lo que se hace en el compilador Z88DK ... voy a pegar un ejemplo con varios tipos de parámetros:

Código: Seleccionar todo

//----------------------------------------------------------------------------
void Funcion1( char dato1 )
{
  #asm
     ld hl, 2
     add hl, sp
     ld a, (hl)   ; A = dato1
     (resto funcion)
   #endasm
}
...


O sea que usan HL. ¿Es eso más rápido que IX+n?
Por ejemplo, para 2 ó 3 parámetros:

Código: Seleccionar todo

ld a, (ix + 0)
ld c, (ix + 2)
ld de, (ix + 4) ; ¿ Esto existe?

Sé que las instrucciones con IX son más largas y más lentas. Si el esquema que has puesto es más eficiente, entonces quizá sea mejor así. Así que lo tendremos en cuenta.

sromero escribió: Más o menos es lo que quieres hacer, ¿no?

Para las llamadas, sólo tendrías que pulsar en la pila los parámetros en orden inverso, y ya está. Los punteros no son más que ints 0-65535 referenciando a una posición de memoria, y los chars (aunque en tu basic yo no pondría chars, sólo ints), solo 16 bits con 0 en el byte alto y el valor en el bajo...

saludos.

PD: Recuerda popear lo que pushees :-)

Veo que concidimos en todo, al menos na_th, tú yo. Respecto a devolver el STACK a su estado original, si uso la forma PASCAL, lo que hago es (según el código que he puesto anteriormente), poner en HL el valor de la dirección de retorno retorno (ex (sp), hl), e incrementar el STACK tantas posiciones como bytes ha metido el llamador. Finalmente hago jp (hl) en vez de ret, y se queda todo como estaba. De esa forma la rutina es la que puede sacar los parámetros del STACK, e incluso puede devolver algun valor de retorno.
Para valores de retorno, una opción es devolverlo en una zona de memoria de 32 bits (como las variables de la ROM). Esto permite devolver punteros (16 bits más bajos), numeros enteros o punto fijo.

Responder

¿Quién está conectado?

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