cursos:ensamblador:interrupciones

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cursos:ensamblador:interrupciones [21-01-2024 11:05] – [Paginación 128KB y ubicación de nuestra ISR] sromerocursos:ensamblador:interrupciones [21-01-2024 11:23] (actual) – [Instrucción HALT] sromero
Línea 105: Línea 105:
 ==== Instrucción HALT ==== ==== Instrucción HALT ====
  
- La instrucción ''HALT'' es una instrucción muy útil que detiene el proceso de ejecución de la CPU. Al llamarla, la CPU comienza a ejecutar continuamente instrucciones ''NOP'' de 4 t-estados (sin incrementar el contador de programa), hasta que se vea interrumpido por una NMI o una MI (INT), en cuyo momento se incrementa PC y se procesa la interrupción. Al volver de la ISR, el procesador continúa la ejecución del programa en la instrucción siguiente al ''HALT''.+ La instrucción ''HALT'' es una instrucción muy útil que detiene el proceso de ejecución de la CPU. Al llamarla, la CPU realiza de forma continuada el mismo procedimiento que cuando se ejecutan instrucciones ''NOP'' de 4 t-estados (pero sin incrementar el contador de programa, e incrementando el registro **R**), hasta que se vea interrumpido por una NMI o una MI (INT), en cuyo momento se incrementa PC y se procesa la interrupción. Al volver de la ISR, el procesador continúa la ejecución del programa en la instrucción siguiente al ''HALT''.
  
 <code z80> <code z80>
Línea 111: Línea 111:
 </code> </code>
  
- Como veremos más adelante, la instrucción ''HALT'' nos será especialmente útil en determinadas ocasiones al trabajar con la manipulación del área de datos de la videomemoria.+ Básicamente, la ejecución de nuestro programa se detiene en el ''HALT'' hasta que ocurra una interrupción.
  
- Como veremos con detalle a continuación, la ULA genera una interrupción 50 veces por segundo (cada vez que se sincroniza con el haz de electrones de la pantalla para su redibujado, en la parte superior izquierda de la pantalla, antes de empezar a dibujar el actual BORDER). Al colocar un ''HALT'' en nuestro programa, la ejecución del mismo se detendrá en ese punto y dejaremos en espera nuestro programa hasta que se produzca dicha interrupción. Es una manera de limitar la velocidad del programa y de sincronizarse con el haz de electrones para hacer efecto concretos con temporizaciones controladas.+ Como veremos con detalle a continuación, la ULA genera una interrupción 50 veces por segundo (cada vez que se sincroniza con el haz de electrones de la pantalla para su redibujado, en la parte superior izquierda de la pantalla, antes de empezar a dibujar el actual BORDER). Al colocar un ''HALT'' en nuestro programa, la ejecución del mismo se detendrá en ese punto y lo dejaremos en espera hasta que se produzca el siguiente retrazo vertical y la ULA genere la interrupción correspondiente. Es una manera de limitar la velocidad del programa y de sincronizarse con el haz de electrones para hacer efectos concretos con temporizaciones controladas
 + 
 + Como veremos más adelante, la instrucción ''HALT'' nos será especialmente útil en determinadas ocasiones al trabajar con la manipulación del área de datos de la videomemoria.
  
 \\ \\
Línea 1117: Línea 1119:
     ret     ret
 </code> </code>
 +
 +
 +\\
 +===== Utilizar un JP como ISR =====
 +
 + En muchos juegos comerciales y homebrew, la rutina de ISR no es una rutina en sí misma sino un ''jp'' a la rutina real, de modo que podamos tenerla junto al resto de nuestro código, y no en una ubicación específica de memoria:
 +
 +
 +<code z80>
 +; Rutina de ISR ubicada junto a nuestro programa, y no en dirección tipo $XYXY
 +    ORG 40000
 +
 +    ; Generamos una tabla de 257 valores "$a2" desde $a000 a $a101
 +    ld hl, $a000
 +    ld a, $a2                     ; A = $a2
 +    ld (hl), a                    ; Cargamos $a2 en $fe00
 +    ld de, $fe01                  ; Apuntamos DE a $fe01
 +    ld bc, 256                    ; Realizamos 256 ldi para copiar $a2
 +    ldir                          ; en toda la tabla de vectores de int.
 +
 +    ; Activamos im2 con nuestra ISR
 +    di
 +    ld a, $fe                     ; Definimos la tabla a partir de $fe00.
 +    ld i, a
 +    im 2                          ; Saltamos a im2
 +    ei
 +
 +    ; Nuestro programa
 +    ; (...)
 +
 +Rutina_ISR:
 +    ; La rutina ISR
 +    (...)
 +    ei
 +    reti
 +
 +    ; Guardamos en una variable de preprocesador la posicion
 +    ; de este punto en el proceso de ensamblado ($)
 +    PUNTO_ENSAMBLADO EQU $
 +
 +    ;-------------------------------------------------------------
 +    ; Nuestra rutina de ISR ensamblada en $A2A2: JP a rutina real
 +    ;-------------------------------------------------------------
 +    ORG $A2A2
 +
 +PUNTO_ENTRADA_ISR:
 +    jp Rutina_ISR
 +</code>
 +
 +De esta forma, la tabla de vectores de interrupción y la rutina ISR (un simple ''jp'' a la rutina real) están prácticamente juntas en memoria y sabemos que acaba 3 bytes después de **$a2a2**, por lo que podemos poner código a continuación sin tener que calcular cuánto ocupa la rutina de ISR. De esta forma también podemos tener la rutina de ISR junto al resto del código, con la única penalización de 3 bytes y 10 ciclos de reloj del ''jp NN''.
  
  
