%
% GSE 1994.
% Arquitectura de Computadores.
% Practica 1. Introduccion al ensamblador. 1994-1995.
%

\typeout{}
\typeout{Arquitectura de Computadores. Pract 4. Timer del IBM PC.}
\typeout{}

\documentstyle[twoside]{IEEEtran}

\begin{document}

\title{Pr\'actica 4. Programaci\'on del temporizador del IBM PC.}
\author{}
\markboth{Pr\'actica 4. Programaci\'on del temporizador del IBM PC.}{Pr\'actica 4. Programaci\'on del temporizador del IBM PC.}
\maketitle

\section{Introducci\'on.}
En esta pr\'actica aprenderemos a usar el temporizador del IBM PC. De esta
forma estamos en la disposici\'on de ejecutar funciones (escritas en ensambador
o en C, Pascal, ...) cada cierto intervalo de tiempo, sin la necesidad de que
lo indiquemos con ninguna llamada a esa funci\'on. Esto es \'util en
situaciones en las que de forma intermitente deseamos que nuestra computadora
realice una determinada tarea.

En la familia de ordenadores IBM existen diferentes circuitos dedicados a contar
tiempo. Existen 3 elementos temporizadores que se dedican a:

\begin{enumerate}
 \item marcar la velocidad de funcionamiento de la CPU (MHz).
 \item llevar el contador de tiempo del sistema (tic-tacs).
 \item Un reloj/calendario de tiempo real (dia,mes,a\~no,hora,minuto,segundo).
 \item Generar sonido a trav\'es de (ese fistro de) altavoz haciendo que suene
 como un zumbador.
\end{enumerate}

\section{Osciladores.}

En el PC original, la extra\~na velocidad de 4.77MHz esta derivada de una
frecuencia b\'asica de un oscilador (generalmente de cuarzo) que oscila a
14.31818MHz, utilizado habitualmente en la circuiter\'{\i}a de los televisores
a color. Si se divide esta frecuencia entre 12, obtenemos 1.19318MHz que es
la frecuencia de reloj que se utiliza para el temporizador i8253 (ver
ap\'endice A) en los PC's y el i8254 (ver ap\'endice A) en los AT's y PS/2.
Actualmente los AT's, PS/2, 386 y 486 tienen una velocidad de reloj de la CPU
mas alta. Estas frecuencias no se pueden modificar por software (que m\'as
quisi\'esemos nosotros).

\section{Temporizadores.}

En los PC's se monta el intel i8253 (ver ap\'endice A) y en el resto de la
familia IBM el intel i8254 (ver apendice A). Se emplean para contar los pulsos
a 1.19318MHz que llegan del divisor de frecuencia del oscilador principal del
sistema (el que marca el ritmo de funcionamiento de la CPU). Funciona
independientemente de la CPU. Lo \'unico que necesita de ella es que sea
programado para iniciar sus registros.

Poseen 3 canales id\'enticos pero que se dedican a 3 areas distintas. Cada
canal se compone de un LATCH de 16 bits y un contador de 16 bits. La CPU
escribe un valor en el LATCH. En esto consiste la programaci\'on de un canal.
Sobre el contador existe un n\'umero que siempre est\'a decrement\'andose.
Irremediablemente este llega a 0, y cuando esto se produce, el temporizador
emite un pulso por su l\'{\i}nea OUT y carga el contenido del LATCH en el
contador. A partir de aqu\'{\i} se repite la secuencia. El contenido del
LATCH no se altera hasta que la CPU vuelve a reescribirlo.

\begin{enumerate}
 \item {\bf canal 0: el 'tic-tac' del sistema.}\newline
Se uliliza en el reloj del sistema. Est\'a controlado por la ROM BIOS desde el
encendido del ordenador, de forma que produce aproximadamente 18.2 pulsos por
segundo. Se mantiene una cuenta de estos pulsos en la posici\'on de memoria
0x0040:0x006C, que contiene el cuenteo del reloj del sistema.

Con cada ciclo de reloj (a raz\'on de 1193180 veces por segundo) se decrementa
el contador de 16 bits del canal 0. Sobre el LATCH asociado a este canal hay
escrito 0xFFFF (salvo que nosotros indiquemos lo contrario. El tiempo que se
tarda en convertir este valor en 0 es 65536/1193180 Hz = 0.0549254 seg. Esto
indica que se producen 1/(0.0549254 seg)=18.206482 pulsos por segundo (Hz).

La salida del temporizador est\'a conectada a la IRQ0 (ver ap\'endice B) . Esta
es gestionada por el PIC i8259A (ver apendice C). La ROM BIOS controla el
contador de tiempo del sistema a trav\'es de la interrupci\'on 0x08. Esto
significa que en la entrada 0x08 del vector de interrupciones (ver ap\'endice D)
del ordenador hay un puntero que apunta a la rutina de gesti\'on del contador
de tiempo del sistema que pertenece a la BIOS. Esta se ejecuta 18.2 veces por
segundo, salvo que no indiquemos lo contrario, deshabilitando las interrupciones
hardware.

Tambi\'en es posible hacer que esta rutina se lance m\'as veces por segundo
cargando sobre el LATCH del canal 0 un n\'umero inferior a 0xFFFF. Esta rutina,
antes de finalizar, llama a la interrupci\'on 0x1C. Esta apunta a una
instrucci\'on RETI (RETorno de Interrupci\'on). Si hacemos que esta entrada en el
vector de interrupciones apunte a un programa construido por nosotros que
acabe con una instrucci\'on RETI, habremos realizado un programa que se lanza
18.2 veces por segundo. Esto acarrea un imperativo: el que nuestra rutina no
tarde m\'as de 0.0549254 segundos en ejecutarse (no es demasiado tiempo). Si
esto no es asi anidaremos llamadas a nuestra rutina restora de interrupci\'on
porque es llamada antes de que se termine de ejecutar.

\item {\bf canal 1: refresco de la memoria.}\newline
Controla el refresco de memoria de todas las m\'aquinas, con excepci\'on del PCjr.
Es mejor dejarlo en paz. La l\'{\i}nea OUT de este canal est\'a conectada al
DMA (i8237), que es el chip encargado de refrescar las DRAM.

\item {\bf canal 2: hace zumbar el altavoz.}\newline
La l\'{\i}nea OUT de este canal esta conectada al amplificador que da la potencia
necesaria para que oscile la membrana del altavoz del PC. Puesto que por esta
l\'{\i}nea lo \'unico que circula son pulsos a direrentes frecuencias, lo \'unico que
emite el altavoz del PC es zumbidos a diferentes frecuencias. Para programar
un zumbido de una frecuencia alta, ponemos un valor bajo en el LATCH del canal
2. El sonido suena de forma constante, hasta que la CPU no indica lo contrario. La frecuencia m\'as baja
generable es de 18.2 Hz. A continuaci\'on exponemos una lista de los puertos
relevantes en entendimiento de esta pr\'actica.

\footnotesize
\begin{verbatim}

Puerto Opers Comentario
------ ----- ----------
0x40   L/E   LATCH del canal 0. Primero escribimos el LSB y a continuacion el MSB.
0x41   L/E   LATCH del canal 1.
0x42   L/E   LATCH del canal 2.
0x43   E     Registro de ordenes del temporizador.
             Sobre el se indica el canal que se va a programar, el modo y
             la posibilidad de que se envie solamente la mitad del LATCH al contador.

                Bits:     Comentario:
                0         0=Datos en binario. 1=Datos en BCD.
                1-3       Modo de funcionamiento.
                4-5       Tipo de operacion:
                             00=Desplazar el valor del contador del LATCH.
                             01=Leer/Escribir solo el MSB.
                             10=Leer/Escribir solo el LSB.
                             11=Leer/Escribir el MSB y a continuacion el LSB.
                6-7       Numero del canal que se va a programar l0-2).

             Por ejemplo: para programar el canal 2 con un numero de 2 bytes
             en formato binario, escribiremos 0xB6.
0x61   E     Pertenece al PPI (Interface Programable de Perifericos) i8255A.
             Despues de que se haya programado el contador de tiempo del canal 2,
             se necesita activar la circuiteria del altavoz. Este se controla
             cambiando los valores de los bits 0 y 1 de este puerto.
             El resto de los bits se utilizan para otras cosas (no tocarlos).
             El bit 0 controla la transmision de la senhal OLIT del segundo canal.
             El bit 1 controla el amplificador.
             Se necesita que los 2 bits esten a 1 para que el altavoz zumbe.

\end{verbatim}
\normalsize
\end{enumerate}

\section{El reloj/calendario de tiempo real.}

S\'olo existe en los AT's y PS/2. Est\'a integrado sobre un Motorola MC146818
(en los AT's), alimentado por bater\'{\i}as, para que no pierda el contenido de
sus registros cuando apagamos el ordenador. En los PS/2, el reloj de tiempo
real est\'a implementado sobre un circuito hecho a medida.

En los dos casos se trata de un procesador independiente que puede contar los
pulsos horarios sin interferencias con las dem\'as operaciones del ordenador.
Est\'a conectado a la IRQ8 (hacia el PIC) y normalmente se manipula con la
rutina de interrupci\'on apuntada por la entrada 0x4A del vector de
interrupciones (ver ap\'endice D). La BIOS del AT y del PS/2 controlan este chip 
a trav\'es de la
interrupci\'on 0x1A. La rutina de la BIOS situada en la posicion de memoria
apuntada por el puntero situado en la posici\'on de memoria 0x0000:(0x001A*4)
(nota: Cada entrada en el vector de interrupciones tiene 4 bytes).
es la rutina que se lanza cada vez que por la IRQ8 se produce una interrupci\'on.
Los puertos asociados al MC146818 son:

\footnotesize
\begin{verbatim}

Puerto Opers Comentario
------ ----- ----------
0x70   E     Registro de direccion.
             En el se indica el numero del registro que se desea leer o escribir:
             Numero_Registro Funcion
             --------------- ------------------
             0x00            Segundos.
             0x01            Alarma de segundos.
             0x02            Minutos.
             0x03            Alarma de minutos.
             0x04            Horas.
             0x05            Alarma de horas.
             0x06            Dia de la semana.
             0x07            Dia del mes.
             0x08            Mes.
             0x09            Anho.
             0x0A            Registro de estado A.
                                 bit 7: 1 si se esta actualizando la hora.
                                        0 se puede leer o escribir la hora.
             0x0B            Registro de estado B.
                                 bit 0: 1 activado el temporizador de tarifas electricas
                                        reducidas (USA).
                                 bit 1: 1 Se cuentan las horas de 0-23.
                                        0 Se cuentan de 0-12.
                                 bit 4: 1 activada la interrupcion de final de actualizacion.
                                 bit 5: 1 activada la interrupcion de alarma.
                                 bit 6: 1 activada la interrupcion periodica.

             0x0C            Registro de estado C.
             0x0D            Registro de estado D.
0x71   L/E   Escribimos o leemos el dato del registro direccionado.

\end{verbatim}
\normalsize

\section{Desarrollo de la pr\'actica.}

Escribir un programa en lenguaje C (preferible Turbo C 2.00) que instale una
rutina gestora de interrupci\'on apuntada por la entrada 0x1C del vector de
interrupciones. Se trata de construir tres funciones:

\footnotesize
\begin{verbatim}

void interrupt Tic();  /* Rutina gestora de la interrupcion 0x1C */
void AliveTic();       /* Instala la rutina de interrupcion sobre la IHT 0x1C */
void KillTic();        /* Desinstala la rutina */

\end{verbatim}
\normalsize

El cuerpo principal del programa deber\'a de tener (al menos) la siguiente
estructura:

\footnotesize
\begin{verbatim}

main()
{
        AliveTic();     /* Activamos nuestra rutina lanzada 18.2 veces/seg */
        getch();        /* Espera a que pulsemos una tecla */
        KillTic();      /* Desactivamos nuestra rutina */
}

\end{verbatim}
\normalsize

Instrucciones necesarias para construir el programa (b\'asico), las
encotraremos en los ficheros cabecera "dos.h" y "conio.h", esto es:

\footnotesize
\begin{verbatim}

#include <dos.h >       /* setvect(), getvect() */
#include <conio.h>      /* getch() */

\end{verbatim}
\normalsize

\noindent Consejo(s):
\begin{enumerate}
\item Dentro de Tic(); es aconsejable poner algunas instrucciones que nos
indiquen que la rutina de interrupci\'on se est\'a ejecutando cada vez que se
produce un "tic". En caso contrario, no sabremos si nuestro programa est\'a
realmente funcionando.

\item Un puntero a una rutina de interrupci\'on se declar\'a as\'{\i}:

\footnotesize
\begin{verbatim}

void interrupt (*OldTic)();

\end{verbatim}
\normalsize
\end{enumerate}

\section{Documentaci\'on (en formato electr\'onico) a entregar.}
\begin{enumerate}
 \item Listado del programa fuente !`DEBIDAMENTE COMENTADO!.
 \item Comentario de la salida.
\end{enumerate}

\section*{Ap\'endice A.}
\footnotesize
\begin{verbatim}

8253/8254 PIT - Programmable Interval Timer
-------------------------------------------
        Port 40h, 8253 Counter 0 Time of Day Clock (normally mode 3)
        Port 41h, 8253 Counter 1 RAM Refresh Counter (normally mode 2)
        Port 42h, 8253 Counter 2 Cassette and Speaker Functions
        Port 43h, 8253 Mode Control Register, data format:

        |7|6|5|4|3|2|1|0|  Mode Control Register
         | | | | | | | +---- 0=16 binary counter, 1=4 decade BCD counter
         | | | | +-+-+----- counter mode bits
         | | +-+---------- read/write/latch format bits
         +-+------------- counter select bits (also 8254 read back command)

        Bits
         76 Counter Select Bits
         00  select counter 0
         01  select counter 1
         10  select counter 2
                11  read back command (8254 only, illegal on 8253, see below)

        Bits
         54  Read/Write/Latch Format Bits
                00  latch present counter value
                01  read/write of MSB only
                10  read/write of LSB only
                11  read/write LSB, followed by write of MSB

        Bits
        321  Counter Mode Bits
               000  mode 0, interrupt on terminal count;  countdown, interrupt,
                    then wait for a new mode or count; loading a new count in the
                    middle of a count stops the countdown
               001  mode 1, programmable one-shot; countdown with optional
                    restart; reloading the counter will not affect the countdown
                    until after the following trigger
               010  mode 2, rate generator; generate one pulse after 'count' CLK
                    cycles; output remains high until after the new countdown has
                    begun; reloading the count mid-period does not take affect
                    until after the period
               011  mode 3, square wave rate generator; generate one pulse after
                    'count' CLK cycles; output remains high until 1/2 of the next
                    countdown; it does this by decrementing by 2 until zero, at
                    which time it lowers the output signal, reloads the counter
                    and counts down again until interrupting at 0; reloading the
                    count mid-period does not take affect until after the period
               100  mode 4, software triggered strobe; countdown with output high
                    until counter zero;  at zero output goes low for one CLK
                    period;  countdown is triggered by loading counter;  reloading
                    counter takes effect on next CLK pulse
               101  mode 5, hardware triggered strobe; countdown after triggering
                    with output high until counter zero; at zero output goes low
                    for one CLK period

        Read Back Command Format  (8254 only)

        |7|6|5|4|3|2|1|0| Read Back Command (written to Mode Control Reg)
         | | | | | | | +--- must be zero
         | | | | | | +---- select counter 0
         | | | | | +----- select counter 1
         | | | | +------ select counter 2
         | | | +------- 0 = latch status of selected counters
         | | +-------- 0 = latch count of selected counters
         +-+--------- 11 = read back command

        Read Back Command Status (8254 only, read from counter register)

        |7|6|5|4|3|2|1|0|  Read Back Command Status
         | | | | | | | +--- 0=16 binary counter, 1=4 decade BCD counter
         | | | | +-+-+---- counter mode bits (see Mode Control Reg above)
         | | +-+--------- read/write/latch format (see Mode Control Reg)
         | +------------ 1=null count (no count set), 0=count available
         +------------- state of OUT pin (1=high, 0=low)


               - the 8253 is used on the PC & XT, while the 8254 is used on the AT+
               - all counters are decrementing and fully independent
               - the PIT is tied to 3 clock lines all generating 1.19318 MHz.
               - the value of 1.19318MHz is derived from (4.77/4 MHz) and has it's
                 roots based on NTSC frequencies
               - counters are 16 bit quantities which are decremented and then
                 tested against zero.  Valid range is (0-65535).  To get a value
                 of 65536 clocks you must specify 0 as the default count since
                 65536 is a 17 bit value.
               - reading by latching the count doesn't disturb the countdown but
                 reading the port directly does; except when using the 8254 Read
                 Back Command
               - counter 0 is the time of day interrupt and is generated
                 approximately 18.2 times per sec.  The value 18.2 is derived from
                 the frequency 1.10318/65536 (the normal default count).
               - counter 1 is normally set to 18 (dec.) and signals the 8237 to do
                 a RAM refresh approximately every 15�s
               - counter 2 is normally used to generate tones from the speaker
                 but can be used as a regular counter when used in conjunction
                 with the 8255
               - newly loaded counters don't take effect until after a an output
                 pulse or input CLK cycle depending on the mode
               - the 8253 has a max input clock rate of 2.6MHz, the 8254 has max
                 input clock rate of 10MHz

        Programming considerations:

                 1.  load Mode Control Register
                 2.  let bus settle (jmp $+2)
                 3.  write counter value
                 4.  if counter 0 is modified, an INT 8 handler must be written to
                     call the original INT 8 handler every 18.2 seconds.  When it
                     does call the original INT 8 handler it must NOT send and EOI
                     to the 8259 for the timer interrupt, since the original INT 8
                     handler will send the EOI also.

        Example code:

               countdown  equ  8000h ; approx 36 interrupts per second

                  cli
                  mov  al,00110110b  ; bit 7,6 = (00) timer counter 0
                                     ; bit 5,4 = (11) write LSB then MSB
                                     ; bit 3-1 = (011) generate square wave
                                     ; bit 0 = (0) binary counter
                  out  43h,al        ; prep PIT, counter 0, square wave&init count
                  jmp  $+2
                  mov  cx,countdown  ; default is 0x0000 (65536) (18.2 per sec)
                                     ; interrupts when counter decrements to 0
                  mov  al,cl         ; send LSB of timer count
                  out  40h,al
                  jmp  $+2
                  mov  al,ch         ; send MSB of timer count
                  out  40h,al
                  jmp  $+2
                  sti

\end{verbatim}
\normalsize

\section*{Ap\'endice B.}
\footnotesize
\begin{verbatim}

IBM PC Hardware Interrupt Table (in order of priority)
------------------------------------------------------
        IRQ#  Interrupt         Function

               IRQ0     8      timer (55ms intervals, 18.2 per second)
               IRQ1     9      keyboard service required
               IRQ2     A      slave 8259 or EGA/VGA vertical retrace
               IRQ8    70      real time clock  (AT,XT286,PS50+)
               IRQ9    71      software redirected to IRQ2  (AT,XT286,PS50+)
               IRQ10   72      reserved  (AT,XT286,PS50+)
               IRQ11   73      reserved  (AT,XT286,PS50+)
               IRQ12   74      mouse interrupt  (PS50+)
               IRQ13   75      numeric coprocessor error  (AT,XT286,PS50+)
               IRQ14   76      fixed disk controller (AT,XT286,PS50+)
               IRQ15   77      reserved  (AT,XT286,PS50+)
               IRQ3     B      COM2 or COM4 service required, (COM3-COM8 on MCA PS/2)
               IRQ4     C      COM1 or COM3 service required
               IRQ5     D      fixed disk or data request from LPT2
               IRQ6     E      floppy disk service required
        IRQ7     F      data request from LPT1 (unreliable on IBM mono)
\end{verbatim}
\normalsize

\section*{Ap\'endice C.}
\footnotesize
\begin{verbatim}

8259. PIC (Programmable Interrupt Controller)
---------------------------------------------
Registro Funci�n                                           Puerto(s)
-------- ------------------------------------------------  --------------
ICW1     Initialization Command Word 1                     20h,A0h
ICW2     Initialization Command Word 2                     21h,A1h
ICW3     Initialization Command Word 3                     21h,A1h
ICW4     Initialization Command Word 4                     21h,A1h
OCW1/IMR Operation Control Word 1 / Interrupt Mask Reg     21h,A1h
OCW2/ICR Operation Control Word 2 / Interrupt Command Reg. 20h,A0h
OCW3     Operation Control Word 3                          20h,A0h
IRR      Interrupt Request Register                        -
ISR      In Service Register                               -

        |7|6|5|4|3|2|1|0|  ICW1
         | | | | | | | +---- 1=ICW4 is needed, 0=no ICW4 needed
         | | | | | | +----- 1=single 8259, 0=cascading 8259's
         | | | | | +------ 1=4 byte interrupt vectors, 0=8 byte int vectors
         | | | | +------- 1=level triggered mode, 0=edge triggered mode
         | | | +-------- must be 1 for ICW1 (port must also be 20h or A0h)
         +-+-+--------- must be zero for PC systems

        |7|6|5|4|3|2|1|0|  ICW2
         | | | | | +-+-+---- 000= on 80x86 systems
         +-+-+-+-+--------- A7-A3 of 80x86 interrupt vector

        |7|6|5|4|3|2|1|0|  ICW3 for Master Device
         | | | | | | | +---- 1=interrupt request 0 has slave, 0=no slave
         | | | | | | +----- 1=interrupt request 1 has slave, 0=no slave
         | | | | | +------ 1=interrupt request 2 has slave, 0=no slave
         | | | | +------- 1=interrupt request 3 has slave, 0=no slave
         | | | +-------- 1=interrupt request 4 has slave, 0=no slave
         | | +--------- 1=interrupt request 5 has slave, 0=no slave
         | +---------- 1=interrupt request 6 has slave, 0=no slave
         +----------- 1=interrupt request 7 has slave, 0=no slave

        |7|6|5|4|3|2|1|0|  ICW3 for Slave Device
         | | | | | +-+-+---- master interrupt request slave is attached to
         +-+-+-+-+--------- must be zero

        |7|6|5|4|3|2|1|0|  ICW4
         | | | | | | | +---- 1 for 80x86 mode, 0 = MCS 80/85 mode
         | | | | | | +----- 1 = auto EOI, 0=normal EOI
         | | | | +-+------ slave/master buffered mode
         | | | |                 00     not buffered
         | | | |                 01     not buffered
         | | | |                 10     buffered mode slave (PC mode)
         | | | |                 11     buffered mode master (PC mode)
         | | | +--------- 1 = special fully nested mode (SFNM), 0=sequential
         +-+-+---------- unused (set to zero)

        |7|6|5|4|3|2|1|0|  OCW1 - IMR Interrupt Mask Register
         | | | | | | | +---- 0 = service IRQ0, 1 = mask off
         | | | | | | +----- 0 = service IRQ1, 1 = mask off
         | | | | | +------ 0 = service IRQ2, 1 = mask off
         | | | | +------- 0 = service IRQ3, 1 = mask off
         | | | +-------- 0 = service IRQ4, 1 = mask off
         | | +--------- 0 = service IRQ5, 1 = mask off
         | +---------- 0 = service IRQ6, 1 = mask off
         +----------- 0 = service IRQ7, 1 = mask off

        |7|6|5|4|3|2|1|0|  OCW2 - ICR Interrupt Command Register
         | | | | | +-+-+---- interrupt request level to act upon
         | | | | +--------- must be 0 for OCW2
         | | | +---------- must be 0 for OCW2
         +-+-+----------- EOI type
                                001  non-specific EOI command
                                010  NOP
                                011  specific EOI command
                                100  rotate in automatic EOI mode
                                101  rotate on non-specific EOI command
                                110  set priority command  (uses bits 2-0)
                                111  rotate on specific EOI command

        |7|6|5|4|3|2|1|0|  OCW3
         | | | | | | | +--- 1=read IRR on next read, 0=read ISR on next read
         | | | | | | +---- 1=act on value of bit 0, 0=no action if bit 0 set
         | | | | | +----- 1=poll command issued, 0=no poll command issued
         | | | | +------ must be 1 for OCW3
         | | | +------- must be 0 for OCW3
         | | +-------- 1=set special mask, 0=reset special mask
         | +--------- 1=act on value of bit 5, 0=no action if bit 5 set
         +---------- not used (zero)

\end{verbatim}
\normalsize

\section*{Ap\'endice D}
\footnotesize
\begin{verbatim}

Intel Defined CPU Exception Table (see notes)
---------------------------------------------
        Interrupt         Function

                0      Divide by zero
                1      Single step
                2      Non-maskable  (NMI)
                3      Breakpoint
                4      Overflow trap
                5      BOUND range exceeded (186,286,386)
                6      Invalid opcode (186,286,386)
                7      Coprocessor not available (286,386)
                8      Double fault exception (286,386)
                9      Coprocessor segment overrun (286,386)
                A      Invalid task state segment (286,386)
                B      Segment not present (286,386)
                C      Stack exception (286,386)
                D      General protection exception (286,386)
                E      Page fault (286,386)
                F      Reserved
               10      Coprocessor error (286,386)

Interrupt Table as Implemented by System BIOS/DOS
-------------------------------------------------
       INT #   Locus            Function

                0      CPU     divide by zero
                1      CPU     single step
                2      CPU     non-maskable
                3      CPU     breakpoint
                4      CPU     overflow trap
                5      BIOS    print screen
                6      CPU     Invalid opcode (186,286,386)
                7      CPU     coprocessor not available (286,386)
                8      IRQ0    timer (55ms intervals, 18.21590 per second)
                9      IRQ1    keyboard service required (see INT 9)
                A      IRQ2    slave 8259 or EGA/VGA vertical retrace
                B      IRQ3    COM2 service required (PS/2 MCA COM3-COM8)
                C      IRQ4    COM1 service required
                D      IRQ5    fixed disk or data request from LPT2
                E      IRQ6    floppy disk service required
                F      IRQ7    data request from LPT1 (unreliable on IBM mono)
               10      BIOS    video (see INT 10)
               11      BIOS    Equipment determination (see INT 11)
               12      BIOS    memory size (see INT 12)
               13      BIOS    disk I/O service  (see INT 13)
               14      BIOS    serial communications (see INT 14)
               15      BIOS    system services, cassette (see INT 15)
               16      BIOS    keyboard services (see INT 16)
               17      BIOS    parallel printer (see INT 17)
               18      BIOS    ROM BASIC loader
               19      BIOS    bootstrap loader (unreliable, see INT 19)
               1A      BIOS    time of day (see INT 1A)
               1B      BIOS    user defined ctrl-break handler (see INT 1B)
               1C      BIOS    user defined clock tick handler (see INT 1C)
               1D      BIOS    6845 video parameter pointer
               1E      BIOS    diskette parameter pointer (base table)
               1F      BIOS    graphics character table
               20      DOS     general program termination
               21      DOS     function request services (see INT 21)
               22      DOS     terminate address (see INT 22)
               23      DOS     control break termination address (see INT 23)
               24      DOS     critical error handler (see INT 24)
               25      DOS     absolute disk read (see INT 25)
               26      DOS     absolute disk write (see INT 26)
               27      DOS     terminate and stay resident (see INT 27)
               28      DOS     idle loop, issued by DOS when idle (see INT 28)
               29      DOS     fast TTY console I/O (see INT 29)
               2A      DOS     critical section and NETBIOS (see INT 2A)
               2B      DOS     internal, simple IRET in DOS 2.0-5.0
               2C      DOS     internal, simple IRET in DOS 2.0-5.0
               2D      DOS     internal, simple IRET in DOS 2.0-5.0
               2E      DOS     exec command from base level command interpreter (see INT 2E)
               2F      DOS     multiplexer (see INT 2F)
               30-31   CPM     far jump vector for CPM (not an interrupt)
               31      DPMI    DOS Protected Mode Interface (for DOS extenders)
               32              reserved
               33              mouse support (see INT 33)
               34-3E           Microsoft/Borland floating point emulation
               3F              overlay manager
               40      BIOS    hard disk
               41      BIOS    fixed disk 0 parameters pointer (see INT 13,9)
               42      BIOS    relocated video handler (EGA/VGA/PS)
               43      BIOS    user font table (EGA/VGA/PS)
               44      BIOS    first 128 graphics characters (also Netware)
               45      BIOS    reserved for BIOS
               46      BIOS    fixed disk 1 parameters ptr (see INT 13,9/INT 41)
               47      BIOS    reserved for BIOS
               48      BIOS    PCjr cordless keyboard translation
               49      BIOS    PCjr non-keyboard scancode translation table
               4A      BIOS    user alarm  (AT,CONV,PS/2) (see INT 4A)
               4B-4F   BIOS    reserved
               50      BIOS    periodic alarm from timer (PS/2)
               51-58   BIOS    reserved
               59      BIOS    GSS Computer Graphics Interface
               5A      BIOS    cluster adapter BIOS entry point
               5B      BIOS    cluster adapter boot
               5C      NETBIOS NETBIOS interface, TOPS interface
               5D-5F   BIOS    reserved for BIOS
               60-67           reserved for user software interrupts
               67      EMS     LIM/EMS specification (see INT 67)
               68              APPC
               69-6B           reserved by IBM
               6C      DOS     DOS 3.2 real time clock update
                       BIOS    system resume vector
               6D-6F           reserved
               70      IRQ8    real time clock  (AT,XT286,PS50+, see INT 15)
               71      IRQ9    software redirected to IRQ2 (AT,XT286,PS50+)
               72      IRQ10   reserved  (AT,XT286,PS50+)
               73      IRQ11   reserved  (AT,XT286,PS50+)
               74      IRQ12   mouse interrupt  (PS50+)
               75      IRQ13   numeric coprocessor NMI error (AT,XT286,PS50+)
               76      IRQ14   fixed disk controller (AT,XT286,PS50+)
               77      IRQ15   reserved (AT,XT286,PS50+)
               78-79           unused
               80-85           ROM BASIC
               86-F0   DOS     reserved for BASIC interpreter use
               86      NETBIOS NETBIOS relocated INT 18
               E0      CPM     CP/M 86 function calls
               F1-FF           reserved by IBM
               FE-FF           may be destroyed by return from protected
                               mode using VDISK on 286 machines

               - Intel defined 0 through 20h for use for internal CPU;  IBM
                 redefined interrupts 0 through 1Fh for its own use, hence
                 the duplicate definitions in the tables
               - all interrupts except the internal CPU exceptions push the
                 flags and the CS:IP of the next instruction onto the stack.
                 CPU exception interrupts are similar but push the CS:IP of the
                 causal instruction.   8086/88 divide exceptions are different,
                 they return to the instruction following the division
               - interrupts are disabled upon entry into any interrupt routine and
                 should be enabled by the user or by an IRET
               - in DOS 3.2+ hardware IRQ interrupts are re-vectored through DOS
                 to provide standard stack frames

\end{verbatim}
\normalsize

\begin{thebibliography}{1}
\bibitem{Guia}
  Peter Norton, Richard Wilton, \newline
  {\em Gu\'{\i}a del Programador para el IBM PC y PS/2}, \newline
  Microsoft Press - Anaya Multimedia, 1988, \newline
  ISBN: 84-7614-226-9.

\bibitem{Solucionario}
  Robert Jourdain.
  {\em Solucionario del Programador para IBM PC, XT, AT y Compatibles}, \newline
  AnayaMultimedia. 1988.

\bibitem{MAPH}
  {\em Microprocessor and Peripheral Handbook. Volume 1. Microprocessor},\newline
  Intel Corporation. SMD Techical Mktg. SC4-40.\newline
  P.O. Box 58122.\newline
  Santa Clara, CA 95052-8122.

\bibitem{TurboC}
  {\em Turbo C. Reference Guide. Version 2.0.}\newline
  {\em Turbo C. User's Manual. Version 2.0.}\newline
  Borland International, inc.

\end{thebibliography}

\def\mes{\ifcase\number\month\or Enero\or Febrero\or Marzo\or Abril\or Mayo\or Junio\or Julio\or Agosto\or Septiembre\or Octubre\or Noviembre\or Diciembre\fi}

\section*{Autores.}
\noindent {\em Vicente Gonz\'alez Ruiz.}\newline
{\em Jose Antonio Mart\'{\i}nez Garc\'{\i}a.}\newline
{\em Jos\'e Fern\'andez Vadillos.}\newline
Departamento de Arquitectura de Computadores y Electr\'onica.\newline
Universidad de Almer\'{\i}a.\newline
04120 La Ca\~nada de San Urbano, s/n.\newline
Almer\'{\i}a.

\bigskip
\small
GSE. Este documento fu\'e interpretado con {\LaTeX} el d\'{\i}a {\number\day} de {\mes} de {\number\year}.

\end{document}
