Jupiter Ace Forth: Utilidades II

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 09 Nov 2022 16:55

Último mensaje de la página anterior:

Versión de ROT en código máquina lo más rápida que he sabido hacerla.

No cabe en la ROM, por lo que se ha de usar como palabra de usuario.

Esta versión es 6 veces más rápida que la original del Ace Forth (y el doble que la de la ROM modificada), pero también tiene un PF casi el triple de grande.

Velocidades medidas en modo FAST

ROT size speed speed
(bytes) (ej./s) (relativa)
---------------------------------
Original 10 2.066 1x
Modific. 10 6.135 3x --> Cabe en ROM
Nuevo 28 12.195 5.9x


Código: Seleccionar todo

; ROT
        LD      HL,($3C3B)      ; SPARE Address of byte past data stack's end.
        DEC     HL
        LD      D,(HL)
        DEC     HL
        LD      E,(HL)
        DEC     HL
        LD      B,(HL)
        LD      (HL),D
        DEC     HL
        LD      C,(HL)
        LD      (HL),E       
        DEC     HL
        LD      D,(HL)
        LD      (HL),B
        DEC     HL
        LD      E,(HL)
        LD      (HL),C
        LD      HL,($3C3B)      ; SPARE
        DEC     HL
        LD      (HL),D
        DEC     HL
        LD      (HL),E
        JP      (IY)            ; Back to Forth.


Recordar que ROT original está programado internamente en Ace Forth, no en código máquina. De ahí que sea relativamente lento.

rot.TZX
(125 Bytes) Descargado 5 veces

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 09 Nov 2022 22:20

Versión de OVER en código máquina lo más rápida que he sabido hacerla.

No cabe en la ROM, por lo que se ha de usar como palabra de usuario.

Esta versión es 7 veces más rápida que la original del Ace Forth (y un 45% más que la de la ROM modificada), pero también tiene un PF el doble de grande.

Velocidades medidas en modo FAST

OVER size speed speed
(bytes) (ej./s) (relativa)
---------------------------------
Original 10 2.198 1x
Modific. 10 10.638 4.8x --> Cabe en ROM
Nuevo 21 15.385 7x

Código: Seleccionar todo

; OVER
        LD      HL,($3C3B)      ; SPARE Address of byte past data stack's end.
        DEC     HL
        DEC     HL
        DEC     HL
        LD      D,(HL)
        DEC     HL
        LD      E,(HL)
        LD      HL,($3C3B)
        LD      (HL),E
        INC     HL
        LD      (HL),D
        INC     HL
        LD      ($3C3B),HL      ; SPARE
        JP      (IY)            ; Back to Forth.


Recordar que OVER original está programado internamente en Ace Forth, no en código máquina. De ahí que sea relativamente lento.

over.TZX
(119 Bytes) Descargado 4 veces

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 09 Nov 2022 23:20

Versión de PICK en código máquina lo más rápida que he sabido hacerla.

No cabe en la ROM, por lo que se ha de usar como palabra de usuario.

Esta versión es tan solo 37% más rápida que la original del Ace Forth con un PF 5 veces mayor (*).

Velocidades medidas en modo FAST

PICK size speed speed
(bytes) (ej./s) (relativa)
---------------------------------
Original 5 4.785 1x
Nuevo 26 6.579 1.4x

Código: Seleccionar todo

; PICK
        LD      HL,($3C3B)      ; SPARE> Address of byte past data stack's end.
        DEC     HL
        LD      B,(HL)
        DEC     HL
        LD      C,(HL)
       
        SLA     C               ; BC=2*BC
        RL      B
       
        XOR     A               ; Clear Carry
       
        SBC     HL,BC           ; HL=address low byte of integer to "pick".
       
        LD      E,(HL)          ; DE=integer to pick
        INC     HL
        LD      D,(HL)
       
        LD      HL,($3C3B)      ; old SPARE, it has not been updated, still pointing where index was.
        DEC     HL
        LD      (HL),D
        DEC     HL
        LD      (HL),E
       
        JP      (IY)            ; Back to Forth.


(*) El PICK original utiliza código de ROLL, por eso es tan pequeña.

pick.TZX
(124 Bytes) Descargado 4 veces

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 10 Nov 2022 16:51

En este post descartaba la posibilidad de hacer una versión 100% en código máquina de la palabra compilante de usuario ULOOP.

