Interrupciones

Una “interrupción” consiste en dejar de ejecutar el programa que está en curso para pasar a ejecutar una “rutina de interrupción”. Tras ejecutarse la rutina de interrupción continúa la ejecución del programa original allí donde se interrumpió.

Las rutinas de interrupción típicamente son rutinas del sistema (por ejemplo, para hacer que parpadee el cursor de BASIC, o para leer el teclado, etc.), pero como veremos más adelante el usuario puede modificarlas o incluso sustituirlas por otras propias.

Para que ocurra una interrupción, es necesario que se active una señal sobre uno de los dos “pines” (patillas) del microprocesador 6510 que tienen que ver con las interrupciones:

  • El pin IRQ.
  • El pin NMI.

Algunos chips del C64 (ej. CIAs) generan interrupciones de forma periódica, y otros (ej. VIC) cuando ocurre algún evento de interés para el programador.

Interrupciones IRQ por hardware

IRQ significa “interrupt request” (petición de interrupción). Cuando se activa este pin, si el flag I – interrupt del registro de estado está desactivado (instrucción “cli”), deja de ejecutarse el programa actual, se ponen a salvo los registros en la pila, y se ejecuta la rutina de interrupción.

Si, por el contrario, el flag I – interrupt estuviera activado (instrucción “sei”), la interrupción IRQ no sería atendida. Por ello a las interrupciones de tipo IRQ también se les llama “enmascarables”.

Interrupciones IRQ por software

Igual que es posible generar interrupciones IRQ por hardware, también es posible hacerlo por software. Para ello, hay que ejecutar la instrucción “brk”.

Cuando se ejecuta la instrucción “brk” ocurre básicamente lo mismo que cuando se activa el pin IRQ, con las diferencias de que se activa el flag B – break en el registro de estado, y que las interrupciones “brk” no son enmascarables mediante el flag I – interrupt.

La instrucción “brk” utiliza el modo de direccionamiento implícito, y sólo afecta al flag B – break. Sus detalles se pueden consultar en http://www.6502.org/tutorials/6502opcodes.html#BRK.

Rutina de interrupción IRQ

Más en detalle, al ejecutarse una interrupción IRQ hardware o software ocurre lo siguiente:

  • El contador de programa se guarda en la pila. Primero el MSB y luego el LSB.
  • El registro de estado se guarda en la pila.
  • Se ejecuta el programa apuntado por las posiciones $fffe y $ffff.

Las posiciones $fffe y $ffff conforman el “vector de interrupción”. Estas posiciones están en ROM, y contienen los valores $48 y $ff respectivamente. Es decir, apuntan a la dirección $ff48, que también está en ROM.

El programa que empieza en $ff48 se llama “rutina de interrupción”, y resumidamente hace esto:

  • Guarda el acumulador en la pila.
  • Guarda el registro X en la pila.
  • Guarda el registro Y en la pila.
  • Analiza si la interrupción IRQ es hardware o software mediante el flag B – break.
  • En el caso software salta a la dirección apuntada por $0316 y $0317.
  • En el caso hardware salta a la dirección apuntada por $0314 y $0315.

Por defecto, las posiciones $0316 y $0317 apuntan a $fe66, y las posiciones $0314 y $0315 apuntan a $ea31. Pero las posiciones $03xx están en RAM y, por tanto, su contenido se puede modificar, modificando así el algoritmo de la rutina de interrupción o incluso sustituyéndolo por otro completamente nuevo.

Esta modificación hay que hacerla con cuidado, porque podrían tener lugar interrupciones en mitad de la modificación. Por ello, suele hacerse dentro de un trozo de código que empieza por “sei” (para inhabilitar temporalmente las interrupciones) y termina con “cli” (para volver a habilitarlas ya con la nueva rutina de interrupción).

De hecho, muchas veces en vez de llamar “vector de interrupción” a $fffe – $ffff, se suele llamar “vector de interrupción” a $0314 – $0315, y en vez de llamar “rutina de interrupción” al programa del sistema esbozado arriba (el que empieza en $ff48), se suele llama “rutina de interrupción” al programa de usuario apuntado por $0314 – $0315. Esto se hace así porque, en el fondo, lo que interesa al usuario son las posiciones $0314 – $0315 y el programa apuntado por este vector. Lo demás es código del sistema que no se puede modificar.

Instrucción “rti”

La rutina de interrupción, ya sea la rutina de interrupción del C64, o una propia del usuario, tiene que terminar con la instrucción “rti”.

Cuando se ejecuta esta instrucción ocurre lo siguiente:

  • Se recupera desde la pila el registro de estado.
  • Se recupera desde la pila el contador de programa. Primero el LSB y luego el MSB.
  • Continúa la ejecución en ese contador de programa, es decir, donde tuvo lugar la interrupción.

La instrucción “rti” usa el modo de direccionamiento implícito, y afecta a todos los flags porque recupera el registro de estado desde la pila. Sus detalles pueden consultarse en http://www.6502.org/tutorials/6502opcodes.html#RTI.

Adicionalmente, antes de la instrucción “rti” lo correcto sería recuperar los registros Y, X y acumulador desde la pila, dado que sólo así podrá continuar la ejecución en exactamente las mismas condiciones que cuando se produjo la interrupción.

Lo anterior es cierto si la “rutina de interrupción de usuario” es una rutina de interrupción completa, que sustituye a la del sistema. Sin embargo, en ocasiones se ven rutinas parciales que ejecutan un “trozo de código” adicional antes que la rutina habitual del C64, y que terminan con un “jmp $ea31” (es decir, con el resto de la rutina habitual del sistema). En este caso se puede confiar en que la recuperación de registros y el “rti” serán ejecutados por la rutina habitual del sistema.

Todo esto quedará más claro con los ejemplos…

Interrupciones NMI

NMI significa “non-maskable interrupts”, es decir, interrupciones no enmascarables. Son interrupciones hardware igual que las IRQ, pero con algunas diferencias:

  • Se activan con el pin NMI, no con el pin IRQ.
  • No son enmascarables, es decir, no les afecta el flag I – interrupt.
  • El vector de interrupción es $fffa – $fffb, no $fffe – $ffff.

Programas de ejemplo: Prog25 y Prog26

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s