¡Esta es una revisión vieja del documento!
Microhobby 10. Año II, del 8 al 14 de enero de 1985
Software: Z-80: Sistema de interrupciones
Tal vez hayamos leído en alguna revista o libro, o alquien nos ha comentado algo sobre las «interrupciones». Pero, ¿qué es eso?; ¿para qué sirve? y sobre todo ¿cómo se utilizan las interrupciones?
En primer lugar hay que explicar cuál es el concepto de interrupción y para ello nada mejor que un ejemplo:
Supongamos que está sentado frente a su Spectrum programado (o más posiblemente jugando a alguno de los juegos que esta revista publica) y, en ese momento se oye una voz que nos grita desde el pasillo: ¡La cena está lista!
Entonces nosotros atenderemos la «interrupción», es decir, cenaremos, y muy posiblemente, seguiremos luego con nuestra tarea, ¡si no nos «desconectan», claro!
Pues bien, el Z-80 puede atender a tareas que reclaman su atención, ejecutarlas y luego seguir con lo que estaba haciendo antes. Y esto es lo que hace nuestro Spectrum cuando por ejemplo, lee el teclado: cincuenta veces por segundo, el ordenador para lo que esté haciendo, luego lee el teclado y aumenta en uno el conjunto de tres bytes formado por la variable del sistema FRAMES y, después sigue ejecutando el programa interrumpido.
Dos tipos de interrupciones
El Z-80 dispone de dos tipos de interrupciones: una enmascarable y otra no enmascarable. Cada una de estas interrupciones está asociada con una «patita» del Z-80. Una interrupción enmascarable es aquella que se puede desactivar o activar a voluntad del programador y esto se hace con las instrucciones DI y El respectivamente. Es decir, si en medio de un programa se pone la instrucción DI, a partir de ese momento no se atenderán las llamadas producidas por la activación de la «patita» correspondiente. Las interrupciones volverán a atenderse cuando se ejecute la instrucción EL Una interrupción no enmascarable se atenderá siempre que se active. A partir de ahora, sólo tomaremos en cuenta las interrupciones enmascarables, que son las únicas que se pueden utilizar con el Spectrum.
El Z-80 tiene tres modos de ejecutar las interrupciones de las cuales el Spectrum sólo nos permite utilizar dos, estos modos se conmutan entre sí con las instrucciones IM1 y IM2.
El Spectrum está normalmente en el modo 1. En este modo siempre se ejecuta una instrucción de RST 38. Es decir, como cada cincuentavo de segundo se produce una interrupción, esto hace que siempre se ejecute un salto a la rutina en ROM que comienza en la dirección 0038 h., y es esta rutina la que se encarga de leer el teclado y de actualizar FRAMES.
Veamos cómo se utiliza el modo 2. En este caso lo primero que hace el Z-80 es formar una dirección con el registro I y con los datos que, en ese momento, estén presentes en el bus de datos. En el caso del Spectrum este último byte tendrá siempe el valor FFh en ese momento. Luego, el Z-80 irá a esa dirección, formará una nueva dirección con el contenido de esos dos bytes consecutivos y comenzará a ejecutar el programa a partir de dicha dirección. Por ejemplo:
El registro I contiene el valor FEh.
La dirección FEFFh tiene DOh
La dirección FFOOh tiene 4Ah
El Z-80 ejecutaría un salto a la dirección 4ADOh y retornaría al programa interrumpido, cuando se encuentre con la instrucción RETI (Retorno desde Interrupción).
Veamos un ejemplo de utilización del sistema de interrupciones en el Spectrum. El programa permite tener un reloj en la esquina superior derecha y la ventaja de hacerlo usando las interrupciones es que nos permite estar realizando otra tarea mientras el reloj funciona independientemente. De todas formas hay que hacer notar que el reloj se parará con aquellos programas que desactiven las interrupciones, como por ejemplo, las rutinas de LOAD y SAVE, pero el reloj continuará después de terminada estas rutinas. Otra «pega» es que si hacemos NEW debere-
nm
fcwiSiíjf^
I l^lfíl
'..t,»MM».»»tf^Wl…… j
ISH
mos volver a ínicianzar el reloj haciendo RANDOMIZE USR 65517.
Las direcciones que interesan son:
— 65426d …… Aquí se alma-
cenan los segundos.
— 65427d …… Minutos.
— 65428d …… Horas.
Haciendo POKE en estas direcciones
pondremos en hora el reloj. El reloj comenzará a marchar cuando se ejecute el programa almacenado en la dirección 65517 (rutina de activación).
Este es el listado del programa BASIC que carga todo el programa:
DIR. ¡CODIGO ¡LISTADO DIR. ¡CODIGO ¡LISTADO
ORG FEFF 7E LD A, (HL)
FEFF 01 FF DIR-OM DEFW FF01 ¡Dirección de 26 FF LD H,FF Carga H con —1
comienzo FF56 24 R10 INC H ¡Cálculo del dígito en
FFO! F3 COMIENZO DI BCD
F5 PUSH AF ¡Guarda registros D6 0A SUB OA ¡más significativo E5 PUSH HL 30 FB JR NC,R10 D5 PUSH DE C6 0A ADD A, OA C5 PUSH BC 6F LD L,A ¡Almacena el resto 21 91 FF LD HL, TIME ¡Actualizar 1/50'avos en L de 7C LD A,H 34 INC (HL) ¡segundo E5 PUSH HL 3E32 LD A,32 ¡Si no se ha llegado CD 6A FF CALL CHR ¡Imprime el contenido a 50 de H BE CP (HL) ¡ir a la rutina de E1 POP HL impresión 7D LD A,L 20 1B JR NZJMP CD 6A FF CALL CHR ¡Imprime el contenido 36 00 LD (HL),00 ¡Poner 1/50'avos a de L cero E1 POP HL 23 INC HL ¡Sumar un segundo C9 RET 34 INC (HL) FF6A 07 CHR RLCA »Multiplica por 8 el 3E 3C LD A,3C ¡Si no se ha llegado contenido a 60 07 RLCA ¡del acumulador BE CP (HL) ¡saltar a la rutina de 07 RLCA 2012 JR NZJMP ¡impresión 21 95 FF LD HL,CARO ¡Cálculo de la 36 00 LD (HL),00 ¡Poner segundos a dirección cero 16 00 LD D,00 ¡del primer byte del 23 INC HL 5F LD E,A ¡carácter a imprimir y 34 INC (HL) ¡Sumar un minuto almacenar BE CP (HL) ¡Si no se ha llegado 19 ADD HL,DE »en DE a 60 ir E5 PUSH HL 20 OB JR NZJMP ¡a la rutina de D1 POP DE impresión 3A 90 FF LD A,(XPOS) ¡Cálculo de la direc- 36 00 LD (HL),00 ¡poner minutos a ción de cero 6F LD L,A ¡atributos 23 INC HL ¡Sumar una hora 26 58 LD H.58 34 INC (HL) 36 38 LD (HL),38 ¡Poner INK negro y 3E 18 LD A,18 ¡Si no se llegado a PAPER blanco 24 horas 26 40 LD H,40 BE CP (HL) ¡saltar a la impresión 06 08 LD B,8 ¡Colocación de 8 20 02 JR NZJMP bytes consecutivos 36 00 LD (HL),00 ¡Poner horas a cero FF82 1A ET1 LD A,(DE) ¡a partir de DE en la
FF2A 21 94 FF IMP LD HLJIME+3 ¡Cargar HL con la di- 77 LD (HL),A ¡pantalla
rección de las horas 24 INC H 3E 17 LD A,17 ¡Cargar XPOS con la 13 INC DE posión 10 Fa DJNZ ET1 32 90 FF LD (XPOS),A ¡donde se imprimirá 3A 90 FF LD A,(XPOS) ¡Increntar la posición el del ¡primer caracter 3C INCA ¡carácter a imprimir a E5 PUSH HL ¡Llamada a la rutina 32 90 FF LD (XPOS),A ¡continuación en uno de imprimir C9 RET CD 52 FF CALL COS ¡el contenido de HL FF90 00 XPOS DEFB 00 ¡Dirección de pantalla 3EOA LD A,OA ¡Impresión del signo ¡se imprimirá el CD 6A FF próximo CALL CHR ¡carácter E1 POP HL FF91 00 00 00 00 TIME DEFB 00 00 00 00 ¡Variables del tiempo 2B DEC HL ¡Llevar a HL la FF95 7C BA C6 C6 CARO DEFB 7C BA C6 C6 ¡Definición de los dirección C6 C6 BA 7C C6 C6 BA 7C ¡caracteres ¡de los minutos 02 06 06 02 CAR1 DEFB 02 06 06 02 E5 PUSH HL 02 06 06 02 02 06 06 02 CD 52 FF CALL COS ¡Imprimir el contenido 7C 3A 06 7A CAR2 DEFB 7C 3A 06 7A de HL BC CO B8 7C BC CO B8 7C 3EOA LD A,OA ¡Imprimir •':" 7C 3A 06 3A CAR3 DEFB 7C 3A 06 3A CD 6A FF CALL CHR 7A 06 3A 7C 7A 06 3A 7C E1 POP HL 82 C6 C6 BA CAR4 DEFB 82 C6 C6 BA 2B DEC HL »Llevar a HL la direc- 7A 06 06 02 7A 06 06 02 ción de los segundos 7C D8 CO BC CAR5 DEFB 7C D8 CO BC CD 52 FF CALL COS 7A 06 3A 7C 7A 06 3A 7C C1 POP BC »Restaurar el conteni- 7C B8 CO BC CAR6 DEFB 7C B8 CO BC do de los BA C6 BA 7C BA C6 BA 7C D1 POP DE ¡registros 7C 3A 06 06 CAR7 DEFB 7C 3A 06 06 E1 POP HL 02 06 06 02 02 06 06 02 F1 OPO AF 7C BA C6 BA CAR8 DEFB 7C BA C6 BA FF RST38 ¡Rutina ROM de lec- BA C6 BA 7C BA C6 BA 7C tura del 7C BA C6 BA CAR9 DEFB 7C BA C6 BA ¡teclado 7A 06 3A 7C 7A 06 3A 7C ED 4D RETI ¡Retorno desde 00 18 18 00 CARD DEFB 00 18 18 00
FF52 E5 interrupción 00 18 18 00 00 18 18 00
eos PUSH HL ¡Esta rutina primero FFED 3E FE ACTIVA LD A,FE ¡Rutina de Activación para el ED 47 LD l,A ¡Carga I con la ¡número binario con- dirección tenido en ¡de la interrupción ¡HL a un número en ED 5E IM 2 ¡Modo de interrup- BCD, también ción 2 ¡contenido en HL C9 RET