Hoy me he dado cuenta que hay una manera de hacerlo.

Aducía en aquel post que tal palabra se estropearía al ser analizada/corregida por REDEFINE si se movía en el diccionario al tener un OF a continuación de la misma que REDEFINE interpretaría como un/unos CAs.

La solución es embeber el OF dentro del PF de la palabra en código máquina. La única limitación es que queda descartada la posibilidad de un OF de tamaño variable.

Ahora bien, palabras como ULOOP compatible con NEXT que tienen una parte compilante bastante compleja, puede ser bastante pesado hacerlas en código máquina.

Teniendo en cuenta que la parte compilante no influye para nada en la velocidad de ejecución, no compensa tenerla que hacer en código máquina. Es por eso que considero que las compilantes 100% en c.m. deberían reservarse a palabras compilantes de usuario más bien sencillitas en lo que a su parte compilante se refiere.

Intentaré hacer algún ejemplo concreto, aunque solo sea para verificar si todo esto que acabo de decir es correcto o un error de bulto....

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 10 Nov 2022 23:37

Defino aquí la palabra FAST? que devuelve 1 si estamos en modo FAST o 0 si estamos en modo SLOW

Fundamento: Ace Forth utiliza el registro IY del Z80 para almacenar la dirección donde saltar cuando se termina la ejecución de la palabra en curso. Según si estamos en modo SLOW o FAST esta dirección es una u otra. (Manual del JA página 148)

Concretamente:

Modo SLOW: $4C8 (1224)
Modo FAST: $4B9 (1209)

FAST? utiliza la palabra auxiliar GETIY en código máquina que simplemente pone en la pila el valor del registro IY del Z80.

16 BASE C!
CODE GETIY FD C, E5 C, D1 C, D7 C, FD C, E9 C,
DECIMAL

: FAST?
GETIY 1209 =
;


Fuente de GETIY

Código: Seleccionar todo

; GETIY
        PUSH    IY
        POP     DE
        RST     10H     ; Pone DE en la pila.
        JP      (IY)    ; Vuelve a Forth


NOTA: La palabra CODE que he usado es la de Dutra que genera GETIY como primitiva, por lo que no hace falta CODE para que funcione. Si se usara el CODE del manual del JA, sí que debería estar presente.

isfast.tzx
(127 Bytes) Descargado 2 veces

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 11 Nov 2022 10:26

Elurdio escribió:En este post descartaba la posibilidad de hacer una versión 100% en código máquina de la palabra compilante de usuario ULOOP.

Hoy me he dado cuenta que hay una manera de hacerlo.
···
La solución es embeber el OF dentro del PF de la palabra en código máquina.
···


Desde luego, si yo fuera miembro de una hipotética Academia del Ace Forth me habrían expulsado de modo fulminante tras hacer pública tal "solución".

Menuda burrada solté... -banghead -banghead

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 11 Nov 2022 11:55

Versión de DROP en código máquina lo más rápida que he sabido hacerla.

No cabe en la ROM, por lo que se ha de usar como palabra de usuario.

Esta versión es un 50% más rápida que la original del Ace Forth pero ocupa algo más del doble.

Velocidades medidas en modo FAST

DROP size speed speed
(bytes) (ej./s) (relativa)
---------------------------------
Original 3 17.241 1x
Nuevo 7 25.641 1.5x

Código: Seleccionar todo

; DROP
        LD      HL,$3C3B    ; Contiene la dirección del byte justo después del final de la pila
        DEC     (HL)
        DEC     (HL)
        JP      (IY)


drop.TZX
(105 Bytes) Descargado 1 vez

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 12 Nov 2022 13:04

Pila vs Variables (I)

A raíz de este hilo de @Iapetus he estudiado un poco el tema "Pila versus Variables".

Desde los tiempos de la HP-48SX con su lenguaje de programación "tipo Forth" interioricé un mantra: El manejo de números es más rápido en la pila que usando variables.

Mantra que parecía evidente y no me lo cuestioné en todo este tiempo.

Pero en Ace Forth la cosa dista bastante de ser así por varios motivos. Así, en lo que respecta a la pila:

  1. La pila en el Ace Forth es software. NO utiliza la pila hardware o interna del Z80 que el Ace Forth se reserva para la pila de Retornos.
  2. Las palabras para el manejo de la pila NO son todas primitivas. En concreto NO lo son: OVER y ROT.
  3. En la programación de las que sí son primitivas ha primado el tamaño a la rapidez, por disponer de poca memoria ROM.

Punto 1

Esto parece obvio y lo he aceptado sin más, pero vete a saber...

Así, por ejemplo, según la tabla de este post (fila "dup"/columna "Corrected") se ve que la velocidad del DUP de IS-Forth (que usa pila hardware) es ~2.3x la del Ace Forth. Pero el DUP modificado del Ace Forth (ver unos posts más arriba) es 1.9x el original, por lo que nos sale que:

DUP IS-Forth es 1.2x DUP Ace Forth modificado. Y si tenemos en cuenta que el Enterprise va a 4 Mhz y el JA a 3.25 la conclusión es que, en este caso concreto, el DUP va igual de rápido tanto con pila software como hardware.

No deja de ser una comparación burda. Para verlo más a fondo habría que comparar todas las palabras de pila (dup, swap, rot, etc.) y no solo DUP además de ver si se puede optimizar la velocidad de las mismas en el Enterprise, cosa que a priori no creo, pues dispone de 16K de ROM (vs 8K del JA) por lo que "imagino" que optó por optimizar velocidad y no espacio.

(continuará...)

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 12 Nov 2022 23:18

Si has programado una palabra en código máquina del tipo primitiva, o sea, las que se generan con el ensamblador de Boldfield, con el CODE de Dutra o cargando la rutina en código máquina en el PF de una tipo CREATE y luego cambiando el CF de modo que apunte al inicio de la rutina en código máquina.

Dicho de otro modo, si la palabra tiene el código máquina en su PF y el CF apunta al inicio de dicho código máquina (normalmente apunta al PFA pero podría apuntar a otro punto del PF).

En este caso se cumple que:

DE apunta al PFA de la palabra que se está ejecutando
HL apunta a la dirección de memoria apuntada por el CF de la palabra.

Normalmente el CF apunta al PFA por lo que a menudo ambos (DE y HL) apuntan al PFA.

Si la has creado con el CODE del manual del JA (la palabra es una definida con la definidora de usuario CODE), entonces:

HL apunta al PFA de la palabra que se está ejecutando.

Las creadas con CODE del JA siempre arrancan la rutina en código máquina por el inicio del PF, o sea, por el PFA.

Esta información es útil si el código máquina necesita saber dónde se encuentra en memoria cuando se ejecute.

Decir que esta información se deduce al examinar el "intérprete interno" del Ace Forth (también llamado secuenciador o intérprete de direcciones) que empieza en la dirección $04B9 de la ROM. Es la rutina que se encarga de ejecutar las palabras compiladas.

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 13 Nov 2022 13:15

Veamos un ejemplo sencillo de aplicación de lo dicho.

Recordemos que en Ace Forth las palabras pueden moverse en el diccionario por lo que no podemos usar direcciones absolutas en el código máquina que apunten dentro de la palabra.

El assembler de Boldfield permite hacerlo (si no se especifica un origen) pero antes de ejecutar la palabra hay que "ajustarla" ejecutando ADR cada vez que la palabra cambie de posición en memoria.

Nuestro ejemplo es el clásico "primer programa" de escribir el mensaje "Hola mundo" en pantalla.

Llamamos a nuestra palabra TEST y la definimos de tal manera que sea una primitiva (PF contiene el código máquina) y su Code Field CF apunta al inicio de la rutina en código máquina: Etiqueta PRI:. (*)

Tal como hemos definido TEST nos encontramos en el primer caso del post anterior, por lo que sabemos que

DE = PFA de TEST

Código: Seleccionar todo

MSG:    .BYTE   "Hola mundo"   

PRI:    EX      DE,HL           ; HL apunta a MSG
        LD      BC,10           ; BC = size mensaje MSG
        LD      DE,9216+(32*4)  ; DE apunta a la quinta línea pantalla (contando desde arriba)
        LDIR
        JP      (IY)            ; Vuelta a Forth


Aunque la palabra TEST se mueva en memoria (**) siempre sabe que MSG empieza en la dirección almacenada en el par de registros DE

Otro ejemplo podría ser que tenemos una serie de datos al principio, en vez del mensaje. Entonces la rutina podría utilizar IX o IY como base para cargar/almacenar/operar los datos.

