¡Esta es una revisión vieja del documento!
Microhobby 12. Año II, del 22 al 28 de enero de 1985
Utilidades: Carga y almacenamiento de programas con velocidad variable (II)
— Paco Martín y José María Diaz
Esperamos que el artículo anterior haya cumplido la misión de aclarar al lector el método empleado para analizar la sintaxis de los nuevos comandos que se nos ocurra incluir en el Basic del Spectrum.
Partiendo de esta premisa, presentamos en este número la rutina de sintaxis completa, es decir, con unas modificaciones necesarias para mayor comodidad de uso, pero que de incluirlas en la anterior exposición, pensamos que hubieran dificultado en extremo la comprensión de la lógica del programa.
Asimismo, hemos incluido también parte de la rutina de velocidad variable para que se pueda ir examinando con el detalle y la tranquilidad que requiere, dada la cierta complejidad de este proceso, en el que se mezclan, siguiendo una lógica precisa, partes de la rutina ROM del ordenador modificadas de acuerdo a nuestros propósitos, con trozos de código que ha sido necesario «fabricar», bastante repletos de trucos y artimañas de programación, que esperamos sean útiles a los programadores ávidos de lenguaje máquina.
Hemos tratado de explicar, con la mayor precisión y brevedad posibles, lo que está sucediendo en el microprocesador mientras ejecuta, paso a paso la rutina, esperando, no obstante, que el lector consiga una visión de conjunto, a vista de pájaro, del procedimiento como un todo.
Antes de terminar, dos aclaraciones:
- para mayor comodidad de uso, después del “REM” deben colocarse dos puntos; así obtendremos fácilmente los “TOKENS” de SAVE, LOAD, VERIFY o MERGE.
- La rutina está pensada para que a velocidad normal (1.500 baudios) sea plenamente compatible con el sistema operativo del ordenador; sin embargo, quisiéramos matizar de nuevo que a altas velocidades de transferencia de información, la precisión con la que este proceso ocurre, depende de las características físicas del aparato de cassette utilizado.
Listado ensamblador
ORG 60000 LD HL,(23645) TOMA LA DIRECCION CH-ADD PARA SINTAXIS INICIAL. INC HL LD A,(HL) CP 234 ;'REM' COMPRUEBA LA PRESENCIA DE "REM" JR NZ,ERRORA Y ":" INC HL LD A,(HL) SI NO EXISTEN. SALTA A ERROR CP ":" JR NZ,ERRORA INC HL LD A,(HL) EXAMINA LOS SIGUIENTES CP 248;'SAVE' CARACTERES DE LA LINEA DE JR Z,TSAVE COMANDO PARA BIFURCARA CP 239;'LOAD' LA SUBRUTINA CORRESPONDIENTE. JP Z,TLOAD CP 214;'VERIFY' JP Z,TVERIF CP 213;'MERGE' JR Z,TMERGE JR ERRORA SI NINGUNO EXISTE SALTA A ERROR. ERROR6 RST 8 LLAMADAS A LA SUBRUTINA ROM DE MENSAJES DE ERROR DEFB 5; 'NUMBER'TOO BIG' ERRORA RST 8 DEFB 9; 'INVALID ARGUMENT ERRORB RST 8 DEFB 10; 'INTEGER OUT OF RANGE' ERRORC RST 8 DEFB 11; NONSENSE IN BASIC' ERRORF RST 8 DEFB 14; INVALID ARGUMENT' ERRORR RST 8 DEFB 26; 'TAPE LOADING ERROR' TSAVE CALL BAUDIO TOMA EL NUMERO INDICADOR DELA VELOCIDAD DE GRABA- CALL NAME CION. NOMBRE Y SI SU LONGITUD ES JR C,ERRORF CERO O MAYOR QUE 10. SALTA A ERROR. CALL SINTAX COGE EL RESTO DE LOS DATOS. PUSH AF PRESERVA EL INDICADOR DE "TIPO". LD A,#FD ABRE CANAL 0 CALL #1601 XOR A LD DE,#9A1 MENSAJE "START TAPE..." CALL #C0A SET 5,(IY+2) FLAG PARA BORRAR MENSAJE. CALL #15D4 ESPERAR PULSACION TECLA. LD IX,CABEC PUNTERO PARA EL BUFFER DE CABECERA. LD DE,17 LONGITUD DEL BUFFER. XOR A INDICA "ES UNA CABECERA", CALL SAVE SALVA LA CABECERA. LD B,#32 HALT SE PRODUCE UN RETARDO ANTES DE SALVAR EL SEGUNDO DJNZ PSAV BLOQUE. POP AF RECUPERA "TIPO" LD DE,(LONT) LONGITUD DEL BLOQUE A SALVAR. LD A,#FF SEÑAL "BLOQUE DE DATOS". LD IX,(23635) SI ES UN PROGRAMA. TOMA DIR. DE COMIENZO. JR C FSAV LD IX,(DIRT) SI NO. LA DIRECCION ESPECIFICADA EN EL COMANDO. FSAV CALL SAVE RET TMERGE CALL BAUDIO CALL NAME CALL C,CPNAME COMPRUEBA QUE EL FINAL ES'"' INC HL LD A,(HL) AL FINAL DEBE HABER UN "ENTER". CP 13 JR NZ,ERRORC CALL RELOAD CARGA LA CABECERA. LD BC,(LONBUF) LONGITUD TOTAL DEL PROGRAMA PUSH BC INC BC RST 48 CREA EN EL AREA DE TRABAJO "BC+1" ESPACIOS. LD (HL),#80 PONE UN INDICADOR DE FIN EN LA LOCALIZACION EXTRA. EX DE,HL POP DE PUSH HL PUSH HL POP IX LD A,#FF CALL LMBYT CARGA EL BLOQUE DEL PROGRAMA. JP 2253 EFECTUA LA OPERACION DE "MERGE". TVERIF CALL LDPREV INICIALIZA VALORES. RES 0,(IY+37) SEÑAL "VERIFICANDO". JR NC,LDBYTE SALTA SI NO ES UN PROGRAMA BASIC. JR CPROG VERIFICA EL PROGRAMA BASIC. LDPREV CALL BAUDIO TOMA LOS VALORES DEL COMANDO. CALL NAME COMPRUEBA SINTAXIS Y CARGA LA CABECERA. CALL C,CPNAME CALL NSINT PUSH AF PRESERVA EL INDICADOR DE TIPO. CALL RELOAD POP AF LO RECUPERA. RET TLOAD CALL LDPREV SET (j.|IY+37) SEÑAL "CARGA EL BLOQUE". JR NC.LDBYTE SALTA SI NO ES UN PROGRAMA BASIC. LD DE.(LONBUF| TOMA LONGITUD TOTAL DEL BLOQUE A CARGAR. LD HL.I23635) ADD HL.DE MIRA SI EL PROGRAMA A CARGAR ES MENOR QUE EL PRO- EX DE.HL GRAMA RESIDENTE. LD HL.I23641) SCF SBC HL.DE JR C.ADDS SIES MAYOR O IGUAL. SALTA JR Z.ADDS PARA CREAR ESPACIO. LD B.H RECLAMA LOS BYTES SOBRANTES. LD C.L EX DE.HL CALL «19E8 JR PPL ADDS ADD HL.DE CREA ESPACIO SUFICIENTE EN MEMORIA PARA EL NUEVO EX DE.HL PROGRAMA. AND A SBC HL.DE LD ' B.H LD C,L EX DE.HL CALL »1655 PPL LD HL.(23635) ASIGNA LA DIRECCION CORRECTA DE LAS VARIABLES DE LD BC.(INFBUF) PROGRAMA. ADD HL.BC LD (23627),HL LD HL(DIBUF) MIRA SI EL PROGRAMA BASIC SE AUTOEJECUTA Y EN QUE U- LD A.H NEA. AND *C0 JR NZ.CPROG LD (23618I.HL SI ES ASI. HACE UNA COPIA. LD |IY+101.0 SEÑALA PRIMERA INSTRUCCION DE LA LINEA. CPROG LD DE.ILONBUF) LD IX.(23635) CARGA LD A.«FF BIT 0 .(IY+37Í EXAMINA "LOAD O VERIFY JR Z.VBYT LMBYT SCF VBYT CALL LOAD RET C JP ERRORR LDBYTE AND A SE EFECTUA UN CHEQUEO DEL REGISTRO "A" PARA DETER- JR NZ.INDEF MINAR EL TIPO DE CARGA LD IX.16384 A=0 INDICA "LOAD SCREENS". LD DE.(LONT) A=1 INDICA "LOAD CODE". LD HL(LONBUF) A=2 INDICA "LOAD CODE XXXX". AND A A=3 INDICA "LOAD CODE XXXX. XXXX". SBC HL.DE JP JR CARGA INDEF CP 2 JR NC(DIDEF) LD IX.(DIBUF) DEFLO LD DE.(LONBUF) JR CARGA DIDEF LD IX.IDIRT) JR NZ.TODEF JR DEFLO TODEF LD DE,(LONT) JR CARGA RELOAD LD IX.BUFCAB DIRECCION DE CARGA DE LA CABECERA. LD DE.17 XOR A SCF CALL LOAD JR NC.RELOAD SI ERROR. INSISTE. RES (j.|IY+82) ABRE CANAL SUPERIOR DE PANTALLA. LD 82 PREVEE SCROLL DE TRES LINEAS. LD HL.CABEC DIRECCION PUNTERO CABECERA ESPECIFICADA. LD C.128 SEÑAL "DIFERENTE TIPO". LD A.(BUFCAB) CP (HL) COMPARA AMBAS CABECERAS. JR NZ.LDTIP SALTA SI NO SON IGUALES. LD C.246 SEÑAL "id CARACTERES IGUALES". LDTIP CP 4 SI EL TIPO DE BLOQUE ES MAYOR JR NC.RELOAD QUE 3.CARGA NUEVA CABECERA LD DE. »900 PUSH BC IMPRIME EL MENSAJE ASOCIADO A CADA TIPO DE BLOQUE CALL «C0A Y EL NOMBRE DEL BLOQUE ENTRANTE. POP BC LD DE.BUFNAM LD HL.NOMBRE LD B.10 LD A,(HL) INC A JR NZ.LDNAME LD A.C ADD A.B LD C.A LDNAME LD A.(DE) CP (HL) INC HL INC DE JR NZ.LDPR INC C LDPR RST 16 DJNZ LDNAME BIT 7,C EXAMINA SI EL TIPO Y EL NOMBRE JR NZ.RELOAD ENTRANTES COINCIDEN. LD A.13 RST 16 RET _