— Paco Martín y José María Diaz
Con este artículo, se completa la trilogía que hemos dedicado a un tema especialmente interesante en código máquina: la posibilidad de elegir la velocidad de transferencia cassette-ordenador, o lo que es lo mismo, cómo conseguir programar más deprisa o más despacio que el estándar permitido. Con ello, esperamos haber satisfecho a nuestros lectores y haber dejado claro un tema tan complejo y atractivo como el expuesto.
FE DE ERRATAS (Publicado en el #015)
En las siete primeras líneas del programa cargador que ofrecimos en el n.° 13, pág. 31 existen unos pequeños errores que a continuación corregimos:
1 RESTORE :CLEAR 59999: LET CHECK = 0: PRINT "CHEQUEO: " 2 FOR I = 1 TO 1206: READ A: POKE 59999 + I, A: LET CHECK = CHECK + A: NEXT I 3 PRINT CHECK; " "; ("IN" AND CHECK <> 154510); "CORRECTO"
BAUDIO CALI NUMERO OBTIENE EL NUMERO DE LA LINEA DE COMANDO. PUSH HL CP r JP NZ ERRORC LD HL.799 EL RANGO DEBE ESTAR COMPRENDIDO ENTRE 80 0 Y 5 0 0 0 . SBC HL.DE JP NC.ERRORB AND A LD HL.50 0 0 SBC HL.DE JP C.ERR0R6 LD DE.(PRES) TOMA EL NUMERO DIVIDIDO POR 10. LD (BAUD|,DE PARA ASIGNAR LA VELOCIDAD CALL INVAL EINICIALIZA VALORES. POP HL INC HL LD A,(HL) CP ..... JP NZ.ERRORA INC HL RET ÑAME LD B,10 SEÑAL "10 CARACTERES PARA EL NOMBRE". LD DE.NOMBRE DIRECCION DEL BUFFER DEL "NOMBRE". PNAME LD A,(HL) CP """ JR ZCMP LD |DE),A EL "NOMBRE" DEL BLOQUE QUEDA ALMACENADO. INC HL INC DE DJNZ PNAME LD A.(HL) CP "" RET Z SCF SEÑAL "NOMBRE DEMASIADO LARGO". RET CMP LD A,9 MIRA SI EXISTE UN "NOMBRE". CP B LD A,32 SE COMPLETAN CON ESPACIOS LOS 10 CARACTERES. LLENA LD (DE|.A INC DE DJNZ LLENA RET CPNAME LD A,(HL) COMPRUEBA QUE "NOMBRE" FINALIZA CP CON COMILLAS. JP NZ.ERR0RF LD A,#FF SEÑAL "NOMBRE NO ESPECIFICADO". LD (N0MBRE).A SINTAX INC HL ANALIZA QUE LA SINTAXIS ES CORRECTA V BIFURCA A LA SUBRUTINA CORRESPONDIENTE. LD A.(HL) CP 13 JR Z.PPR0G CP 20 2: UNE' JR Z.PR0GL CP 170 ; SCREENS' JR Z.SPANT CP 175:'CODE' JR Z.C0DE JP ERRORC PPROG LD HL.*80 0 0 SEÑAL "NO AUTOEJECUCION" LD (DIRTI.HL TIPO XOR A ASIGNACION DE VALORES PARA LA CABECERA. LD (CABEQ.A LD DE,(23635) LD HL,(23627) SBC HL,DE LD (INFCfcHL LD HL,(23641) SCF SBC HL.0E LD (L0NT),HL SCF RET PROGL CALL ENUM TOMA EL VALOR NUMERICO SIGUIENTE AL TOKEN UNE; SI ES MAYOR DE 9999, ERRORB LD HL.9999 SBC HL,DE JP C.ERRORB LD (DIRT),DE CALL TIPO RET SPANT INC HL MIRA QUE EL SIGUIENT CARACTER SEA ENTER' LD A.(HL) CP 13 JP NZ,ERRORC LD HL,16384 ASIGNA LOS VALORES NECESARIOS Y RETORNA LD (DIRT),HL LD HL.6912 LD (LONTLHL INSA LD HL,«8000 LD (INFC),HL LD A,3 LD (CABEQA RET CODE CALL NUMERO TOMA LOS DATOS DE DIRECCION Y UDNGITUD A LA VEZ QUE CHEQUEA SINTAXIS LO (DIRT),DE CALL COMDAT DEFLON LD A,(HL| CP : JP NZ.ERRORC CALL ENUM LO ¡LONT).DE CALL COMDAT JR INSA COMOAT LD A,O CHEQUEA QUE SI EL NUMERO ES CERO, EXISTIA AL MENOS UN ASCII f OR E RET NZ DEC HL LD AiHLl CP i" JP NZ.ERRORC INC HL RET ENUM CALL NUMERO TOMA EL ULTIMO NUMERO ESPECIFICADO CP 13 Y ANALIZA QUE EL SIGUIENTE SEA JP NZ.ERRORC ENTER': SI NO. ERRORC RET NSINT XOR A CONTINUA ANALIZANDO LA SINTAXIS DE VERIFY Y LOAD. Bl- FURCANDO A LA SUBRUTINA ADECUADA LD ¡CABECIL INC HL LD A,(HL) CP 13 SCF SEÑAL "PROGRAMA BASIC" RET Z LD A,3 SEÑAL "BYTES" LD (CABEC).A LD A,|HL) CP 170 : "SCREENS' JR Z.LPANT CP 175:'CODE' JR Z.LCODE JP ERRORC ím CALL SPANT ASIGNA VALORES PARA "LOAD"-"VERIFY" DE PANTALLA XOR A RET LCOOE INC HL ANALIZA SI SE HA ESPECIFICADO LA DIRECCION LD A,(HL) CP 13 LD A.1 SEÑAL "DIRECCION NO ESPECIFICADA" RET Z DEC HL CALL NUMERO TOMA EL VALOR DE LA DIRECCION LD (DIRT).DE CALL COMDAT LD A.(HL) CP 13 LD A,2 SEÑAL "DIRECCION ESPECIFICADA" RET Z JR DEFLON NUMERO LD DE.0 INICIALIZA EL VALOR A CERO CRNUM INC HL APUNTA AL SIGUIENTE CARACTER LD A,(HL) TOMA EL DATO CP 58 ¿ES MAYOR QUE "9"? RET NC RETORNA SI ES ASI CP 48 ¿ES MENOR QUE'f'? RET C RETORNA SI ES ASI SUB 48 AJUSTA EL VALOR ASCII A DECIMAL PUSH HL PRESERVA EL PUNTERO LD (PRES).DE ALMACENA EL NUMERO CALCULADO EX DE.HL INTERCAMBIA VALORES CALL MULT OPERACION HUHL'ltf LO D4 LD E,A ADD HL.DE ASIGNA EL NUEVO VALOR. QUE NO DEBE SER MAYOR QUE 65535 JP C.ERRORB EX DE.HL POP HL JR CRNUM PRES DEFW 0 MULT ADD HL.HL HUNUMERO'2 JP C.ERRORB LD D.H COPIA HL EN DE LD E.L ADD HL.HL HUNUMERO'4 JP C.ERRORB ADD HL.HL HL=NUMER0'8 JP CERRORB ADD HL.DE HL=NUMERO+NUMERO'2 JP CERRORB RET ¡NVAL LD DE.DATSAV TOMA LA DIRECCION DEL DATA PARA AJUSTAR VALORES EN LA OPERACION SAVE EFECTUANDO EL CALCULO A CONTINUACION CALL CALCUL LD HL.8UFFER LD A.|HL] EL REGISTRO HL SE UTILIZA COMO PUNTERO DE LOS DATOS OBTENIDOS. INSERTA LOS VALORES ADECUADOS EN LAS POSICIONES CO RRESPONDIENTES PARA LA OPERACION "SAVE" LD (DS1+2).A INC HL LD A.(HL) LD |DS2+1).A INC HL LD (DS3+D.A INC HL LD A,(HL) LD (DS4+1),A LD DE.DATLOA EFECTUA LA MISMA OPERACION PARA CALL CALCUL "LOAD". "VERIFY", "MERGE" LD HL,BUFFER LD A.(HL) NEG LD (DL1+1|.A INC HL LD A.(HL) NEG LD (DL2+1).A INC HL LD A,(HL) NEG LD (DL3+1).A INC HL LD A,(HL) NEG LD (DL4+1),A RET ESTA SUBRUTINA EFECTUA EL CALCULO (DDAT)' 150/(BAUD) CALCUL LD B.4 SE VAN A CALCULAR 4 VALORES LD HL.BUFFER SE INICIALIZA EL PUNTERO DE LD (DDAT),HL DIRECCION DONDE SE VA A COLOCAR EL RESULTADO DEL NCALC PUSH 8C CALCULO LD A,(DE) TOMA EL PRIMER VALOR A CALCULAR PUSH DE LD HL150 LD D.0 LD E,A CALL «30 A9 OPERACION HUHL'DE LD B,H LD C,L PUSH BC LD BC.IBAUD) TOMA EL VALOR DE LOS BAUDIOS V LO ALMACENA EN EL STACK CALL «2D2B POP BC PUSH HL CALL #2D2B POP DE CALL #31AF SE DIVIDEN AMBOS VALORES CALL #2DA2 RECUPERA EN A EL RESULTADO LD HL.(DDAT) EL RESULTADO QUEDA ALMACENADO LD (HL),A INC HL EL PUNTERO SE INCREMENTA LD (DDAT).HL POP DE INC DE POP BC DJNZ NCALC RET DDAT DEFW | BUFFER DEFB 0 ,0.0.0 BAUD DEFW 150 DATSAV DEFB 59,66.62,49 DATLOA DEFB 80,78,53.80 CABEC DEFB 0 NOMBRE DEFB 127 DEFM "M. H08BY" LONT DEFW 0 DIRT DEFW 0 INFC DEFW 0 BUFCAB DEFB 0 BUFNAM DEFS 10 LONBUF DEFW 0 DIBUF DEFW 0 INFBUF 0EFW ^ SE EFECTUA LA MISMA OPERACION QUE EN LA ROM. SALVO QUE COLOCAMOS NUESTROS PROPIOS VALORES CALCULADOS ANTERIORMENTE EN LOS LUGARES SEÑALADOS CON UNA" " ; LOAD LOAD INC D EX AF.AF' DEC D DI LD A.#0 F OUT («FE).A LD HL,«0 53F PUSH HL IN A,|»FE) RRA AND #20 OT "0 2 LD C,A CP A LBREAK RET NZ LSTART CALL «0 5E7 JR NC,LBREAK LD HL,#0415 LDWAIT DJNZ LDWAIT DEC HL LD A.H OR L JR NZ,LDWAIT CALL #05E3 JR NC,LBREAK LEADER LD B.#9C CALL «05E3 JR NC,LBREAK LD A,#C6 CP B JR NC,LSTART INC H JR NZ,LEADER LDSYNC LD B,#C9 CALL «05E7 JR NC.LBREAK LD A.B CP #D4 JR NC.LDSYNC CALL #05E7 RET NC LD A.C XOR #0 3 LD C,A LD H.«0 0 DL1 LD B.*B0 ; JR MARKER LDLOOP EX AF,AF JR NZ.LDFLAG JR NC.VERIFY LD (IX+0 ),L JR LDNEXT LDFLAG RL C XOR L RET NZ LD A.C RRA LD C.A INC DE JR LDDEC VERIFY LD A.(IX+0) XOR L RET NZ LDNEXT INC IX LDDEC DEC DE EX AF.AF DL2 LD B,"B2: MARKER LD L,#0 1 LDBITS CALL «0 5E3 RET NC DL3 LD A.#CB: CP B RL L DL4 LD B.#B0 ; JP NC.LDBITS LD A.H XOR L LD H.A LD A.D OR E JR NZ,LDLOOP LD A.H CP 1 RET DE LA MISMA MANERA QUE EN "LORD". INTRODUCIMOS ¡ NUESTROS PROPIOS VALORES ; SAVE SAVE LD HL.«0 53F PUSH HL LD HL.#1F80 BIT 7,A JR Z.SAFLAG LD HL,#0 C98 SAFLAG EX AF.AF" INC DE DEC IX DI LD A,#0 2 LD B,A SLEAD DJNZ SLEAD OUT (#FE).A XOR #0 F LD B.#A4 DEC L JR NZ.SLEAD DEC B DEC H JP P.SLEAD LD B.#2F SSINC1 DJNZ SSINC1 OUT (#FE),A LD M0 D LD B.#37 SSINC2 DJNZ SSINC2 OUT («FE),A DS1 LD BG,«3B0 E; EX AF.AF' LD LA JP SSTART SALOOP LD A.D OR E JR Z.SPARYT LD LJX+tf) LPARYT LD A.H XOR L SSTART LD H,A LD A,*(J 1 SCF JP SABITS SPARYT LD L,H JR LPARYT SABIT2 LD A,C BIT 7.B SABIT1 DJNZ SABIT1 JR NC.SAOUT DS2 LD B.#42 ; SASET DJNZ SASET SAOUT OUT ("FE),A DS3 LD B.#3E; JR NZ.SABIT2 DEC B XOR A INC A SABITS RL L JP NZ.SABIT1 DEC DE INC IX DS4 LD B. #31; LD A.#7F IN A,(«FE) RRA RET NC LD A.D INC A JP NZ.SALOOP LD B,#3B SDELAY DJNZ SDELAY RET