PUSH DE
POP IX
···
···
···
LD B,(IX+n)
···
LD (IX+m),C
···
etc.

siendo también una rutina totalmente relocalizable.

Rcordad que Ace Forth utiliza IX para indexar las variables del sistema. Así que, antes de terminar la rutina hay que restaurar su valor:
LD  IX,$3C00


(*) Detallo aquí como la construyo (ya explicado en posts antiguos del hilo "Utilidades")

La rutina en código máquina la escribo en Notepad++ y la compilo con TASM29. Luego cargo el fichero TEST.bin (21 bytes) en el PF de TEST definido así:

CREATE TEST 21 ALLOT Crea la palabra TEST como tipo CREATE.
TEST . Imprimo en pantalla el PFA de TEST

Conocido el PFA de TEST hago en EightyOne:

File->Load Memory Block con Address = PFA y Filename el TEST.bin

Como vemos en el fuente, nuestra rutina empieza después del texto a imprimir, que ocupa 10 bytes. Para que TEST sea una palabra tipo primitiva su CF debe apuntar al interior del PF. En nuestro caso ha de apuntar a PFA+10, dónde la etiqueta PRI:

TEST DUP 10 + SWAP 2- !

pues TEST pone en la pila su PFA. Sabemos que CFA=PFA-2 y CF=(CFA). Hacemos CF=PFA+10.

Ahora TEST es una palabra tipo primitiva y ejecutará el código máquina en la posición PFA+10 (en PRI:)

(**) Recordemos que una palabra se puede mover en memoria si cargamos con LOAD el diccionario que la contiene sobre un diccionario existente o a raíz de utilizar REDEFINE con palabras por debajo de ella o si es ella la que se redefine.

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 13 Nov 2022 15:16

Pila vs Variables (II)

Elurdio escribió:···
Pero en Ace Forth la cosa dista bastante de ser así por varios motivos. Así, en lo que respecta a la pila:

  1. La pila en el Ace Forth es software. NO utiliza la pila hardware o interna del Z80 que el Ace Forth se reserva para la pila de Retornos.
  2. Las palabras para el manejo de la pila NO son todas primitivas. En concreto NO lo son: OVER y ROT.
  3. En la programación de las que sí son primitivas ha primado el tamaño a la rapidez, por disponer de poca memoria ROM.
···


Punto 2

La palabra ROT está definida internamente como una palabra Ace Forth así:

: ROT
R> SWAP >R SWAP
;

Su PF son solo 10 bytes pero a costa de tener una velocidad de ejecución de 2.066 ejecuciones/segundo.

Debería estar definida en código máquina para ser rápida.

La versión modificada para optimizar la velocidad alcanza las 12.195 ejecuciones/segundo (5.9x) pero a costa de un PF de 28 bytes.

He conseguido una modificación que alcanza una velocidad de 6.135 ej/s (3x) pero también con 10 bytes, lo que permite ponerla en la ROM en lugar de la original.

Otro tanto sucede con la palabra OVER que está definida internamente como una palabra Ace Forth así:

: OVER
R> DUP >R SWAP
;

Su PF son solo 10 bytes pero a costa de tener una velocidad de ejecución de 2.198 ej/s.

Debería estar definida en código máquina para ser rápida.

La versión modificada para optimizar la velocidad alcanza las 15.385 ej/s (7x) a costa de un PF de 21 bytes.

He conseguido una modificación que alcanza las 10.638 ej/s (4x) también con 10 bytes, por lo que cabe en la ROM para substituir a la original.

Las versiones que caben en la ROM, tanto de ROT como de OVER, son versiones ligeramente modificadas de las que vienen en el programa Turtle Graphics Pack.

(continuará)

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor dancresp » 13 Nov 2022 20:17

Realmente estás haciendo un trabajo increíble con este sistema.

Al empezar a leer, sobretodo la parte de la reprogramación de las palabras que vienen por defecto, de cual sería el rendimiento de este equipo si se hubieran hecho las cosas como tú explicas. Si ya de por si el equipo es rápido, comparado con el BASIC, con un poco más de ROM, habría sido brutal.

Mis conocimientos en Forth a tu lado son casi ridículos, aunque con todo soy capaz de hacer algunas cosillas con este lenguaje que siempre me ha fascinado.

