QL80
Description of the page content
Z80 assembler written in SuperBASIC for the Sinclair QL.
Tags:
QL80 is a Z80 assembler written in SuperBASIC for the Sinclair QL. I used it to wrote a lot of Z80 code for the ZX Spectrum.
The comments of the code, and the name of its variables, constants and functions, are in Spanish. The user interface is in Spanish, Esperanto and English.
Source code
REMark ---------------------------------------------------------------
REMark QL80
REMark ---------------------------------------------------------------
:
REMark versión: / versio: / version: 0.40
:
REMark Ensamblador de Z80 para el ordenador Sinclair QL
REMark Z80-asemblilo por la komputilo Sinclair QL
REMark Z80 assembler for the Sinclair QL computer
:
REMark Copyright (C) 1992 Marcos Cruz (http://programandala.net)
REMark Licencia/Permesilo/License: http://programandala.net/license
:
REMark Límites de esta versión:
REMark Cxiversiaj limoj:
REMark Limits of this version:
:
REMark - 4095 etiquetas de 6 letras, que empiecen por mayúscula
REMark - 32768 líneas de programa fuente
REMark - 10 parámetros como máximo en DEFB y DEFW
REMark - 136 columnas como mínimo en impresora para los listados
REMark - no puede emplearse el punto y coma dentro de las cadenas
REMark - lista las etiquetas por orden de creación, no alfabético
:
REMark Herramientas usadas: / Uzitaj iloj: / Toolkits used:
:
REMark Care/QJUMP Toolkit II 2.11
REMark TURBO Toolkit 1.32
REMark TURBO Compiler 1.09
:
REMark ---------------------------------------------------------------
:
REMark (1.00)
REMark 1988
REMark Intento de hacer un ensamblador en Forth
REMark que traduzca lenguaje ensamblador del Z80 escrito
REMark de forma totalmente estándar en un fichero de texto
REMark Abandonado debido a las complicaciones:
REMark pantallas del Forth, tratamiento de ficheros, cadenas...
:
REMark (2.00)
REMark 1988
REMark En SuperBasic
REMark Intento de hacer un ensamblador que interprete
REMark los nemónicos Z80 como órdenes de Basic
:
REMark (3.00)
REMark 1988
REMark Intento de ensamblador en Forth que lea
REMark una versión especial de ensamblador de Z80, adaptada
REMark a la sintaxis del Forth: los nemónicos son palabras,
REMark el programa está escrito en pantallas de Forth, etc.
REMark Abandonado antes de ser totalmente depurado
REMark por no poder usarlo para compilar Z80 estándar
:
REMark (4.00)
REMark 1988
REMark Primera versión esquelética en SuperBasic con plantemientos
REMark totalmente tradicionales: dos pasadas
:
REMark (4.44)
REMark 1988 06
:
REMark (6.30) 0.00
REMark 1988
REMark Primera versión realmente utilizable, después de
REMark sucesivas búsquedas de errores
:
REMark (6.40) 0.01
REMark 1988
REMark - Detecta etiquetas con más de seis caracteres y da error
:
REMark (7.00) 0.02
REMark - Reconoce cadenas de un carácter en las expresiones
:
REMark (8.00) 0.10
REMark - Crea fichero objeto con cabecera para enviar al Spectrum
REMark - Emplea la parte superior de la pantalla, no la inferior
REMark - Emplea más órdenes del Toolkit II, y menos del Turbo Toolkit
REMark - Muestra correctamente la línea, en caso de error
REMark - Corregido error al calcular "dir_vale", en "localiza_etiqueta%"
:
REMark (9.00) 0.20
REMark - Lista todos los errores posibles sin detener el ensamblado
REMark - Añadido el procedimiento "lista_error"
REMark - Cita línea del módulo en la que se produce cada error
REMark - Corregido error de "RETurn" en "ex%"
REMark - Añadida comparación de parámetros en la primera pasada en "RET"
REMark - Si se agota el espacio para las etiquetas, le añade la memoria libre
:
REMark (9.01) 0.21
REMark 1989 04 17
REMark - Corregida columna de impresión del nombre del módulo actual
REMark - Inicializada variable "fin_cadena_no_encontrado" en "interpreta"
:
REMark (10.00) 0.22
REMark - Eliminado el tratamiento final de error en la ventana
REMark - Trasladado "bifurca_a_nemónico%" al interior de "ensambla"
REMark para conseguir un poco más de velocidad
REMark - Corregidos un par de parámetros positivos de llamada a "lista_error"
REMark - Cambiadas comparaciones "IF x=0" a "IF NOT(x)", para mayor velocidad
REMark - Eliminada inicialización "fichero_fuente$=OPT_CMD$"
REMark - Ajustes para acelerar la impresión en la ventana
REMark - Tinta blanca sobre papel negro
REMark - Correcta colocación de la ventana y del borde
REMark - Eliminada instrucción "MODE 4"
REMark - Empleada "n_" como índice de bucles, en vez de "n" y "n_par"
REMark - Eliminadas "n_pendiente" y "n_eti" del "IMPLICIT%", que no se usaban
REMark - Antigua variable "fin_cadena_no_encontrado" convertida en entera
REMark - Trasladado "ensambla" al interior de "bucle_principal"
REMark - Añadidos los procedimientos
REMark - "borra_ventana"
REMark - "muestra_error"
REMark - "pausa"
REMark - "escribe_nombre_fichero"
REMark - Trasladado "guarda_etiqueta%" al interior de "ensambla"
REMark - Trasladado "coge_etiqueta%" al interior de "interpreta"
REMark - Traladado "interpreta" al interior de "ensambla"
REMark - Eliminada comprobación de longitud en "localiza_etiqueta%"
REMark - Eliminadas instrucciones "TRA", residuos de versiones antiguas
REMark - Perfeccionado y corregido el procedimiento "lista_error"
REMark - Añadido el recuento de líneas del fichero fuente principal
REMark - Trasladado el código de "DEFM" al interior de "ensambla"
REMark - Trasladado el código de "*F" al interior de "ensambla"
:
REMark (10.01) 0.23
REMark - "org_inicial" se inicializa con 0 en lugar de con 25000
REMark - Permite espacios intermedios entre los elementos de las
REMark expresiones numéricas a interpretar, y avisa de ellos
REMark - Añadidos los procedimientos
REMark - "lista_aviso"
REMark - "lista_mensaje"
REMark - Reseteada "núm_líneas_mód%" dentro del bucle "pasada"
REMark - Preparada la ventana de ensamblado tras inicializar las
REMark variables y flags, en lugar de antes
REMark - Si se agota el espacio de etiquetas, detiene el ensamblado
:
REMark (10.02) 0.24
REMark - Corregido error en "*L+", que se producía al no haberse
REMark abierto fichero de salida
REMark - Incluido, para lo anterior, el flag "listar_fuente%"
REMark - Corregido error en la petición de dispositivo de salida,
REMark donde se saltaba a "lista_error" en vez de a "muestra_error"
:
REMark (10.10) 0.25
REMark - Permite elegir si se crea el fichero objeto con cabecera especial
REMark para ser enviado al Spectrum directamente
REMark - Para ello se crea el flag "fichero_objeto_Spectrum%"
REMark - Si se responde en blanco a las preguntas "S/N", se considera "n"
REMark - Las instrucciones de apertura del fichero objeto han sido sacadas
REMark de la sección REMAINDER del SELECT de errores y colocadas detrás
REMark de la estructura REPEAT
:
REMark (10.11) 0.26
REMark - Los créditos del programa están cifrados,
REMark para que no puedan ser alterados
REMark - Nueva función "descifrado$" y nuevas variables:
REMark "texto_c$" y "texto_d$"
:
REMark (10.20) 0.27
REMark - La opción de no crear código objeto ha sido eliminada,
REMark con lo cual la ejecución es algo más rápida
:
REMark (10.21) 0.28
REMark 1990 01
REMark - Se ha añadido un cierre de fichero objeto en el caso de
REMark finalizar el ensamblado con error, que faltaba
:
REMark (11.00) 0.30
REMark 1990 12 -> 1991 01
REMark - El nombre pasa a ser "QL-Z80" en lugar de "Quantum Z80"
REMark - Se puede elegir la lengua de trabajo entre:
REMark Español, Esperanto, English
REMark - Corregidas dos errores ortográficos: "Lineas" por "Líneas"
REMark - Los mensajes de error aparecen en la lengua de trabajo
:
REMark (11.10) 0.31
REMark 1991 10
REMark - Corregida la inicialización de la variable
REMark "fichero_objeto_spectrum%", que quedaba a cero si la
REMark lengua de trabajo no era el castellano
REMark - El procedimiento "pausa" siempre hace una pausa infinita
REMark - El número máximo de etiquetas es 4095, para que su espacio
REMark no pase de 32768 bytes, y poder emplear MOD en
REMark el procedimiento "localiza_etiqueta%"
REMark - La validez de la etiqueta encontrada en "localiza_etiqueta%"
REMark se combrueba con MOD, para mayor velocidad
REMark - Corregida la falta de la palabra "líneas" en la lengua de
REMark trabajo en la ventana informativa final
REMark - El número de errores final aparece en la lengua de trabajo
REMark - Eliminados "peekw" y "pokew" en favor de PEEK y POKE_W
REMark - Eliminada "texto1$" por redundante e innecesaria
REMark - Añadido REMAINDER que faltaba en "error_en_lengua$"
REMark - Revisados todos los textos, especialmente en esperanto
REMark - La variable "segundos%" pasa a ser real, para evitar
REMark el límite de 9 horas de ensamblado
:
REMark (11.20) 0.32
REMark 1991 12 29
REMark - Reconoce IF, ELSE y ENDIF para controlar el ensamblado
REMark - Permite hasta 36 caracteres en nombres de ficheros
REMark - Corregido error, sustituido "S" por sí$
REMark - No altera el nombre de fichero fuente si no acaba en "_asm"
REMark - Pide el idioma mediante EDIT$, para no perder el cursor
:
REMark (11.21) 0.33
REMark 1992 01 07
REMark - Corregido error que se producía al responder en blanco
REMark a la elección de lengua de trabajo (la tarea se borraba)
REMark - Actualizados los títulos de crédito
REMark - Alterado el procedimiento "descifrado$" para compatibilizarlo
REMark con el programa codificador Nomkasxilo 1.00
REMark (se ha invertido el bucle que examina el texto)
REMark - El nombre pasa a ser simplemente QL80 en vez de QL-Z80
:
REMark (11.30) 0.40
REMark 1992 04 05
REMark - Cierra el fichero objeto aun si no tiene cabecera de Spectrum
REMark - Corregidos graves errores en el ensamblado condicional; ahora:
REMark 1) DEFM y *F no actúan cuando ensamblar%=0
REMark 2) IF no actúa cuando ensamblar%=0
REMark 3) ELSE y ENDIF actúan siempre, aun cuando ensamblar%=0
REMark 4) Si ensamblar%=0, no se leen las etiquetas
REMark 5) Si ensamblar%=0, no se examinan los parámetros de los
REMark comandos que deben o pueden llevarlos
REMark - Cambiado el nombre de ensamblando% a ensamblado%, más adecuado
REMark - Añadida la función mayúsculas$, para comprobar mejor la extensión
REMark del nombre del fichero fuente, _asm o _ASM
REMark - Cambiada la traducción "fronto" por "dosierkapo"
REMark - Añadido el procedimiento abre_ventanas
:
REMark 0.50
REMark 1996
REMark cosas a medio hacer:
REMark COSAS POR HACER:
REMark PRIORITARIAS
REMark - Nueva interfaz, a modo de las ventanas del Pointer Environment
REMark - Crear ficheros objeto para Spectrum también en formato TAP
REMark - Dividir el programa en módulos
REMark para hacerlo más fácil de editar y mantener, ya que la velocidad
REMark no es un problema con la QXL
REMark - Revisar y normalizar el uso de extensiones de Turbo y TK2
REMark SECUNDARIAS
REMark - Eliminar límite de 4096 etiquetas
REMark - Listar etiquetas por orden alfabético
REMark - Eliminar límite de 32768 líneas de código fuente
REMark - Eliminar límite de 10 parámetros en DEFB y DEFW
REMark - Decidir sobre los idiomas de trabajo
REMark - La variable segundos puede ser entera de nuevo,
REMark ya que el límite de 9 horas de ensamblado es suficiente
REMark DIFíCILES
REMark - Reconocer el punto y coma en los parámetros
REMark - Permitir etiquetas de longitud variable
REMark - Permitir cualquier combinación de espacios y tabuladores como separadaores
:
REMark Abreviaturas en nombres de variables
REMark ant antigua/o
REMark dir dirección
REMark dis dispositivo
REMark exp expresión
REMark h_ high, parte alta de un valor de 16 bits
REMark l_ low, parte baja de un valor de 16 bits
REMark len longitud de una cadena
REMark lon longitud
REMark máx máximo/a
REMark mód módulo
REMark n_ índice de bucle
REMark núm número
REMark org origen, dirección del código objeto en el Spectrum
REMark p_ parámetro de entrada en una función
REMark par parámetro
REMark pri primera/o
REMark últ último/a
:
REMark Variables enteras implícitas
IMPLICIT% n_, n_parámetro, n_nemónico, pasada, registro1, registro2, tipo1, núm_par, n_par, operación, pseudo_nemónico, tipo_elemento, cód_letra, flag_error, ctexto, lengua
:
REMark Bucle principal -----------------------------------------------
:
REPeat bucle_principal
CLEAR:REMark si no, el espacio libre de la tarea se va reduciendo
REMark Constantes y variables inicializadas
últ_nemónico%=78:REMark 75 en v11.10
últ_parámetro%=30
núm_máx_parámetros%=10
lon_nombre%=36:REMark 32 en v11.10
lon_máx_línea%=115:REMark 136, menos lo que añade el ensamblado
lon_media_línea%=20:REMark longitud media de las líneas
lon_parámetro%=lon_máx_línea%-12
bytes_máx_listados%=4
REMark Cadenas
DIM fichero_fuente$(lon_nombre%)
DIM módulo_fuente$(lon_nombre%)
DIM fichero_objeto$(lon_nombre%)
DIM dis_listado$(lon_nombre%)
DIM dis_errores$(lon_nombre%)
DIM código_objeto$(bytes_máx_listados%*2)
DIM línea$(lon_máx_línea%)
DIM línea_original$(lon_máx_línea%)
DIM línea_anterior$(lon_máx_línea%)
DIM etiqueta$(6)
DIM comando$(4)
DIM parámetros$(lon_parámetro%)
DIM un_parámetro$(lon_parámetro%)
DIM elemento$(lon_parámetro%)
DIM letra$(1)
DIM comillas$(1)
DIM plural$(2)
DIM texto_c$(80)
DIM texto$(60):REMark para guardar el texto en la lengua en uso
DIM texto2$(60):REMark para guardar el texto en la lengua en uso
DIM sí$(1)
DIM no$(1)
REMark Matrices
DIM tipo_par%(núm_máx_parámetros%)
DIM valor_par%(núm_máx_parámetros%)
DIM identificador_par%(núm_máx_parámetros%)
DIM valor_exp(núm_máx_parámetros%)
DIM nemónico$(últ_nemónico%,4)
DIM nemónico%(últ_nemónico%,2)
REMark nemónico%(n,0)=identificador
REMark nemónico%(n,1)=número mínimo de parámetros
REMark nemónico%(n,2)=número máximo de parámetros
RESTORE
FOR n_=0 TO últ_nemónico%
READ nemónico%(n_,0),nemónico$(n_),nemónico%(n_,1),nemónico%(n_,2)
END FOR n_
DIM parámetro$(últ_parámetro%,lon_parámetro%)
DIM parámetro%(últ_parámetro%,2)
REMark parámetro%(n,0)=identificador
REMark parámetro%(n,1)=tipo
REMark parámetro%(n,2)=valor
FOR n_=0 TO últ_parámetro%
READ parámetro%(n_,0),parámetro$(n_),parámetro%(n_,1),parámetro%(n_,2)
END FOR n_
REMark Canales
ventana%=4
fichero_fuente%=5
fichero_objeto%=6
dis_listado%=7
dis_errores%=8
REMark Pantalla
abre_ventanas
pausa
REMark Elegir lengua de trabajo
REPeat elige_lengua
CLS#ventana%
PRINT#ventana%," 1=Español 2=Esperanto 3=English ?: ";
letra$=EDIT$(#ventana%,"2",1)
IF LEN(letra$) AND letra$ INSTR "123":EXIT elige_lengua
END REPeat elige_lengua
lengua=letra$
SELect ON lengua
=1:sí$="S":no$="N":REMark Español
=2:sí$="J":no$="N":REMark Esperanto
=3:sí$="Y":no$="N":REMark English
END SELect
REPeat ensambla
REMark Inicializar variables previas al ensamblado
flag_error=0
línea$=""
núm_errores%=0
ensamblado%=0:REMark indicador de ensamblado aún no comenzado
REMark Pedir nombre de fichero fuente
abierto_fichero_fuente%=0
REPeat pide_fichero_fuente
CLS#ventana%
SELect ON lengua
=1:texto$="Fichero fuente"
=2:texto$="Asembla dosiero"
=3:texto$="Source file"
END SELect
PRINT#ventana%," ";texto$;": ";
fichero_fuente$=EDIT$(#ventana%,fichero_fuente$,lon_nombre%)
IF fichero_fuente$="":EXIT ensambla
REMark Detectar errores
flag_fichero=DEVICE_STATUS(fichero_fuente$)
SELect ON flag_fichero
=-8,-20
REMark Abrir fichero fuente
OPEN_IN#fichero_fuente%,fichero_fuente$
abierto_fichero_fuente%=1
lon_fichero_fuente=FLEN(#fichero_fuente%)
núm_líneas%=lon_fichero_fuente/lon_media_línea%
EXIT pide_fichero_fuente
=-3,-6,-7,-9,-11,-12,-16
muestra_error flag_fichero
=REMAINDER
muestra_error -7:REMark no encontrado
END SELect
NEXT pide_fichero_fuente
END REPeat pide_fichero_fuente
REMark Pedir tipo de fichero objeto
REPeat pide_tipo_fichero_objeto
CLS#ventana%
SELect ON lengua
=1:texto$="¿Cabecera para"
=2:texto$="Dosierkapo por"
=3:texto$="Header for"
END SELect
PRINT#ventana%," ";texto$;" ZX Spectrum? ";
letra$=EDIT$(#ventana%,sí$,1)
IF letra$==sí$ OR letra$==no$:EXIT pide_tipo_fichero_objeto
END REPeat pide_tipo_fichero_objeto
fichero_objeto_Spectrum%=LEN(letra$)&&(letra$==sí$)
bytes_objeto=0:REMark inicializar contador de bytes objeto
IF mayúsculas$(fichero_fuente$(LEN(fichero_fuente$)-3 TO))="_ASM"
fichero_objeto$="ram1"&fichero_fuente$(5 TO LEN(fichero_fuente$)-3)
ELSE
fichero_objeto$="ram1"&fichero_fuente$(5 TO)&"_"
END IF
IF fichero_objeto_Spectrum%
fichero_objeto$=fichero_objeto$&"SpectrumCODE"
ELSE
fichero_objeto$=fichero_objeto$&"Z80"
END IF
REMark Pedir fichero objeto
REPeat pide_fichero_objeto
CLS#ventana%
SELect ON lengua
=1:texto$="Fichero objeto"
=2:texto$="Masxinkoda dosiero"
=3:texto$="Object file"
END SELect
PRINT#ventana%," ";texto$;": ";
fichero_objeto$=EDIT$(#ventana%,fichero_objeto$,lon_nombre%)
IF fichero_objeto$="":EXIT ensambla
REMark Detectar errores
flag_fichero=DEVICE_STATUS(fichero_objeto$)
SELect ON flag_fichero
=-3,-6,-7,-9,-11,-12,-16,-20
muestra_error flag_fichero
NEXT pide_fichero_objeto
END SELect
EXIT pide_fichero_objeto
END REPeat pide_fichero_objeto
OPEN_OVER#fichero_objeto%,fichero_objeto$
IF fichero_objeto_Spectrum%
REMark - procedimiento abre_ventanas
REMark Poner cabecera para enviar después el código al Spectrum
BPUT#fichero_objeto%,3,0,0,0,0,255,255,255,255
END IF
REMark Pedir número máximo de etiquetas
dir_zona_etiquetas=0
núm_máx_etiquetas%=1+INT(núm_líneas%/8.3)
REPeat pide_núm_máx_etiquetas
CLS#ventana%
SELect ON lengua
=1:texto$="Número máximo de etiquetas"
=2:texto$="Plej da etikedoj"
=3:texto$="Largest number of labels"
END SELect
PRINT#ventana%," ";texto$;": ";
núm_máx_etiquetas%=EDIT%(#ventana%,INT(núm_máx_etiquetas%),4)
IF núm_máx_etiquetas%<1 OR núm_máx_etiquetas>4095:EXIT ensambla
lon_zona_etiquetas=núm_máx_etiquetas%*8
IF lon_zona_etiquetas>(PEEK_L(163856)-PEEK_L(163852))
muestra_error -3:REMark sin memoria
NEXT pide_núm_máx_etiquetas
END IF
EXIT pide_núm_máx_etiquetas
END REPeat pide_núm_máx_etiquetas
dir_zona_etiquetas=ALCHP(lon_zona_etiquetas)
REMark Pedir dispositivo de errores
REPeat pide_dis_errores
CLS#ventana%
SELect ON lengua
=1:texto$="Listado de errores hacia"
=2:texto$="Erarlisto al"
=3:texto$="List of errors to"
END SELect
PRINT#ventana%," ";texto$;": ";
dis_errores$=EDIT$(#ventana%,"ser1",lon_nombre%)
IF dis_errores$="":EXIT ensambla
flag_fichero=DEVICE_STATUS(dis_errores$)
SELect ON flag_fichero
=-3,-6,-7,-9,-11,-12,-16,-20
muestra_error flag_fichero
=REMAINDER
REMark Abrir dispositivo de listado errores
OPEN_OVER#dis_errores%,dis_errores$
abierto_dis_errores%=1
EXIT pide_dis_errores
END SELect
NEXT pide_dis_errores
END REPeat pide_dis_errores
REMark Pedir listado fuente S/N
REPeat pide_listado_fuente
CLS#ventana%
SELect ON lengua
=1:texto$="Listado fuente"
=2:texto$="Asembla printajxo"
=3:texto$="Source list"
END SELect
PRINT#ventana%," ";texto$;"? ";
letra$=EDIT$(#ventana%,no$,1)
IF letra$==sí$ OR letra$==no$:EXIT pide_listado_fuente
END REPeat pide_listado_fuente
listado_fuente%=(letra$==sí$):REMark flag invariable
listar_fuente%=listado_fuente%:REMark flag variable durante el ensamblado, según los pseudonemónicos "*L-" y "*L+"
REMark Pedir listado de etiquetas S/N
REPeat pide_listado_etiquetas
CLS#ventana%
SELect ON lengua
=1:texto$="Listado de etiquetas"
=2:texto$="Etikedlisto"
=3:texto$="Label list"
END SELect
PRINT#ventana%," ";texto$;"? ";
letra$=EDIT$(#ventana%,no$,1)
IF letra$==sí$ OR letra$==no$:EXIT pide_listado_etiquetas
END REPeat pide_listado_etiquetas
listado_etiquetas%=(letra$==sí$)
REMark Pedir fichero de listado
abierto_dis_listado%=0
IF listado_fuente% OR listado_etiquetas%
REPeat pide_dis_listado
CLS#ventana%
SELect ON lengua
=1:texto$="Dispositivo de salida"
=2:texto$="Listkanalo"
=3:texto$="Output device"
END SELect
PRINT#ventana%," ";texto$;": ";
dis_listado$=EDIT$(#ventana%,dis_listado$,lon_nombre%)
IF dis_listado$="":EXIT ensambla
flag_fichero=DEVICE_STATUS(dis_listado$)
SELect ON flag_fichero
=-3,-6,-7,-9,-11,-12,-16,-20
muestra_error flag_fichero
=REMAINDER
REMark Abrir dispositivo de listado
OPEN_OVER#dis_listado%,dis_listado$
abierto_dis_listado%=1
EXIT pide_dis_listado
END SELect
END REPeat pide_dis_listado
END IF
REMark Pedir confirmación
REPeat pide_confirmación
CLS#ventana%
SELect ON lengua
=1:texto$="¿Todo correcto"
=2:texto$="Cxio en ordo"
=3:texto$="All right"
END SELect
PRINT#ventana%," ";texto$;"? ";
letra$=EDIT$(#ventana%,sí$,1)
IF letra$==sí$ OR letra$==no$:EXIT pide_confirmación
END REPeat pide_confirmación
IF letra$==no$:EXIT ensambla
REMark Inicializar variables para el ensamblado
org_inicial=0:REMark dirección de origen por defecto
núm_líneas_fuente%=0:REMark número de líneas del fichero fuente principal
núm_etiquetas%=0
ensamblando_módulo%=0
es_un_registro%=0
era_índice%=0
hay_pendiente%=0
listar_línea_anterior%=1
ensamblado%=1:REMark indicar que comienza el ensamblado
ensamblar%=1:REMark situación inicial activa de la bandera de IF
módulo_fuente$=fichero_fuente$
REMark Preparar la pantalla
borra_ventana
SELect ON lengua
=1:texto$="Pasada"
=2:texto$="Pasxo"
=3:texto$="Pass"
END SELect
PRINT#ventana%," ";texto$
SELect ON lengua
=1:texto$="Línea"
=2:texto$="Linio"
=3:texto$="Line"
END SELect
AT#ventana%,0,10
PRINT#ventana%,texto$
SELect ON lengua
=1:texto$="Ensamblando"
=2:texto$="Elasemble"
=3:texto$="Assembling"
END SELect
AT#ventana%,0,22
PRINT#ventana%,texto$;":"
escribe_nombre_fichero
REMark Realizar el ensamblado
tiempo_inicio=DATE
FOR pasada=1 TO 0 STEP -1
núm_líneas_mód%=0
AT#ventana%,0,8
PRINT#ventana%,2-pasada
SET_POSITION#fichero_fuente%,0
dir_org=org_inicial
núm_líneas%=0:REMark número de líneas total de todos los ficheros
AT#ventana%,0,16:PRINT#ventana%," ":REMark borrar no. línea
REPeat ensambla_módulo
REPeat lee_línea
REMark Leer línea y quitarle comentarios
IF EOF(#fichero_fuente%):EXIT lee_línea
INPUT#fichero_fuente%,línea_original$
línea$=línea_original$
IF listar_fuente%
IF NOT(pasada)
REMark segunda pasada
lista_línea_anterior
REMark Preparar listado de la línea actual
dir_org_anterior=dir_org
listar_dir_anterior%=1
código_objeto$=""
bytes_listados%=0
línea_anterior$=línea_original$
END IF
END IF
núm_líneas%=núm_líneas%+1
núm_líneas_mód%=núm_líneas_mód%+1
AT#ventana%,0,16
PRINT#ventana%,núm_líneas%
hasta%=";" INSTR línea$
IF hasta%
IF hasta%=1:listar_dir_anterior%=0:NEXT lee_línea
línea$=línea$(1 TO hasta%-1)
END IF
len_línea%=LEN(línea$)
REMark ** IF NOT(len_línea%):listar_dir_anterior%=0:NEXT lee_línea
REMark Separar etiqueta
hay_etiqueta%=0
IF pasada
REMark primera pasada
IF ensamblar%
etiqueta$=línea$(1 TO 6)&" "
IF etiqueta$(1 TO 6)<>" "
REMark la etiqueta no está en blanco
IF localiza_etiqueta%=-7
REMark la etiqueta no existía antes
REMark Guardar la etiqueta
IF núm_etiquetas%=núm_máx_etiquetas%
lista_error -3:REMark sin memoria
EXIT ensambla
END IF
POKE$ dir_etiqueta,etiqueta$
POKE_W dir_etiqueta+6,dir_org
núm_etiquetas%=núm_etiquetas%+1
dir_etiqueta_nueva=dir_etiqueta:REMark guardar posición
hay_etiqueta%=1
ELSE
REMark la etiqueta ya existía
lista_error -8:REMark ya existe
END IF
END IF
END IF
END IF
REMark Separar comando
hay_comando%=0
núm_par=0
IF len_línea%>7
REMark la línea es mayor que la zona de etiquetas
línea$=línea$&" ":REMark añadir dos espacios al final
hasta%=" " INSTR línea$(8 TO)+7
IF hasta%>8
REMark hay algo en la zona de comandos
comando$=línea$(8 TO hasta%-1)
parámetros$=línea$(hasta%+1 TO)
IF comando$<>FILL$(" ",LEN(comando$))
REMark el comando no está en blanco
REMark Buscar comando en la lista de nemónicos
FOR n_nemónico=0 TO últ_nemónico%
IF comando$=nemónico$(n_nemónico)
núm_mín_par%=nemónico%(n_nemónico,1)
núm_máx_par%=nemónico%(n_nemónico,2)
hay_comando%=1
EXIT n_nemónico
END IF
END FOR n_nemónico
IF hay_comando%
SELect ON n_nemónico
=3
IF ensamblar%
REMark DEFM
bytes%=0
IF parámetros$(1)<>'"'
lista_error -15:REMark parámetro incorrecto
ELSE
len_un_parámetro%=LEN(parámetros$)
REPeat corta_cadena
IF parámetros$(len_un_parámetro%)<>" ":EXIT corta_cadena
len_un_parámetro%=len_un_parámetro%-1
parámetros$=parámetros$(1 TO len_un_parámetro%)
END REPeat corta_cadena
IF parámetros$(len_un_parámetro%)<>'"'
lista_error -15:REMark parámetro incorrecto
ELSE
IF pasada
bytes%=len_un_parámetro%-2
ELSE
FOR n_=2 TO len_un_parámetro%-1
pokea CODE(parámetros$(n_))
END FOR n_
bytes%=n_-1
END IF
END IF
END IF
END IF
=75
REMark *F
IF ensamblar%
hasta%=" " INSTR parámetros$
IF hasta%=1
lista_error -15:REMark parámetro incorrecto
EXIT ensambla
END IF
parámetros$=parámetros$(1 TO hasta%-1)
IF ensamblando_módulo%:
lista_error -8:REMark ya existe
ELSE
posición_fuente=POSITION(#fichero_fuente%)
flag_fichero=DEVICE_STATUS(parámetros$)
SELect ON flag_fichero
=-8,-20
REMark Cambiar fichero fuente
CLOSE#fichero_fuente%
módulo_fuente$=parámetros$
núm_líneas_fuente%=núm_líneas_mód%:REMark guardar líneas del fichero fuente principal
núm_líneas_mód%=0:REMark inicializar cuenta de líneas del nuevo módulo
OPEN_IN#fichero_fuente%,módulo_fuente$
ensamblando_módulo%=1
escribe_nombre_fichero
listar_dir_anterior%=0
=-3,-6,-7,-9,-11,-12,-16
lista_error flag_fichero
=REMAINDER
lista_error -7:REMark no encontrado
END SELect
END IF
bytes%=0
END IF
=REMAINDER
IF núm_mín_par% OR núm_máx_par%
IF ensamblar%
REMark Leer parámetros
IF parámetros$<>FILL$(" ",LEN(parámetros$))
no_quedan_parámetros%=0
REPeat separa_parámetros
hasta%="," INSTR parámetros$
IF hasta%
IF hasta%=1
lista_error -21:REMark línea incorrecta
NEXT lee_línea
END IF
un_parámetro$=parámetros$(1 TO hasta%-1)
len_un_parámetro%=LEN(un_parámetro$)
parámetros$=parámetros$(hasta%+1 TO)
ELSE
un_parámetro$=parámetros$
len_un_parámetro%=LEN(un_parámetro$)
REPeat corta_un_parámetro
IF un_parámetro$(len_un_parámetro%)<>" ":EXIT corta_un_parámetro
IF len_un_parámetro%=1:EXIT corta_un_parámetro
un_parámetro$=un_parámetro$(1 TO len_un_parámetro%-1)
len_un_parámetro%=len_un_parámetro%-1
END REPeat corta_un_parámetro
no_quedan_parámetros%=1
END IF
IF núm_par>núm_máx_par%
lista_error -21:REMark línea incorrecta
END IF
REMark Estudiar el parámetro
IF len_un_parámetro%<5
FOR n_parámetro=0 TO últ_parámetro%
IF un_parámetro$=parámetro$(n_parámetro)
es_un_registro%=1
EXIT n_parámetro
END IF
END FOR n_parámetro
END IF
IF es_un_registro%
es_un_registro%=0
identificador_par%(núm_par)=parámetro%(n_parámetro,0)
tipo_par%(núm_par)=parámetro%(n_parámetro,1)
valor_par%(núm_par)=parámetro%(n_parámetro,2)
núm_par=núm_par+1
ELSE
entre_paréntesis%=0
IF un_parámetro$(1)="("
IF un_parámetro$(len_un_parámetro%)=")":entre_paréntesis%=1
END IF
IF entre_paréntesis%
IF un_parámetro$(4) INSTR "+-"
IF un_parámetro$(2 TO 3)="IX"
era_índice%=22:REMark (IX)
ELSE
IF un_parámetro$(2 TO 3)="IY"
era_índice%=23:REMark (IY)
END IF
END IF
END IF
un_parámetro$=un_parámetro$(2 TO len_un_parámetro%-1)
len_un_parámetro%=len_un_parámetro%-2
END IF
IF era_índice%
identificador_par%(núm_par)=parámetro%(era_índice%,0)
tipo_par%(núm_par)=parámetro%(era_índice%,1)
valor_par%(núm_par)=parámetro%(era_índice%,2)
era_índice%=0
núm_par=núm_par+1
un_parámetro$=un_parámetro$(3 TO)
len_un_parámetro%=len_un_parámetro%-2
núm_máx_par%=núm_máx_par%+1
END IF
REMark Interpretar la expresión
hay_pendiente%=0
letra%=0
valor_expresión=0
operación=1:REMark suma por defecto
REPeat interpreta_expresión
fin_cadena_no_encontrado%=0:REMark resetear flag especial de cadenas
elemento$=""
REMark Buscar comienzo del elemento
REPeat busca_elemento
letra%=letra%+1
IF letra%>len_un_parámetro%
lista_error -17:REMark expresión errónea
RETurn
END IF
letra$=un_parámetro$(letra%)
cód_letra=CODE(letra$)
SELect ON cód_letra
=65 TO 90
REMark "A...Z" etiqueta
tipo_elemento=0
elemento$=letra$
EXIT busca_elemento
=48 TO 57
REMark "0...9" número decimal
tipo_elemento=1
elemento$=letra$
EXIT busca_elemento
=35
REMark "#" número hexadecimal
tipo_elemento=2
EXIT busca_elemento
=43
REMark "+" suma, número positivo
operación=1:REMark suma
NEXT busca_elemento
=45
REMark "-" resta, número negativo
operación=2:REMark resta
NEXT busca_elemento
=37
REMark "%" número binario
tipo_elemento=3
EXIT busca_elemento
=34,39
tipo_elemento=5
comillas$=letra$
fin_cadena_no_encontrado%=1
EXIT busca_elemento
=36
REMark "$" contador de programa
tipo_elemento=4
EXIT busca_elemento
=32
REMark espacio
IF pasada
REMark primera pasada
lista_aviso -17:REMark expresión errónea
PRINT#dis_errores%,"(Espacio innecesario ignorado)"
END IF
NEXT busca_elemento
=REMAINDER
lista_error -17:REMark expresión errónea
EXIT interpreta_expresión
END SELect
END REPeat busca_elemento
REMark Coger el resto del elemento
REPeat coge_elemento
letra%=letra%+1
IF letra%>len_un_parámetro%:EXIT coge_elemento
letra$=un_parámetro$(letra%)
IF fin_cadena_no_encontrado%
IF letra$=comillas$
fin_cadena_no_encontrado%=0
NEXT coge_elemento:REMark para que no se sumen las comillas
END IF
ELSE
nueva_operación%=letra$ INSTR "+-*/"
IF nueva_operación%:EXIT coge_elemento
END IF
elemento$=elemento$&letra$
END REPeat coge_elemento
REMark Calcular el valor del elemento
SELect ON tipo_elemento
=0
REMark se trata de una etiqueta
REMark Buscar la etiqueta entre las ya existentes
etiqueta$=elemento$&" "
flag_error=localiza_etiqueta%
SELect ON flag_error
=-8
REMark se encontró la etiqueta
REMark Coger su valor, en dos pasos
REMark (de este modo se evita el signo)
h_=PEEK(dir_etiqueta+6)
valor_elemento=256*h_+PEEK(dir_etiqueta+7)
=-7
REMark la etiqueta no existe
IF NOT(pasada)
REMark segunda pasada
lista_error -7:REMark no encontrado
PRINT#dis_errores%,etiqueta$
END IF
hay_pendiente%=1:REMark aviso para un posible EQU
valor_elemento=0
END SELect
=1
REMark se trata de un número decimal
valor_elemento=elemento$
=2
REMark se trata de un número hexadecimal
valor_elemento=HEX(elemento$)
=3
REMark se trata de un número binario
valor_elemento=BIN(elemento$)
=5
REMark se trata de una cadena
IF LEN(elemento$)<>1
lista_error -17:REMark expresión errónea
END IF
valor_elemento=CODE(elemento$)
=4
REMark se trata del contador de programa
IF LEN(elemento$)>1
lista_error -17:REMark expresión errónea
END IF
valor_elemento=dir_org
END SELect
SELect ON operación
=1
REMark suma
valor_expresión=valor_expresión+valor_elemento
=2
REMark resta
valor_expresión=valor_expresión-valor_elemento
=3
REMark producto
valor_expresión=valor_expresión*valor_elemento
=4
REMark división
valor_expresión=valor_expresión/valor_elemento
END SELect
IF valor_expresión<-32768 OR valor_expresión>65535
lista_error -4:REMark fuera de rango
valor_expresión=0
END IF
IF letra%>=len_un_parámetro%
EXIT interpreta_expresión
END IF
operación=nueva_operación%
END REPeat interpreta_expresión
tipo_par%(núm_par)=128+entre_paréntesis%
identificador_par%(núm_par)=-1:REMark borrar
valor_exp(núm_par)=valor_expresión
núm_par=núm_par+1
END IF
IF no_quedan_parámetros%:EXIT separa_parámetros
END REPeat separa_parámetros
IF núm_par<núm_mín_par%
lista_error -21:REMark línea incorrecta
NEXT lee_línea
END IF
ELSE
IF núm_mín_par%
lista_error -21:REMark línea incorrecta
NEXT lee_línea
END IF
END IF
END IF
ELSE
REMark no tiene que haber parámetros
IF parámetros$<>FILL$(" ",LEN(parámetros$))
lista_error -21:REMark línea incorrecta
NEXT lee_línea
END IF
END IF
pseudo_nemónico=nemónico%(n_nemónico,0)
IF ensamblar%
SELect ON pseudo_nemónico
= 1:bytes%=ld%:REMark LD
=48:bytes%=call%:REMark CALL
=52:bytes%=jr%:REMark JR
=66:bytes%=defb%:REMark DEFB
=67:bytes%=defw%:REMark DEFW
=50:bytes%=jp%:REMark JP
=19:bytes%=logicarit%(182,0):REMark CP
=74:bytes%=push_pop%(0):REMark POP
=73:bytes%=push_pop%(4):REMark PUSH
=15:bytes%=inc_dec%(0):REMark INC
=51:bytes%=ret_%:REMark RET
=18:bytes%=logicarit%(158,0):REMark AND
=45:bytes%=bits%(62):REMark BIT
=39:bytes%=equ%:REMark EQU
= 0:bytes%=logicarit%(166,0):REMark XOR
=14:bytes%=inc_dec%(1):REMark DEC
=13:bytes%=add%:REMark ADD
=49:bytes%=djnz%:REMark DJNZ
= 3:bytes%=nemónico1%(217):REMark EXX
= 2:bytes%=ex%:REMark EX
=17:bytes%=logicarit%(142,0):REMark SUB
= 7:bytes%=nemónico_ed%(176):REMark LDIR
=44:bytes%=giros%(54):REMark SRL
=46:bytes%=bits%(126):REMark RES
=68:bytes%=defs%:REMark DEFS
=55:bytes%=rst%:REMark RST
=11:bytes%=nemónico_ed%(177):REMark CPIR
=26:bytes%=nemónico1%(118):REMark HALT
=27:bytes%=im%:REMark IM
=20:bytes%=logicarit%(174,0):REMark OR
=29:bytes%=nemónico1%(0):REMark NOP
=30:bytes%=nemónico1%(55):REMark SCF
=36:bytes%=giros%(22):REMark RR
=64:bytes%=org%:REMark ORG
=53:bytes%=nemónico_ed%(77):REMark RETI
=47:bytes%=bits%(190):REMark SET
=24:bytes%=nemónico1%(243):REMark DI
=25:bytes%=nemónico1%(251):REMark EI
= 4:bytes%=nemónico_ed%(168):REMark LDD
= 5:bytes%=nemónico_ed%(184):REMark LDDR
= 6:bytes%=nemónico_ed%(160):REMark LDI
= 8:bytes%=nemónico_ed%(169):REMark CPD
= 9:bytes%=nemónico_ed%(185):REMark CPDR
=10:bytes%=nemónico_ed%(161):REMark CPI
=12:bytes%=adc_sbc%(0):REMark ADC
=16:bytes%=adc_sbc%(16):REMark SBC
=21:bytes%=nemónico1%(63):REMark CCF
=22:bytes%=nemónico1%(47):REMark CPL
=23:bytes%=nemónico1%(39):REMark DAA
=28:bytes%=nemónico_ed%(68):REMark NEG
=31:bytes%=giros%(14):REMark RL
=32:bytes%=nemónico1%(23):REMark RLA
=33:bytes%=giros%(-2):REMark RLC
=34:bytes%=nemónico1%(7):REMark RLCA
=35:bytes%=nemónico_ed%(111):REMark RLD
=37:bytes%=nemónico1%(31):REMark RRA
=38:bytes%=giros%(6):REMark RRC
=40:bytes%=nemónico1%(15):REMark RRCA
=41:bytes%=nemónico_ed%(103):REMark RRD
=42:bytes%=giros%(30):REMark SLA
=43:bytes%=giros%(38):REMark SRA
=54:bytes%=nemónico_ed%(69):REMark RETN
=56:bytes%=in%:REMark IN
=61:bytes%=out%:REMark OUT
=69:bytes%=comando_listado%(1):REMark *L+
=70:bytes%=comando_listado%(0):REMark *L-
=76:bytes%=comando_if%:REMark IF
=77:ensamblar%=NOT ensamblar%:REMark ELSE
bytes%=0
=57:bytes%=nemónico_ed%(170):REMark IND
=58:bytes%=nemónico_ed%(162):REMark INI
=59:bytes%=nemónico_ed%(172):REMark INIR
=60:bytes%=nemónico_ed%(186):REMark INDR
=62:bytes%=nemónico_ed%(171):REMark OUTD
=63:bytes%=nemónico_ed%(163):REMark OUTI
=71:bytes%=nemónico_ed%(187):REMark OTDR
=72:bytes%=nemónico_ed%(179):REMark OTIR
END SELect
ELSE
REMark el ensamblado está desactivado por IF
SELect ON pseudo_nemónico
=77:ensamblar%=NOT ensamblar%:REMark ELSE
bytes%=0
=78:ensamblar%=1:REMark ENDIF
bytes%=0
END SELect
END IF
END SELect
dir_org=dir_org+bytes%
ELSE
REMark nemónico no reconocido
lista_error -12:REMark nombre incorrecto
NEXT lee_línea
END IF
ELSE
REMark nemónico en blanco
IF parámetros$<>FILL$(" ",LEN(parámetros$))
lista_error -21:REMark línea incorrecta
NEXT lee_línea
END IF
END IF
END IF
END IF
IF NOT(hay_comando%):listar_dir_anterior%=0
END REPeat lee_línea
REMark se terminaron las líneas del fichero fuente
IF listar_fuente%
REMark Listar la última línea si acabamos la segunda pasada
IF NOT(pasada):lista_línea_anterior
END IF
REMark Volver al fichero principal, si es preciso
IF ensamblando_módulo%
REMark estábamos ensamblando un módulo
CLOSE#fichero_fuente%
OPEN_IN#fichero_fuente%,fichero_fuente$
SET_POSITION#fichero_fuente%,posición_fuente
núm_líneas_mód%=núm_líneas_fuente%:REMark recuperar líneas...
REMark ...del fichero fuente principal, guardadas en comando_fichero%
módulo_fuente$=fichero_fuente$
ensamblando_módulo%=0
escribe_nombre_fichero
NEXT ensambla_módulo
END IF
EXIT ensambla_módulo
END REPeat ensambla_módulo
REMark Inicializar variables para listado en la segunda pasada
listar_dir_anterior%=0
código_objeto$=""
bytes_listados%=0
línea_anterior$=""
IF núm_errores%:EXIT ensambla
END FOR pasada
EXIT ensambla
END REPeat ensambla
REMark Final
BEEP 2500,10
borra_ventana
IF abierto_fichero_fuente%:CLOSE#fichero_fuente%
IF dir_zona_etiquetas:RECHP dir_zona_etiquetas
IF núm_errores%
SELect ON lengua
=1:texto$="error":plural$="es":texto2$="en la pasada"
=2:texto$="eraro":plural$="j":texto2$="en pasxo"
=3:texto$="error":plural$="s":texto2$="in pass"
END SELect
IF núm_errores%=1:plural$=""
PRINT#dis_errores%,\núm_errores%!texto$;plural$!texto2$!2-pasada
CLOSE#fichero_objeto%
ELSE
REMark no hubo error alguno
IF ensamblado%
REMark el ensamblado se realizó
IF fichero_objeto_Spectrum%
REMark Rellenar cabecera del fichero
h_bytes=INT(bytes_objeto/256)
l_bytes=bytes_objeto-256*h_bytes
BPUT#fichero_objeto%\1,l_bytes,h_bytes:REMark número de bytes
h_org=INT(org_inicial/256)
l_org=org_inicial-256*h_org
BPUT#fichero_objeto%\3,l_org,h_org:REMark dirección destino
END IF
CLOSE#fichero_objeto%
REMark Mostrar resultados
SELect ON lengua
=1:texto$="Etiquetas":texto2$="Líneas"
=2:texto$="Etikedoj":texto2$="Linioj"
=3:texto$="Labels":texto2$="Lines"
END SELect
PRINT#ventana%,!texto$;"=";núm_etiquetas%;
PRINT#ventana%,!texto2$;"=";núm_líneas%;
segundos=DATE-tiempo_inicio
IF segundos
SELect ON lengua
=1:texto$="Líneas/minuto":texto2$="Minutos"
=2:texto$="Linioj/minuto":texto2$="Minutoj"
=3:texto$="Lines/minute":texto2$="Minutes"
END SELect
PRINT#ventana%,!texto$;"=";60*(núm_líneas% DIV segundos);
PRINT#ventana%;!texto2$;"=";segundos DIV 60;",";segundos MOD 60
END IF
IF listado_etiquetas%
SELect ON lengua
=1:texto$="Listando etiquetas"
=2:texto$="Listante etikedojn"
=3:texto$="Listing labels"
END SELect
AT#ventana%,0,55
PRINT#ventana%,texto$;"...";
CLS#ventana%,4
PRINT#dis_listado%,\
FOR n_=0 TO núm_etiquetas%-1
dir_etiqueta=dir_zona_etiquetas+8*n_
valor_etiqueta=256*PEEK(dir_etiqueta+6)+PEEK(dir_etiqueta+7)
PRINT#dis_listado%,PEEK$(dir_etiqueta,6);
PRINT_USING#dis_listado%,"######",valor_etiqueta;
PRINT#dis_listado%,!HEX$(valor_etiqueta,16);" ";
IF (n_&&3)=3:PRINT#dis_listado%
END FOR n_
PRINT#dis_listado%
AT#ventana%,0,55
CLS#ventana%,4
END IF
pausa
END IF
END IF
IF abierto_dis_listado%:CLOSE#dis_listado%
CLOSE#dis_errores%
END REPeat bucle_principal
:
REMark Procedimientos y funciones auxiliares ------------------------
:
DEFine PROCedure lista_error(núm_error%)
SELect ON lengua
=1,3:texto$="ERROR"
=2:texto$="ERARO"
END SELect
PRINT#dis_errores%,\texto$;
lista_mensaje núm_error%
núm_errores%=núm_errores%+1
END DEFine lista_error
:
DEFine PROCedure lista_aviso(núm_error%)
SELect ON lengua
=1:texto$="AVISO"
=2:texto$="AVERTO"
=3:texto$="WARNING"
END SELect
PRINT#dis_errores%,\texto$;
lista_mensaje núm_error%
END DEFine lista_aviso
:
DEFine PROCedure lista_mensaje(núm_error%)
SELect ON lengua
=1:texto$="en la línea":texto2$="del módulo"
=2:texto$="en linio":texto2$="de modjulo"
=3:texto$="in the line":texto2$="of the module"
END SELect
PRINT#dis_errores%,!texto$!núm_líneas_mód%!texto2$!módulo_fuente$
PRINT#dis_errores%,línea_original$
PRINT#dis_errores%,error_en_lengua$(núm_error%)
END DEFine lista_mensaje
:
DEFine PROCedure muestra_error(núm_error%)
REMark Muestra error, no de ensamblado, en la ventana
borra_ventana
PRINT#ventana%," ";error_en_lengua$(núm_error%)
pausa
END DEFine lista_error
:
DEFine FuNction error_en_lengua$(núm_error%)
LOCal núm_error
núm_error=ABS(núm_error%)
SELect ON lengua
=1
SELect ON núm_error
=1:texto$="No finalizado"
=2:texto$="Tarea inválida"
=3:texto$="Sin memoria"
=4:texto$="Fuera de rango"
=5:texto$="Búfer lleno"
=6:texto$="Canal no abierto"
=7:texto$="No encontrado"
=8:texto$="Ya existe"
=9:texto$="En uso"
=10:texto$="Fin de fichero"
=11:texto$="Disco/Cartucho lleno"
=12:texto$="Nombre incorrecto"
=13:texto$="Error de transmisión"
=14:texto$="Fallo en inicialización"
=15:texto$="Parámetro incorrecto"
=16:texto$="Medio incorrecto"
=17:texto$="Expresión errónea"
=18:texto$="Desbordamiento"
=19:texto$="No implementado"
=20:texto$="Sólo lectura"
=21:texto$="Línea incorrecta"
=REMAINDER :texto$="Error "&núm_error
END SELect
=2
SELect ON núm_error
=1:texto$="Ne finita"
=2:texto$="Nevalida tasko"
=3:texto$="Sen memoro"
=4:texto$="Preter rango"
=5:texto$="Bufro plena"
=6:texto$="Kanalo ne malfermita"
=7:texto$="Ne trovita"
=8:texto$="Jam ekzistas"
=9:texto$="Uzata"
=10:texto$="Fino de dosiero"
=11:texto$="Plena disko aux bendo"
=12:texto$="Erara nomo"
=13:texto$="Elsendad-eraro"
=14:texto$="Malsukceso dum formatado"
=15:texto$="Erara parametro"
=16:texto$="Disko aux bendo difektita"
=17:texto$="Erara esprimo"
=18:texto$="Preterrangigxo"
=19:texto$="Ankoraux ne estigita"
=20:texto$="Nur legebla"
=21:texto$="Erara linio"
=REMAINDER :texto$="Eraro "&núm_error
END SELect
=3
SELect ON núm_error
=1:texto$="Not complete"
=2:texto$="Invalid job"
=3:texto$="Out of memory"
=4:texto$="Out of range"
=5:texto$="Buffer full"
=6:texto$="Channel not found"
=7:texto$="Not found"
=8:texto$="Already exists"
=9:texto$="In use"
=10:texto$="End of file"
=11:texto$="Drive full"
=12:texto$="Bad name"
=13:texto$="Xmit error"
=14:texto$="Format failed"
=15:texto$="Bad parameter"
=16:texto$="Bad medium"
=17:texto$="Error in expression"
=18:texto$="Overflow"
=19:texto$="Not implemented (yet)"
=20:texto$="Read only"
=21:texto$="Bad line"
=REMAINDER :texto$="Error "&núm_error
END SELect
END SELect
RETurn texto$
END DEFine error_en_lengua$
:
DEFine PROCedure pausa
AT#ventana%,0,81
CURSEN#ventana%
letra$=INKEY$(#ventana%,-1)
CURDIS#ventana%
END DEFine pausa
:
DEFine PROCedure abre_ventanas
OPEN#ventana%,con_504x14a4x0
PAPER#ventana%,0
INK#ventana%,7
borra_ventana
PRINT#ventana%," QL80 0.40 (k) 1992 far Marcos Cruz"
END DEFine ventanas
:
DEFine PROCedure borra_ventana
CLS#ventana%
BORDER#ventana%,2,7,0
END DEFine borra_ventana
:
DEFine PROCedure escribe_nombre_fichero
AT#ventana%,0,36
IF ensamblando_módulo%
PRINT#ventana%,módulo_fuente$
ELSE
PRINT#ventana%,fichero_fuente$
END IF
CLS#ventana%,4
END DEFine
:
DEFine PROCedure lista_línea_anterior
IF listar_línea_anterior%
REMark hay que listar la línea anterior
IF listar_dir_anterior%
REMark hay que listar la dirección de la línea anterior
PRINT_USING#dis_listado%,"#####",dir_org_anterior;
PRINT#dis_listado%," ";HEX$(dir_org_anterior,16);" ";
ELSE
REMark no hay que listar la dirección de la línea aterior
PRINT#dis_listado%," ";
END IF
PRINT#dis_listado%,código_objeto$;
PRINT#dis_listado%,FILL$(" ",9-2*bytes_listados%);línea_anterior$
ELSE
listar_línea_anterior%=1
END IF
END DEFine lista_línea_anterior
:
DEFine FuNction localiza_etiqueta%
REMark Entrada
REMark etiqueta$=etiqueta a localizar, al menos de 6 caracteres
REMark Local
REMark dir_etiquetas=dirección inicial de búsqueda
REMark lon_etiquetas=longitud de la zona de búsqueda
REMark dir_vale=cálculo intermedio
REMark Salida si se encuentra la etiqueta
REMark RETURN -8
REMark dir_etiqueta=dirección de la etiqueta en la zona
REMark Salida si no se encuentra la etiqueta
REMark RETURN -7
REMark dir_etiqueta=primera dirección libre en la zona
etiqueta$=etiqueta$(1 TO 6)
dir_etiquetas=dir_zona_etiquetas
lon_etiquetas=núm_etiquetas%*8+1
REPeat busca_etiqueta
dir_etiqueta=SEARCH_MEMORY(dir_etiquetas,lon_etiquetas,etiqueta$)
IF dir_etiqueta
IF (dir_etiqueta-dir_zona_etiquetas) MOD 8
dir_etiquetas=dir_etiqueta+1
lon_etiquetas=lon_etiquetas-dir_etiquetas+dir_zona_etiquetas
IF lon_etiquetas>7:NEXT busca_etiqueta
ELSE
RETurn -8:REMark ya existe
END IF
END IF
dir_etiqueta=dir_zona_etiquetas+núm_etiquetas%*8
RETurn -7:REMark no encontrado
END REPeat busca_etiqueta
END DEFine localiza_etiqueta%
:
DEFine FuNction descifrado$(texto_c$)
LOCal texto_d$(80)
texto_d$="":REMark texto descifrado
FOR n_=1 TO LEN(texto_c$)
texto_d$=texto_d$&CHR$(CODE(texto_c$(n_))^^255^^(LEN(texto_c$)-n_+1))
END FOR n_
RETurn texto_d$
END DEFine descifrado$
:
DEFine FuNction mayúsculas$(texto$)
LOCal ctexto
FOR n_=1 TO LEN(texto$)
ctexto=CODE(texto$(n_))
SELect ON ctexto
=97 TO 122:texto$(n_)=CHR$(CODE(texto$(n_))-32)
=137:texto$(n_)="Ñ"
=135:texto$(n_)="Ü"
END SELect
END FOR n_
RETurn texto$
END DEFine mayúsculas$
:
REMark Comandos del ensamblador -------------------------------------
:
DEFine FuNction comando_listado%(p_flag):REMark *L+ y *L-
IF NOT(pasada)
REMark segunda pasada
IF listado_fuente%
listar_fuente%=p_flag:listar_dir_anterior%=0
END IF
listar_línea_anterior%=0
END IF
RETurn 0
END DEFine comando_listado%
:
DEFine FuNction comando_if%:REMark IF
IF es_exp_sin_paréntesis%(0)
ensamblar%=valor_exp(0)&&1
ELSE
lista_error -15:REMark parámetro incorrectro
END IF
RETurn 0
END DEFine comando_if%
:
REMark Pseudonemónicos ----------------------------------------------
:
DEFine FuNction defb%:REMark DEFB
IF NOT(pasada)
REMark segunda pasada
FOR n_=0 TO núm_par-1
IF es_exp_sin_paréntesis%(n_)
byte=valor_exp(n_)
IF vale_byte%
pokea byte
ELSE
lista_error -4:REMark fuera de rango
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END FOR n_
END IF
RETurn núm_par
END DEFine defb%
:
DEFine FuNction defs%:REMark DEFS
IF pasada
IF es_exp_sin_paréntesis%(0)
valor=valor_exp(0)
IF dir_org+valor<65536:RETurn valor
lista_error -4:REMark fuera de rango
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
RETurn 0
END IF
valor=valor_exp(0)
IF fichero_objeto%:FOR byte=1 TO valor:pokea 0:REMark rellenar
RETurn valor
END DEFine defs%
:
DEFine FuNction defw%:REMark DEFW
IF NOT(pasada)
REMark segunda pasada
FOR n_=0 TO núm_par-1
IF es_exp_sin_paréntesis%(n_)
pokeaw valor_exp(n_)
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END FOR n_
END IF
RETurn 2*núm_par
END DEFine defw%
:
DEFine FuNction equ%:REMark EQU
IF pasada
REMark primera pasada
IF hay_etiqueta%
IF hay_pendiente%:
lista_error -7:REMark no encontrado
ELSE
IF es_exp_sin_paréntesis%(0)
POKE_W dir_etiqueta_nueva+6,valor_exp(0)
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
ELSE
lista_error -21:REMark línea incorrecta
END IF
ELSE
IF listado_fuente%:dir_org_anterior=valor_exp(0)
END IF
RETurn 0
END DEFine equ%
:
DEFine FuNction org%:REMark ORG
IF pasada
REMark primera pasada
IF es_exp_sin_paréntesis%(0)
IF dir_org=org_inicial:org_inicial=valor_exp(0)
dir_org=valor_exp(0)
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
ELSE
valor=valor_exp(0)
IF fichero_objeto%:FOR byte=1 TO valor-dir_org:pokea 0
dir_org=valor
END IF
RETurn 0
END DEFine org%
:
REMark Nemónicos multiuso -------------------------------------------
:
DEFine FuNction adc_sbc%(p_opcode%):REMark ADC y SBC
REMark Nemónico p_opcode%
REMark -------- ---------
REMark ADC 0
REMark SBC 16
registro1=identificador_par%(0)
IF pasada
REMark primera pasada
IF registro1=1:RETurn logicarit%(0,1):REMark ADC/SBC A,?
RETurn 2:REMark ADC/SBC HL,rr
END IF
REMark segunda pasada
SELect ON registro1
=1:RETurn logicarit%(134+p_opcode%,1):REMark ADD/SBC A,?
=15
REMark ADC/SBC HL,rr
p_opcode%=74-p_opcode%/2
registro2=identificador_par%(1)
SELect ON registro2
=13:pokea_ed p_opcode% :RETurn 2:REMark ADC/SBC HL,BC
=14:pokea_ed p_opcode%+16:RETurn 2:REMark ADC/SBC HL,DE
=15:pokea_ed p_opcode%+32:RETurn 2:REMark ADC/SBC HL,HL
=16:pokea_ed p_opcode%+48:RETurn 2:REMark ADC/SBC HL,SP
END SELect
END SELect
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine adc_sbc%
:
DEFine FuNction bits%(p_opcode%):REMark BIT, SET y RES
REMark Nemónico p_opcode%
REMark -------- ---------
REMark BIT 62
REMark SET 126
REMark RES 190
IF pasada
REMark primera pasada
IF núm_par=3:RETurn 4:REMark BIT b,(Ir+n)
RETurn 2:REMark BIT b,r/(HL)
END IF
REMark segunda pasada
IF es_exp_sin_paréntesis%(0)
bit=valor_exp(0)
IF bit>7
lista_error -4:REMark fuera de rango
bit=0
END IF
registro2=identificador_par%(1)
SELect ON núm_par
=2
REMark BIT b,r/(HL)
IF entre_A_y_HL%(1)
pokea_cb p_opcode%+valor_par%(1)+8*bit
RETurn 2
END IF
=3
REMark BIT b,(Ir+n)
desplazamiento=valor_exp(2)
IF vale_desplazamiento%
SELect ON registro2
=9 :pokea 221:REMark (IX)
=11:pokea 253:REMark (IY)
END SELect
pokea_cb desplazamiento
pokea p_opcode%+8*(bit+1)
RETurn 4
END IF
END SELect
END IF
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine bits%
:
DEFine FuNction giros%(p_opcode%)
REMark Nemónico p_opcode%
REMark -------- ---------
REMark RLC -2
REMark RRC 6
REMark RL 14
REMark RR 22
REMark SLA 30
REMark SRA 38
REMark SRL 54
IF pasada:RETurn 2*núm_par:REMark primera pasada
REMark segunda pasada
registro1=identificador_par%(0)
SELect ON núm_par
=1
REMark GIRO r
IF entre_A_y_HL%(0)
pokea_cb p_opcode%+valor_par%(0)
RETurn 2
END IF
=2
REMark GIRO (Ir+n)
desplazamiento=valor_exp(1)
IF vale_desplazamiento%
SELect ON registro1
=9 :pokea 221:REMark (IX)
=11:pokea 253:REMark (IY)
END SELect
pokea_cb desplazamiento
pokea p_opcode%+8
RETurn 4
END IF
lista_error -4:REMark fuera de rango
=REMAINDER
lista_error -15:REMark parámetro incorrecto
END SELect
RETurn 0
END DEFine giros%
:
DEFine FuNction inc_dec%(p_opcode%)
REMark Nemónico p_opcode%
REMark -------- ---------
REMark INC 0
REMark DEC 1
IF pasada
REMark primera pasada
IF núm_par=2:RETurn 3:REMark INC/DEC (Ir+n)
registro1=identificador_par%(0)
SELect ON registro1
=17:RETurn 2:REMark IX
=18:RETurn 2:REMark IY
END SELect
RETurn 1:REMark INC/DEC rr/r
END IF
REMark segunda pasada
SELect ON núm_par
=1
IF entre_A_y_HL%(0)
REMark INC/DEC r
pokea 4+p_opcode%+8*(valor_par%(0)-2)
RETurn 1
END IF
REMark INC/DEC rr
registro1=identificador_par%(0)
SELect ON registro1
=13 TO 16
REMark INC/DEC BC/DE/HL/SP
pokea 3+8*p_opcode%+16*valor_par%(0)
RETurn 1
=17
REMark INC/DEC IX
pokea_dd 3+8*p_opcode%+16*valor_par%(0)
RETurn 2
=18
REMark INC/DEC IY
pokea_fd 3+8*p_opcode%+16*valor_par%(0)
RETurn 2
END SELect
=2
REMark INC/DEC (Ir+n)
desplazamiento=valor_exp(1)
IF vale_desplazamiento%
registro1=identificador_par%(0)
SELect ON registro1
=9 :pokea_dd 52+p_opcode%:REMark (IX)
=11:pokea_fd 52+p_opcode%:REMark (IY)
END SELect
pokea desplazamiento
RETurn 3
END IF
lista_error -4:REMark fuera de rango
=REMAINDER
lista_error -15:REMark parámetro incorrecto
END SELect
RETurn 0
END DEFine inc_dec%
:
DEFine FuNction logicarit%(p_opcode%,p_par1%)
REMark Nemónico p_opcode%,p_par1%
REMark -------- -----------------
REMark ADD A, 126,1
REMark ADC A, 134,1
REMark SUB 142,0
REMark SBC A, 150,1
REMark AND 158,0
REMark XOR 166,0
REMark CP 182,0
IF pasada
REMark primera pasada
IF núm_par=2+p_par1%:RETurn 3:REMark NEMO-A (Ir+n)
IF es_exp_sin_paréntesis%(p_par1%):RETurn 2:REMark NEMO-A n
RETurn 1:REMark NEMO-A r/(HL)
END IF
REMark segunda pasada
SELect ON núm_par
=1+p_par1%
REMark NEMO-A r/(HL)/n
IF es_exp_sin_paréntesis%(p_par1%)
REMark NEMO-A n
byte=valor_exp(p_par1%)
IF vale_byte%
pokea p_opcode%+72
pokea byte
RETurn 2
END IF
lista_error -4:REMark fuera de rango
ELSE
IF entre_A_y_HL%(p_par1%)
REMark NEMO-A r/(HL)
pokea p_opcode%+valor_par%(p_par1%)
RETurn 1
END IF
END IF
=2+p_par1%
REMark NEMO-A (Ir+n)
desplazamiento=valor_exp(1+p_par1%)
IF vale_desplazamiento%
registro1=identificador_par%(p_par1%)
SELect ON registro1
=9 :pokea_dd p_opcode%+8:REMark (IX)
=11:pokea_fd p_opcode%+8:REMark (IY)
END SELect
pokea desplazamiento
RETurn 3
END IF
lista_error -4:REMark fuera de rango
=REMAINDER
lista_error -15:REMark parámetro incorrecto
END SELect
RETurn 0
END DEFine logicarit%
:
DEFine FuNction nemónico1%(p_opcode%)
IF pasada:RETurn 1:REMark primera pasada
REMark segunda pasada
pokea p_opcode%
RETurn 1
END DEFine nemónico1%
:
DEFine FuNction nemónico_ed%(p_opcode%)
IF pasada:RETurn 2:REMark primera pasada
REMark segunda pasada
pokea_ed p_opcode%
RETurn 2
END DEFine nemónico_ed%
:
DEFine FuNction push_pop%(p_opcode%)
REMark Nemónico p_opcode%
REMark -------- ---------
REMark POP 0
REMark PUSH 4
registro1=identificador_par%(0)
IF pasada
REMark primera pasada
IF núm_par<>1:lista_error -15:REMark parámetro incorrecto
IF registro1=17 OR registro1=18:RETurn 2:REMark PUSH/POP IX/IY
RETurn 1:REMark PUSH/POP rr
END IF
REMark segunda pasada
SELect ON registro1
=22:pokea 241+p_opcode%:RETurn 1:REMark AF
=13:pokea 193+p_opcode%:RETurn 1:REMark BC
=14:pokea 209+p_opcode%:RETurn 1:REMark DE
=15:pokea 225+p_opcode%:RETurn 1:REMark HL
=17:pokea_dd 225+p_opcode%:RETurn 2:REMark IX
=18:pokea_fd 225+p_opcode%:RETurn 2:REMark IY
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
RETurn 0
END DEFine push_pop%
:
REMark Nemónicos concretos -----------------------------------------
:
DEFine FuNction add%:REMark ADD
registro1=identificador_par%(0)
IF pasada
REMark primera pasada
IF registro1=1:RETurn logicarit%(126,1):REMark ADD A,?
IF núm_par<>2
lista_error -15:REMark parámetro incorrecto
RETurn 0
END IF
IF registro1=15:RETurn 1:REMark ADD HL,rr
RETurn 2:REMark ADD Ir,nn
END IF
REMark segunda pasada
SELect ON registro1
=1:RETurn logicarit%(126,1):REMark ADD A,?
=15
REMark ADD HL,rr
registro2=identificador_par%(1)
SELect ON registro2
=13:pokea 9 :RETurn 1:REMark ADD HL,BC
=14:pokea 25:RETurn 1:REMark ADD HL,DE
=15:pokea 41:RETurn 1:REMark ADD HL,HL
=16:pokea 57:RETurn 1:REMark ADD HL,SP
END SELect
=17,18
REMark ADD IX/IY,rr
SELect ON registro1
=17:pokea 221:REMark ADD IX,rr
=18:pokea 253:REMark ADD IY,rr
END SELect
registro2=identificador_par%(1)
SELect ON registro2
=13:pokea 9 :RETurn 2:REMark ADD IX/IY,BC
=14:pokea 25:RETurn 2:REMark ADD IX/IY,DE
=17:IF registro1=17:pokea 41:RETurn 2:REMark ADD IX,IX
=18:IF registro1=18:pokea 41:RETurn 2:REMark ADD IY,IY
=16:pokea 57:RETurn 2:REMark ADD IX/IY,SP
END SELect
END SELect
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine add%
:
DEFine FuNction call%:REMark CALL
IF pasada:RETurn 3:REMark primera pasada
REMark segunda pasada
SELect ON núm_par
=1
REMark CALL nn
IF es_exp_sin_paréntesis%(0)
pokea 205
pokeaw valor_exp(0)
RETurn 3
END IF
=2
REMark CALL cc,nn
IF es_condición%(0)
IF es_exp_sin_paréntesis%(1)
pokea 196+8*valor_par%(0)
pokeaw valor_exp(1)
RETurn 3
END IF
END IF
END SELect
lista_error -15:REMark parámetro incorrecto
RETurn 3
END DEFine call%
:
DEFine FuNction djnz%:REMark DJNZ
IF pasada
REMark primera pasada
IF núm_par<>1:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
IF es_exp_sin_paréntesis%(0)
desplazamiento=valor_exp(0)-dir_org-2
IF vale_desplazamiento%
pokea 16
pokea desplazamiento
ELSE
lista_error -4:REMark fuera de rango
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
RETurn 2
END DEFine djnz%
:
DEFine FuNction ex%:REMark EX
registro2=identificador_par%(1)
IF pasada
REMark primera pasada
IF núm_par=2
IF registro2=17 OR registro2=18:RETurn 2:REMark EX ?,IX/IY
RETurn 1:REMark EX ?,?
END IF
ELSE
REMark segunda pasada
registro1=identificador_par%(0)
SELect ON registro1
=14
REMark EX DE,?
IF registro2=15:pokea 235:RETurn 1:REMark EX DE,HL
=22
REMark EX AF,?
IF registro2=23:pokea 8:RETurn 1:REMark EX AF,AF'
=19
REMark EX (SP),?
SELect ON registro2
=15:pokea 227:RETurn 1:REMark EX (SP),HL
=17:pokea_dd 227:RETurn 2:REMark EX (SP),IX
=18:pokea_fd 227:RETurn 2:REMark EX (SP),IY
END SELect
END SELect
END IF
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine ex%
:
DEFine FuNction im%:REMark IM
IF pasada
REMark primera pasada
IF núm_par<>1:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
IF es_exp_sin_paréntesis%(0)
valor=valor_exp(0)
SELect ON valor
=2:pokea_ed 94
=0:pokea_ed 70
=1:pokea_ed 86
=REMAINDER :lista_error -4:REMark fuera de rango
END SELect
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
RETurn 2
END DEFine im%
:
DEFine FuNction in%:REMark IN
IF pasada
REMark primera pasada
IF núm_par<>1:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
IF entre_A_y_L%(0)
REMark IN r,?
IF NOT(identificador_par%(1))
REMark IN r,(C)
pokea_ed 64+8*(valor_par%(0)-2)
ELSE
IF es_exp_con_paréntesis%(1)
REMark IN r,(n)
IF identificador_par%(0)=1
REMark IN A,(n)
byte=valor_exp(1)
IF vale_byte%
pokea 219
pokea byte
ELSE
lista_error -4:REMark fuera de rango
END IF
END IF
END IF
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
RETurn 2
END DEFine in%
:
DEFine FuNction jp%:REMark JP
IF pasada
REMark primera pasada
IF núm_par=2:RETurn 3:REMark JP cc,nn
IF es_exp_sin_paréntesis%(0):RETurn 3:REMark JP nn
IF identificador_par%(0)=8:RETurn 1:REMark JP (HL)
RETurn 2:REMark JP (IX)/(IY)
END IF
REMark segunda pasada
SELect ON núm_par
=1
IF es_exp_sin_paréntesis%(0)
REMark JP nn
pokea 195
pokeaw valor_exp(0)
RETurn 3
END IF
IF es_tipo%(0,17)
REMark JP (rr)
registro1=identificador_par%(0)
SELect ON registro1
=8 :pokea 233 :RETurn 1:REMark JP (HL)
=9 :pokea_dd 233:RETurn 2:REMark JP (IX)
=11:pokea_fd 233:RETurn 2:REMark JP (IY)
END SELect
END IF
=2
REMark ¿JP cc,nn?
IF es_condición%(0)
IF es_exp_sin_paréntesis%(1)
pokea 194+8*valor_par%(0)
pokeaw valor_exp(1)
RETurn 3
END IF
END IF
END SELect
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine jp%
:
DEFine FuNction jr%:REMark JR
IF NOT(pasada)
REMark segunda pasada
SELect ON núm_par
=1
IF es_exp_sin_paréntesis%(0)
REMark JR nn
desplazamiento=valor_exp(0)-dir_org-2
IF vale_desplazamiento%
pokea 24
pokea desplazamiento
ELSE
lista_error -4:REMark fuera de rango
END IF
END IF
=2
IF es_condición%(0)
REMark JR cc,nn
IF es_exp_sin_paréntesis%(1)
valor%=valor_par%(0)
IF valor%<4
desplazamiento=valor_exp(1)-dir_org-2
IF vale_desplazamiento%
pokea 32+8*valor%
pokea desplazamiento
ELSE
lista_error -4:REMark fuera de rango
END IF
END IF
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END SELect
END IF
RETurn 2
END DEFine jr%
:
DEFine FuNction ld%:REMark LD
IF pasada
REMark primera pasada
IF núm_par=3
IF es_exp_sin_paréntesis%(2):RETurn 4:REMark LD (Ir+n),n
RETurn 3:REMark LD r,(Ir+n)/(Ir+n),r
END IF
IF núm_par<>2
lista_error -15:REMark parámetro incorrecto
RETurn 0
END IF
tipo1=tipo_par%(0)&&153
SELect ON tipo1
=8
REMark LD r,?
IF entre_A_y_L%(0)
IF identificador_par%(0)=1
REMark LD A,?
IF es_exp_con_paréntesis%(1):RETurn 3:REMark LD A,(nn)
registro2=identificador_par%(1)
SELect ON registro2
=20,21:RETurn 1:REMark LD A,(BC)/(DE)
=10,12:RETurn 2:REMark LD A,I/R
END SELect
END IF
IF es_exp_sin_paréntesis%(1):RETurn 2:REMark LD r,n
RETurn 1:REMark LD r,r
END IF
RETurn 2:REMark LD I/R,A
=16
REMark LD rr,?
IF es_exp_sin_paréntesis%(1)
REMark LD rr,nn
registro1=identificador_par%(0)
SELect ON registro1=17,18:RETurn 4:REMark LD IX/IY,nn
RETurn 3
END IF
IF es_exp_con_paréntesis%(1)
REMark LD rr,(nn)
IF identificador_par%(0)=15:RETurn 3:REMark LD HL,(nn)
RETurn 4
END IF
REMark LD SP,?
IF identificador_par%(1)=15:RETurn 1:REMark LD SP,HL
REMark LD SP,IX/IY
RETurn 2
=129
REMark LD (nn),?
registro2=identificador_par%(1)
SELect ON registro2=1,15:RETurn 3:REMark LD (nn),A/HL
RETurn 4
=17
REMark LD (rr),?
IF es_exp_sin_paréntesis%(1):RETurn 2:REMark LD (HL),nn
RETurn 1
=REMAINDER
lista_error -15:REMark parámetro incorrecto
RETurn 0
END SELect
END IF
REMark segunda pasada
registro1=identificador_par%(0)
IF núm_par=3
REMark carga con registros índices
IF es_exp_sin_paréntesis%(2)
REMark LD (Ir+n),n
desplazamiento=valor_exp(1)
IF vale_desplazamiento%
byte=valor_exp(2)
IF vale_byte%
SELect ON registro1
=9 :pokea_dd 54:REMark (IX)
=11:pokea_fd 54:REMark (IY)
END SELect
pokea desplazamiento
pokea byte
END IF
ELSE
lista_error -4:REMark fuera de rango
END IF
RETurn 4
ELSE
IF entre_A_y_L%(2)
REMark LD (Ir+n),r
desplazamiento=valor_exp(1)
IF vale_desplazamiento%
SELect ON registro1
=9 :pokea 221:REMark (IX)
=11:pokea 253:REMark (IY)
END SELect
pokea 110+valor_par%(2)
pokea desplazamiento
ELSE
lista_error -4:REMark fuera de rango
END IF
RETurn 3
END IF
IF entre_A_y_L%(0)
REMark LD r,(Ir+n)
desplazamiento=valor_exp(2)
IF vale_desplazamiento%
registro2=identificador_par%(1)
SELect ON registro2
=9 :pokea 221:REMark (IX)
=11:pokea 253:REMark (IY)
END SELect
pokea 70+(valor_par%(0)-2)*8
pokea desplazamiento
ELSE
lista_error -4:REMark fuera de rango
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
RETurn 3
END IF
END IF
tipo1=tipo_par%(0)&&153
SELect ON tipo1
=8
REMark LD r,?
registro2=identificador_par%(1)
IF entre_A_y_L%(0)
IF registro1=1
REMark LD A,?
IF es_exp_con_paréntesis%(1)
REMark LD A,(nn)
pokea 58
pokeaw valor_exp(1)
RETurn 3
END IF
SELect ON registro2
=20:pokea 10:RETurn 1:REMark LD A,(BC)
=21:pokea 26:RETurn 1:REMark LD A,(DE)
=12:pokea_ed 95:RETurn 2:REMark LD A,R
=10:pokea_ed 87:RETurn 2:REMark LD A,I
END SELect
END IF
IF es_exp_sin_paréntesis%(1)
REMark LD r,n
byte=valor_exp(1)
IF vale_byte%
pokea 6+(valor_par%(0)-2)*8
pokea byte
ELSE
lista_error -4:REMark fuera de rango
END IF
RETurn 2
END IF
REMark LD r,?
IF registro2=8
REMark LD r,(HL)
pokea 70+(valor_par%(0)-2)*8
RETurn 1
END IF
IF entre_A_y_L%(1)
REMark LD r,r
pokea 64+(valor_par%(0)-2)*8+valor_par%(1)-2
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
RETurn 1
END IF
REMark ¿ LD I/R,A ?
IF registro2=1
REMark LD ?,A
SELect ON registro1
=10:pokea_ed 71:REMark LD I,A
=12:pokea_ed 79:REMark LD R,A
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
END IF
RETurn 2
=16
REMark LD rr,?
IF es_exp_sin_paréntesis%(1)
REMark LD rr,nn
registro1=identificador_par%(0)
SELect ON registro1
=15:pokea 33 :REMark LD HL,nn
=14:pokea 17 :REMark LD DE,nn
=13:pokea 1 :REMark LD BC,nn
=17
REMark LD IX,nn
pokea_dd 33
pokeaw valor_exp(1)
RETurn 4
=18
REMark LD IY,nn
pokea_fd 33
pokeaw valor_exp(1)
RETurn 4
=16:pokea 49 :REMark LD SP,nn
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
pokeaw valor_exp(1)
RETurn 3
END IF
IF es_exp_con_paréntesis%(1)
REMark LD rr,(nn)
registro1=identificador_par%(0)
SELect ON registro1
=15
REMark LD HL,(nn)
pokea 42
pokeaw valor_exp(1)
RETurn 3
=14:pokea_ed 91 :REMark LD DE,(nn)
=13:pokea_ed 75 :REMark LD BC,(nn)
=17:pokea_dd 42 :REMark LD IX,(nn)
=18:pokea_fd 42 :REMark LD IY,(nn)
=16:pokea_ed 123:REMark LD SP,(nn)
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
pokeaw valor_exp(1)
RETurn 4
END IF
IF registro1=16
REMark LD SP,?
registro2=identificador_par%(1)
SELect ON registro2
=15:pokea 249 :RETurn 1:REMark LD SP,HL
=17:pokea_dd 249:REMark LD SP,IX
=18:pokea_fd 249:REMark LD SP,IY
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
END IF
RETurn 2
=129
REMark LD (nn),?
dirección=valor_exp(0)
registro2=identificador_par%(1)
SELect ON registro2
=1
REMark LD (nn),A
pokea 50
pokeaw dirección
RETurn 3
=15
REMark LD (nn),HL
pokea 34
pokeaw dirección
RETurn 3
=14:pokea_ed 83 :REMark LD (nn),DE
=13:pokea_ed 67 :REMark LD (nn),BC
=17:pokea_dd 34 :REMark LD (nn),IX
=18:pokea_fd 34 :REMark LD (nn),IY
=16:pokea_ed 115:REMark LD (nn),SP
=REMAINDER :lista_error -15:REMark parámetro incorrecto
END SELect
pokeaw dirección
RETurn 4
=17
REMark LD (rr),?
registro1=identificador_par%(0)
SELect ON registro1
=8
REMark LD (HL),?
IF es_exp_sin_paréntesis%(1)
REMark LD (HL),n
byte=valor_exp(1)
IF vale_byte%
pokea 54
pokea byte
ELSE
lista_error -4:REMark parámetro incorrecto
END IF
RETurn 2
END IF
IF entre_A_y_L%(1):pokea 110+valor_par%(1):RETurn 1:REMark LD (HL),r
=21
REMark LD (DE),?
IF identificador_par%(1)=1:pokea 18:RETurn 1:REMark LD (DE),A
=20
REMark LD (BC),?
IF identificador_par%(1)=1:pokea 2:RETurn 1:REMark LD (BC),A
END SELect
END SELect
lista_error -15:REMark parámetro incorrecto
RETurn 0
END DEFine ld%
:
DEFine FuNction out%:REMark OUT
IF pasada
REMark primera pasada
IF núm_par<>2:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
IF es_exp_con_paréntesis%(0)
REMark OUT (n),?
IF identificador_par%(1)=1
REMark OUT (n),A
byte=valor_exp(0)
IF vale_byte%
pokea 211
pokea byte
ELSE
lista_error -4:REMark fuera de rango
END IF
END IF
ELSE
REMark OUT ?
IF NOT(identificador_par%(0))
REMark OUT (C),?
IF entre_A_y_L%(1)
REMark OUT (C),A/B/C/D/E/H/L
pokea_ed 65+8*(valor_par%(1)-2)
END IF
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
END IF
RETurn 2
END DEFine out%
:
DEFine FuNction ret_%:REMark RET
IF pasada
REMark primera pasada
IF núm_par>1:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
SELect ON núm_par
=0:pokea 201:REMark RET
=1
IF es_condición%(0)
REMark RET cc
pokea 192+8*valor_par%(0)
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END SELect
END IF
RETurn 1
END DEFine ret_%
:
DEFine FuNction rst%:REMark RST
IF pasada
REMark primera pasada
IF núm_par<>1:lista_error -15:REMark parámetro incorrecto
ELSE
REMark segunda pasada
IF es_exp_sin_paréntesis%(0)
valor=valor_exp(0)
IF valor>56 OR valor MOD 8:lista_error -4:REMark fuera de rango
pokea 199+valor
ELSE
lista_error -15:REMark parámetro incorrecto
END IF
END IF
RETurn 1
END DEFine rst%
:
REMark Creación del código objeto ----------------------------------
:
DEFine PROCedure pokea_cb(p_byte)
pokea 203:REMark #CB
pokea p_byte
END DEFine
:
DEFine PROCedure pokea_dd(p_byte)
pokea 221:REMark #DD
pokea p_byte
END DEFine pokea_dd
:
DEFine PROCedure pokea_ed(p_byte)
pokea 237:REMark #ED
pokea p_byte
END DEFine pokea_ed
:
DEFine PROCedure pokea_fd(p_byte)
pokea 253:REMark #FD
pokea p_byte
END DEFine pokea_fd
:
DEFine PROCedure pokeaw(p_dir)
h_dir=INT(p_dir/256)
pokea p_dir-h_dir*256
pokea h_dir
END DEFine pokeaw
:
DEFine PROCedure pokea(p_byte)
PRINT#fichero_objeto%,CHR$(p_byte);
bytes_objeto=bytes_objeto+1
IF listar_fuente%
REMark Comprobar ancho del código
IF bytes_listados%<bytes_máx_listados%
código_objeto$=código_objeto$&HEX$(p_byte,8)
bytes_listados%=bytes_listados%+1
END IF
END IF
END DEFine pokea
:
REMark Funciones para comprobar rangos -----------------------------
:
DEFine FuNction vale_desplazamiento%
REMark Entrada
REMark desplazamiento
RETurn desplazamiento>-129 AND desplazamiento<128
END DEFine vale_desplazamiento%
:
DEFine FuNction vale_byte%
REMark Entrada
REMark byte
RETurn byte>65407 OR byte<256
END DEFine vale_byte%
:
DEFine FuNction entre_A_y_HL%(p_núm_par%)
identificador%=identificador_par%(p_núm_par%)
RETurn identificador%>0 AND identificador%<9
END DEFine entre_A_y_HL%
:
DEFine FuNction entre_A_y_L%(p_núm_par%)
identificador%=identificador_par%(p_núm_par%)
RETurn identificador%>0 AND identificador%<8
END DEFine entre_A_y_L%
:
REMark Funciones para comprobar pseudoparámetros -------------------
:
DEFine FuNction es_exp_sin_paréntesis%(p_núm_par%)
RETurn (tipo_par%(p_núm_par%)&&129)=128
END DEFine es_exp_sin_paréntesis%
:
DEFine FuNction es_exp_con_paréntesis%(p_núm_par%)
RETurn (tipo_par%(p_núm_par%)&&129)=129
END DEFine es_exp_con_paréntesis%
:
DEFine FuNction es_tipo%(p_par,p_tipo)
RETurn (tipo_par%(p_par)&&p_tipo)=p_tipo
END DEFine es_tipo%
:
DEFine FuNction es_condición%(p_núm_par%)
RETurn tipo_par%(p_núm_par%)&&2
END DEFine es_condición%
:
REMark Datas -------------------------------------------------------
:
REMark Comandos
REMark identificador,"nombre",parámetros mínimos,parámetros máximos
:
DATA 1,"LD",2,2
DATA 48,"CALL",1,2
DATA 52,"JR",1,2
DATA 65,"DEFM",1,1
DATA 66,"DEFB",1,30
DATA 67,"DEFW",1,30
DATA 50,"JP",1,2
DATA 19,"CP",1,1
DATA 74,"POP",1,1
DATA 73,"PUSH",1,1
DATA 15,"INC",1,1
DATA 51,"RET",0,1
DATA 18,"AND",1,1
DATA 45,"BIT",2,2
DATA 39,"EQU",1,1
DATA 0,"XOR",1,1
DATA 14,"DEC",1,1
DATA 13,"ADD",2,2
DATA 49,"DJNZ",1,1
DATA 3,"EXX",0,0
DATA 2,"EX",2,2
DATA 17,"SUB",1,1
DATA 7,"LDIR",0,0
DATA 44,"SRL",1,1
DATA 46,"RES",2,2
DATA 68,"DEFS",1,1
DATA 55,"RST",1,1
DATA 11,"CPIR",0,0
DATA 26,"HALT",0,0
DATA 27,"IM",1,1
DATA 20,"OR",1,1
DATA 29,"NOP",0,0
DATA 30,"SCF",0,0
DATA 36,"RR",1,1
DATA 64,"ORG",1,1
DATA 53,"RETI",0,0
DATA 47,"SET",2,2
DATA 24,"DI",0,0
DATA 25,"EI",0,0
DATA 4,"LDD",0,0
DATA 5,"LDDR",0,0
DATA 6,"LDI",0,0
DATA 8,"CPD",0,0
DATA 9,"CPDR",0,0
DATA 10,"CPI",0,0
DATA 12,"ADC",2,2
DATA 16,"SBC",2,2
DATA 21,"CCF",0,0
DATA 22,"CPL",0,0
DATA 23,"DAA",0,0
DATA 28,"NEG",0,0
DATA 31,"RL",1,1
DATA 32,"RLA",0,0
DATA 33,"RLC",1,1
DATA 34,"RLCA",0,0
DATA 35,"RLD",0,0
DATA 37,"RRA",0,0
DATA 38,"RRC",1,1
DATA 40,"RRCA",0,0
DATA 41,"RRD",0,0
DATA 42,"SLA",1,1
DATA 43,"SRA",1,1
DATA 54,"RETN",0,0
DATA 56,"IN",2,2
DATA 57,"IND",0,0
DATA 58,"INI",0,0
DATA 59,"INIR",0,0
DATA 60,"INDR",0,0
DATA 61,"OUT",2,2
DATA 62,"OUTD",0,0
DATA 63,"OUTI",0,0
DATA 69,"*L+",0,0
DATA 70,"*L-",0,0
DATA 71,"OTDR",0,0
DATA 72,"OTIR",0,0
DATA 75,"*F",1,1
DATA 76,"IF",1,1
DATA 77,"ELSE",0,0
DATA 78,"ENDIF",0,0
:
REMark Parámetros
REMark identificador,"nombre",tipo,valor
REMark Significado de los bits del identificador
REMark 0 ¿entre paréntesis? (tanto registros como expresiones)
REMark 1 ¿condición?
REMark 2
REMark 3 ¿registro de 8 bits?
REMark 4 ¿registro de 16 bits?
REMark 5
REMark 6
REMark 7 ¿expresión? (para las expresiones numéricas)
:
DATA 1,"A",8,9
DATA 15,"HL",16,2
DATA 24,"NZ",2,0
DATA 3,"C",10,3
DATA 25,"Z",2,1
DATA 13,"BC",16,0
DATA 2,"B",8,2
DATA 14,"DE",16,1
DATA 8,"(HL)",17,8
DATA 17,"IX",16,2
DATA 22,"AF",16,0
DATA 6,"H",8,6
DATA 21,"(DE)",17,1
DATA 5,"E",8,5
DATA 7,"L",8,7
DATA 26,"NC",2,2
DATA 4,"D",8,4
DATA 12,"R",8,0
DATA 19,"(SP)",17,0
DATA 10,"I",8,0
DATA 16,"SP",16,3
DATA 18,"IY",16,2
DATA 9,"(IX)",17,0
DATA 11,"(IY)",17,0
DATA 20,"(BC)",17,0
DATA 23,"AF'",16,0
DATA 0,"(C)",9,0
DATA 27,"PO",2,4
DATA 28,"PE",2,5
DATA 29,"P",2,6
DATA 30,"M",2,7
: