Interrupciones en ensamblador Intel 8086
viernes, octubre 22, 2010 | Author: Aldo JB Madueño
 una pequeña base de los que es el lenguaje ensamblador. Ahora veremos que son las interrupciones en el Intel 8086 y para que se utilizan.

¿Que son las interrupciones del Intel 8086?
Pues las interrupciones son señales enviadas por alguno de los perifericos que advierten al procesador que ha habido actividad en dicho periférico. Por ejemplo cuando pulsamos alguna tecla, el teclado envía una señal de que ha sido pulsada una tecla y envía el código binario de la tecla pulsada. A continuación veremos más a fondo cual es el proceso de las interrupciones y que tipos hay. 

¿Como se gestionan las interrupciones del Intel 8086?
Las interrupciones del Intel 8086 se gestionan por el Controlador de interrupciones. Dicho controlador tiene cuatro registro (memorias) de 16 bits cada uno. Cada uno de estos registros tiene una función especifica y gracias a ellos se van a gestionar funciones como las prioridades de los perifericos, peticiones de servicio etc. Estos registro son:
- Registro IRR: marca las peticiones de los perifericos
- Registro IMR: esta en el puerto 21h y da permisos a las peticiones de las interrupciones. Pasa si es 0 y no pasa si es 1. 
- Registro IPR: lógica que selecciona la prioridad
- Registro ISR: marca que peticiones se estan activando
- Registro de Control: está en el puerto 20h y es el encargado de avisar al procesador que ha acurrido una interrupción. 

El controlador de interrupciones tiene 8 entrada para los distintos perifericos y la habilitación es por flanco (es decir, es controlado por la señal del reloj) y es programable. Es decir cambiando los valores del registro de control y del registro IMR podemos controlar las interrupciones. 

Ya he mencionado que el controlador de interrupciones tienen 8 entradas. Estas 8 entradas podeis verlas en la imagen de abajo (hay que tener en cuenta que el más prioritario es el reloj y el menos prioritario es la impresora):



En la imagen podemos observar que se nos muestra la dirección de memoria (en décima) en la que está ubicado cada uno de los periféricos. En dicha dirección de memoria se almacena el Driver del Sistema Operativo que se encarga de controlar dicho periférico. Ahora teniendo en cuenta que el controlador de interrupciones es programable podemos programar nuestros propios Drivers y sustituir los en las direcciones de memoria indicadas por el vector de interrupciones. Esta sustitución de Driver se hace en el caso de que tenemos que programar una aplicación que tenga funciones especificas de los periféricos. Por ejemplo en los juegos las distintas teclas tienen funciones especificas por tanto al iniciar el juego tenemos que poner nuestro propio Driver y al acabar el juego tenemos que restablecer el Driver del Sistema Operativa para que el teclado funcione con normalidad. 

Por ultimo os tengo que comentar que las interrupciones forman parte del proceso de Entrada/Salida (E/S) del ordenador. Este proceso está descrito a continuación:



En la imagen podemos observar que la E/S de datos se realiza mediante una sincronización (que puede ser por encuesta o por interrupción) y a continuación se hace una trasferencia (que puede ser programada o por DMA). 

La diferencia entre la sincronización por encuesta y la sincronización por interrupciones es que en la encuesta el ordenador nos piden obligatoria mente la activación de alguno de los periféricos (por ejemplo pulsar una tecla) mientras que en la interrupción la CPU hace su trabajo y si se activa alguno de los periféricos realiza una transferencia, es decir, tratar la interrupción mediante programación (si la transferencia es programada). A continuación os dejo un ejemplo muy sencillo de sincronización por interrupción con transferencia programada:


TITLE nombre_del_programa
MODEL small
.STACK 100h ; asignamos a la pila tamaño 100h
.DATA ; empiza el segmento de declaracion de variables
;--------------------------------------------------------------------
;BLOQUE DE VARIABLES
;--------------------------------------------------------------------
tecla db ? ; almacena el valor de una tecla que se ha pulsado
crono db 0 ; variable de cronometro. almacena la cantidad de veces que el reloj de la CPU envia una señal
;---------------------------------------------------------------
; DATOS: VECTOR DE INTERRUPCIONES
;---------------------------------------------------------------
ip_reloj DW 0 ; ip rut. serv. reloj del sistema
cs_reloj DW 0 ; cs rut. serv. reloj del sistema
ip_tecla DW 0 ; ip rut. serv. teclado del sistema
cs_tecla DW 0 ; cs rut. serv. teclado del sistema
IRQ0 EQU 8*4 ; d.e. de la interrupción de reloj
IRQ1 EQU 9*4 ; d.e. de la interrupción de teclado
.CODE ; A PARTIR DE AQUI EMPIEZA EL PROGRAMA
;Esto hay que hacer lo siempre cuando empiza un programa
principio: mov ax,@DATA ; almacenamos en reg. ax la dir. de memoria en la que empieza nuestro programa
mov ds,ax ; movemos el valor de reg. ax en reg. ds.
;--------------------------------------------------------------------
;CAMBIA LOS DRIVERS DEL SISTEMA OPERATIVO POR LOS NUESTROS
;--------------------------------------------------------------------
;CAMBIO DE RUTINA DE SERVICIO DEL S.O.
xor ax,ax ; ponemos ax=0
mov es,ax ; moves el valor de ax en es

;Rutina del reloj. Desactivamos el Driver del Sistema Operativo
;y almacenamos en las variables ip_reloj y cs_reloj las dirección
;de memoria en la que esta almacendo el Driver del reloj
mov si,IRQ0
mov ax,es:[si]
mov ip_reloj,ax
mov ax,es:[si+2]
mov cs_reloj,ax