Felicidades por estos posts. Son realmente interesantes.
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: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 16 Nov 2022 00:02

Ahora que estoy repasando el código máquina del Copiador de Búfers, he aprovechado y repasado también el asunto descrito en éste post:

Elurdio escribió:En el programa que hice que permite guardar copias del búfer de entrada, sigo utilizando mi método de detectar si estamos en el búfer de entrada comprobando el valor del registro SP del Z80, por lo que solo puedo detectar si estamos en el búfer de entrada "principal".

Para que funcione ?LINE se ha de ejecutar y en nuestro caso está todo parado, pues usamos una interrupción para "observar" como está el Ace Forth. Hemos de detectar que estamos en el búfer de entrada con el Ace Forth en suspensión.

Como el método de chequear el SP solo nos detecta el principal he intentado encontrar algo al estilo del método Dutra (pero con el Ace Forth supendido) y todo parece indicar que, cuando estamos en el búfer de entrada "principal" el valor de la primera posición de la pila de Retornos es $4F7.

En cambio para otros búfer de entrada ejecutados con QUERY no es posible detectarlos o, más bien, no veo como hacerlo. Seguiré pensando/probando a ver si encuentro alguna manera. Igual estoy espeso, lo tengo delante de las narices y no lo veo...

Lo que sí parece que se puede detectar con el Ace Forth suspendido es si estamos en el búfer de entrada por la ejecución de EDIT.

Aquí no nos sirve lo de comprobar el bit#2 y/o bit·6 del byte de la variable FLAGS, pues estos solo se activan al entrarse el búfer de entrada con ENTER, (solo si la palabra era larga, permanecerán a 1 mientras se edita el 2º o sucesivos bloques).

Pero en cambio, parece ser que la ultima posición de la pila de Retornos siempre vale $16F3 durante un EDIT.

Si lograra encontrar la manera de detectar que estoy en QUERY en modo suspendido, entonces podría (aunque no sé si sería conveniente) hacer que el copiador de Búferes copiara no solo el "principal" sino también tras producirse un RETYPE (una palabra no reconocida). Pues tendría todas las herramientas necesarias para saber que estamos un búfer (principal o no) distinto del de EDIT (el único caso que no quiero copiar).


He estado haciendo pruebas y comprobaciones, incluido consultar el desensamblado ROM de EDIT y creo poder asegurar que ciertamente, el último valor de la pila de Retornos siempre vale $16F3 si estamos editando una palabra.

Siendo así ya puedo almacenar cualquier búfer de entrada que no sea un EDIT como pretendía y no solo el "principal". Haré una versión del copidor de búfers que trabaje así y la probaré a ver si realmente vale la pena, pues aún tengo dudas que almacenar líneas de corrección de errores (RETYPE) sea conveniente.

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 16 Nov 2022 11:42

.
Me tendré que tomar unas vacaciones del Ace Forth pues cada vez estoy peor... -banghead

Hoy me he puesto a aprovechar el hecho de haber confirmado que durante un EDIT la pila de retornos contiene en su última posición el valor $16F3.

Y estando en la tarea, me doy cuenta que el problema no era que no hubiera confirmado lo del EDIT sino que es otro, a saber, que NO encuentro la manera de detectar que estamos en el búfer de entrada en general (o sea, que estoy en un QUERY)... como se explica en el último párrafo del post referenciado.

EDIT: Algo bueno ha salido de esto. Creo que he encontrado como saber que estamos en QUERY con el Ace en suspensión. Lo comprobaré a fondo antes de meter la pata de nuevo.

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 16 Nov 2022 12:48

Para detectar si estamos en un QUERY he mirado el desensamblado de la ROM del Ace Forth.

Para no tener que "rastrearlo" todo, he mirado qué valores de los que hay en la pila de retornos cuando estoy en el búfer de entrada apuntan a la zona del QUERY en el desensamblado.

Y he encontrado esto:

L059B:  BIT     5,(HL)                  ; wait for interrupt to set the bit.
JR Z,L059B ; loop until.

Por un lado me acabo de enterar para que sirve el bit #5 de la variable del sistema FLAGS (la apuntada por HL en este fragmento). Ahora solo me restan los bits 0,1 y 7 (si es que tienen alguna función). El manual solo documenta los bits 2,3,4 y 6. Este bit #5 se pone a 1 cuando se pulsa la tecla ENTER durante la interrupción.