Línea 1172: Línea 1224:
  
 \\  \\ 
-|< 70% >| +|< 90% >| 
-^ Juego ^ Ubicación tabla vectores ^ Ubicación ISR ^ Tipo de ISR (rutina o salto) ^ Notas ^ +^ Juego ^ Ubicación tabla vectores ^ Ubicación ISR ^ Tipo de ISR (rutina o\\ salto a rutina real) ^ Notas ^ 
-| La Familia Addams (The Addams Family) | $b900-$ba00 | $5b5b | ISR es ''jp $ba6e'' (rutina real) | - |+| La Familia Addams (The Addams Family) | $b900-$ba00 | $5b5b | ISR es ''jp $ba6e'' | - |
 | Where Time Stood Still | $8400-$8500 | $bebe | Rutina ISR | - | | Where Time Stood Still | $8400-$8500 | $bebe | Rutina ISR | - |
-| Demo 7th Reality | $6300-$6400 | $6464 | ISR es ''jp $624d'' (rutina real) | - |+| Demo 7th Reality | $6300-$6400 | $6464 | ISR es ''jp $624d'' | - |
 | La Abadia Del Crimen | $be00-$bf00 | $bfbf | Rutina ISR | - | | La Abadia Del Crimen | $be00-$bf00 | $bfbf | Rutina ISR | - |
-| Chase HQ 2 | $9b00-$9c00 | $fdfd | ISR es ''jp $ba6e'' (rutina real) | ISR en bloque paginable |  +| Chase HQ 2 | $9b00-$9c00 | $fdfd | ISR es ''jp $ba6e'' | ISR en bloque paginable |  
-| Grand Prix Circuit | $8200-$8300 | $6363 | ISR es ''jp $a07a'' (rutina real) | - | +| Grand Prix Circuit | $8200-$8300 | $6363 | ISR es ''jp $a07a'' | - | 
-| Robocop 2 | $7700-$7800 | $5b5b | ISR es ''jp $9cb4'' (rutina real) | - | +| Robocop 2 | $7700-$7800 | $5b5b | ISR es ''jp $9cb4'' | - | 
-| Robocop 3 | $7700-$7800 | $7676 | ISR es ''jp $8225'' (rutina real) | - | +| Robocop 3 | $7700-$7800 | $7676 | ISR es ''jp $8225'' | - | 
-| Spacegun | $be00-$bf00 | $bfbf | ISR es ''jp $a07a'' (rutina real) | - | +| Spacegun | $be00-$bf00 | $bfbf | ISR es ''jp $a07a'' | - | 
-| Desafio Total (Total Recall) | $9100-$9200 | $5d5d | ISR es ''jp $71ff'' (rutina real) | - |+| Desafio Total (Total Recall) | $9100-$9200 | $5d5d | ISR es ''jp $71ff'' | - |
 | Carrier Command | $8300-$8400 | $8585 | Rutina ISR | - | | Carrier Command | $8300-$8400 | $8585 | Rutina ISR | - |
 | El Gran Halcón (Hudson Hawk) | $9000-$8100 | $8181 | Rutina ISR | - | | El Gran Halcón (Hudson Hawk) | $9000-$8100 | $8181 | Rutina ISR | - |
-| NARC | $be00-$bf00 | $bfbf | ISR es ''jp $de38'' (rutina real) | - | +| NARC | $be00-$bf00 | $bfbf | ISR es ''jp $de38'' | - | 
-| Navy Seals | $9100-$9200 | $5d5d | ISR es ''jp $6dfd'' (rutina real) | - | +| Navy Seals | $9100-$9200 | $5d5d | ISR es ''jp $6dfd'' | - | 
-| Pang | $8000-$8101 | $8181 | ISR es ''jp $6286'' (rutina real) | - |+| Pang | $8000-$8101 | $8181 | ISR es ''jp $6286'' | - |
 \\  \\ 
  
  • cursos/ensamblador/interrupciones.1705835144.txt.gz
  • Última modificación: 21-01-2024 11:05
  • por sromero