;Activamos nuestro propio Driver de teclado
cli
mov ax,OFFSET reloj ;reloj_int: empieza rutina de servicio del reloj
mov es:[si],ax
mov ax,cs
mov es:[si+2],ax
sti


;Rutina del teclado.Desactivamos el Driver del Sistema Operativo
;y almacenamos en las variables ip_tecla y cs_tecla las dirección
;de memoria en la que esta almacendo el Driver del teclado
mov si,IRQ1
mov ax,es:[si]
mov ip_tecla,ax
mov ax,es:[si+2]
mov cs_tecla,ax

;Activamos nuestro propio Driver de teclado
cli
mov ax,OFFSET teclado
mov es:[si],ax
mov ax,cs
mov es:[si+2],ax
sti

;---------------------------------------------------------------
;CÓDIGO DEL PROGRAMA PRINCIPAL
;---------------------------------------------------------------
; AQUI TIENE QUE PONER EL CÓDIGO DEL PROGRAMA PRINCIPAL
; AQUI TIENE QUE PONER EL CÓDIGO DEL PROGRAMA PRINCIPAL
; AQUI TIENE QUE PONER EL CÓDIGO DEL PROGRAMA PRINCIPAL
; AQUI TIENE QUE PONER EL CÓDIGO DEL PROGRAMA PRINCIPAL
;---------------------------------------------------------------
;RECUPERAMOS LOS DRIVERS DEL S.O.
;---------------------------------------------------------------
xor ax,ax ; ponemos ax=0
mov es,ax ; movemos el valor de ax en es
;Recuperacion rutina de servicio reloj del S.O.
cli ; desactivamos las interrupciones para que no interrumpan el programa
mov si,IRQ0
mov ax,ip_reloj
mov es:[si],ax
mov ax,cs_reloj
mov es:[si+2],ax
sti
 ; activamos las interrupciones

;Recuperacion rutina de servicio teclado del S.O.
xor ax,ax
mov es,ax


cli ; deactivamos las interrupciones durante el proceso de camibio de driver del teclado
mov si,IRQ1
mov ax,ip_tecla
mov es:[si],ax
mov ax,cs_tecla
mov es:[si+2],ax
sti
 ; activamos las interrupciones

mov ah,4Ch ;SIEMPRE: devolver el control
int 21h ;al sistema operativo
;---------------------------------------------------------------
;RUTINAS DE SERVICIO
;Rutina de servicio del reloj
;---------------------------------------------------------------
reloj:
push ax

inc crono
 ; incrementamos la variable crono con una unidad

;EOI: proceso en el cual indicamos al registro de control de interrupciones que se ha acabado la interrupción
mov al,20h ; almacenamos en el registro al el dato 21h
out 20h,al ; escribimos el datos 21h (del reg. al) en el puerto 21h (registro de control del controlador de interrupciones)

pop ax
iret
 ; volvemos en la dir. de memoria en la que ha sido interrumpido el programa principal
;-----------------------------------------------------------------
;RUTINA DE SERVICIO DEL TECLADO
; Es nuetro propio DRIVER DE TECLADO
;----------------------------------------------------------------
teclado:
sti

push ax ; almacenamos en la pila el valor de ax para no interrumpir el correcto fucionamiento del programa principal
pushf ; almacenamos en la pila la palabra de estado o los flags de la CPU

in al,60h ; leemos del puerto 60h la tecla que se pulsado
PUSH AX ; almacenamos en el registro ax la tecla pulsada y lo guardamos en la pila

; es un proceso en el cual vamos a indicar al procesador que se ha liedo una tecla y que podemos leer una nueva
IN AL, 61H ;al = Registro de control (61h)
OR AL, 10000000B ;al = 1XXXXXXX
OUT 61H, AL ;Bit de strobe = 1 .Es decir se autoriza la lectura de otro dato del teclado
AND AL, 011111111B
OUT 61H, AL

;FIN 

;Gestion de tecla de pausa en partida
POP AX ;Recuperamos la tecla que se ha pulsado
mov tecla,a ; almacenamos en la variable tecla el código de la tecla que se ha pulsado

;EOI: proceso en el cual indicamos al registro de control de interrupciones que se ha acabado la interrupción
mov al,20h ; almacenamos en el registro al el dato 21h
out 20h,al ; escribimos el datos 21h (del reg. al) en el puerto 21h (registro de control del controlador de interrupciones)

popf ; recuperamos la palabra de estado de la CPU
pop ax ; recuperamos el valor antiguo del registro ax
iret ; volvemos en la dirección de memoria en la que ha sido interrupmido el programa principal

END principio



En proceso es el siguiente: al empezar el programa el Sistema Operativo asigna una dirección de memoria en la que empieza nuestro programa. Así que se recupera nuestro programa del disco duro y se almacena en la RAM a partir de la dirección asignada en la linea 1 de nuestro programa. A continuación nosotros hemos decidido cambiar los Drivers de teclado y de reloj del Sistema Operativo por nuestros Propios Drivers que hemos llamado reloj y teclado. A continuación debe ir el código del programa principal de la aplicación que vamos a programar y antes de finalizar el programa debemos recuperar los Drivers del teclado y reloj del Sistema Operativo para que pueda funcionar con normalidad el ordenador. Para finalizar devolvemos el control al Sistema Operativo y el programa acaba. 


Las instrucciones del lenguaje ensamblador las podéis consultar en la dirección web de Intel: Manual de ensamblador Intel
http://www.intel.com/products/processor/manuals/index.htm
This entry was posted on viernes, octubre 22, 2010 and is filed under . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.