Cuando se ejecuta QUERY el Forth entra en este bucle a la espera que se cumpla la condición (que se active el bit 5 de FLAGS STATIN).

Entretanto se ejecuta una interrupción cada 0.02 segundos. Allí se controla lo que se teclea en el búfer, por lo que se va rellenando con lo que escribamos hasta que pulsemos ENTER momento en que se activa el bit #5 de FLAGS STATIN.

Lo bueno es que el copiador de búfers intercepta la interrupción original para sus asuntos. Por lo que sé a ciencia cierta que si estoy en un QUERY con el Ace en supensión (en la interrupcion) tiene que haber en la pila de retornos un $059B o un $059D (es la dirección del JR Z,L059B del desensamblado), uno de los dos por narices. Solo me resta determinar la posición en relación al valor de SP.

EDIT (25-11-2022): Me equivoqué con respecto al bit #5 de la variable del sistema FLAGS. El par de registros HL apunta a la variable del sistema STATIN $3C28 y no a la FLAGS como afirmé. Por tanto es el bit #5 de la variable del sistema STATIN el que se pone a 1 cuando se pulsa la tecla ENTER.

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 24 Nov 2022 11:06

Ahora que me he "quedado seco" en Ace Forth en cuanto a temas que comentar y/o cosas que hacer, para no perder el contacto y olvidarme rápidamente de todo me he puesto a leer este libro sobre Forth del año 1989.

Me ha llamado la atención esta sección que reproduzco parcialmente a continuación sobre sus "desventajas" con la que comulgo:

The disadvantages of Forth
Given that there are so many advantages to using Forth, there must
obviously be some disadvantages, as well. One of the biggest
objections that many people have is that, although word definitions are
very easy to write, they are very difficult to understand afterwards
,
particularly if they have been written by someone else. The main
reason for this is that most numbers are processed on the stack, rather
than by using variables. With variables, it is possible to get a general
idea of what is happening to each parameter, particularly if the names
of the variables bear some relation to their function. But when the
stack is used, it is not at all obvious which numbers are actually being
processed.
Another problem is thatmany features which are already built in to
most languages have to be defined by the user in Forth
. Because Forth
can easily be extended, this does not limit the power of the language,
but it does mean that a programmer has to have a reasonably good
understanding of how the computer stores and processes numbers
before he can produce sophisticated applications. For example, stringhandling
words are not available in most versions of Forth. It is fairly
easy to write these, but to do so the programmer has to understand
how the elements of the string are processed by the machine. Arrays
also have to be created from scratch, and most versions of Forth do not
handle floating-point arithmetic. Another problem is that, although it
is possible to handle very large numbers in Forth, this again requires an
understanding of the way that numbers are processed. By contrast,
someone writing a program in BASIC would not need to know
anything about how BASIC actually worked, provided that he
understood how to use all the commands.

···
···

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

Re: Jupiter Ace Forth: Utilidades II

Mensajepor Elurdio » 25 Nov 2022 12:35

Cuando trabajamos con la pila, si queremos modificar el valor de una posición de la misma lo tenemos fácil si es una de las tres primeras posiciones. Así, supongamos que queremos sumarle 1:

  • Posición 1 -> 1+
  • Posición 2 -> SWAP 1+ SWAP
  • Posición 3 -> ROT 1+ ROT ROT
  • Posición 4 -> 4 ROLL 1+ 4 ROLL 4 ROLL 4 ROLL
  • etc.
Ya vemos que a partir de la posición 4, además de usar ROLL (que precisa un parámetro), para devolver el resultado a su posición original hemos de realizar 3 veces seguidas 4 ROLL.

En general, para la posición n sería: n ROLL 1+ <(n-1) veces n ROLL>

En estos casos resulta útil haber definido previamente la palabra ROLLD (*) que es igual que ROLL pero realiza la rotación en sentido inverso. Así, para sumar uno a la posición n haríamos:

n ROLL 1+ n ROLLD

(*) En el hilo "Utilidades" en los posts sobre NEXT ya puse la definición de ROLLD tanto en Forth como en código máquina (de ésta solo el fuente). Aprovecho para poner aquí el .TZX del ROLLD en código máquina.

rolldmc.TZX
(163 Bytes) Descargado 1 vez


Volver a “Jupiter Ace”

¿Quién está conectado?

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