%
% GSE 1994.
% Arquitectura de Computadores.
% Practica 3. Lectura del Byte del equipo. 1994-1995.
%

\typeout{}
\typeout{Arquitectura de Computadores. Pract 5. Programaci�n del teclado del IBM PC.}
\typeout{}

\documentstyle[twoside]{IEEEtran}

\begin{document}

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

\section{Introducci\'on a los manejadores de perif\'ericos del DOS.}

La filosof\'{\i}a original del sistema operativo MS-DOS fue la de manejar los
dispositivos externos de forma que cada uno de ellos se gestionara a trav\'es
de una interrupci\'on (hardware o software). Posteriormente, con el DOS 2.0 y
siguientes, se a\~nadi\'o soporte en el S.O. para menejadores instalables con
una interfaz de alto nivel para el programador. Se instalan definiendo en
el fichero CONFIG.SYS un campo DEVICE con el nombre del manejador a
instalar. En la pr\'actica que proponemos vamos a seguir el primer m\'etodo,
programando una rutina de interrupci\'on para el manejador de teclado,
implementada como una rutina residente (TSR).

\section{Rutina de servicio de la interrupci\'on de teclado.}

\subsection{Manejo de interrupciones.}

La familia x86 realiza la misma secuencia de operaciones para interrupciones
software (mediante INT) que para las generadas por hardware. Cuando tiene lugar
una instrucci\'on INT, la CPU conserva el estado actual del registro de FLAGS
empuj\'andolo en la pila. Despu\'es pone a 0 el flag de interrupci\'on (I) y el de
retenci\'on (T). La inicializaci\'on tiene el mismo efecto que le instrucci\'on CLI,
que incapacita las interrupciones y se asegura que la CPU no es interrumpida
hasta que el procedimiento INT finalice su tarea cr\'{\i}tica. Un controlador de
interrupciones deber\'{\i}a activarlas tan pronto como sea seguro hacerlo utilizando
la intrucci\'on STI. Estas instrucciones pueden omitirse si el c\'odigo del
controlador es muy corto.

A continuaci\'on, la CPU guarda CS en la pila y CS se carga con la direcci\'on del
segmento del controlador en la tabla de vectores de interrupci\'on (ver pr\'actica 4
, ap\'endice D). Esta tabla est\'a indexada multiplicando el n\'umero de INT por
cuatro y sum\'andole la direcci\'on del desplazamiento del controlador que se
encuentra en la tabla de vectores de interrupci\'on. Este proceso le da el control
al procedimiento indicado por CS:IP, el programa de interrupci\'on. Una de las
primeras cosas que hace el controlador es activar las interrupciones.
Cualquier registro que pueda ser modificado, y nos interese guardar, se debe
almacenar en la pila. Cuando el controlador acaba, restaura los registros. Si el
controlador es de una interrupci\'on hardware, informar\'a al PIC que la interrupci\'on
est\'a a punto de acabar envi\'andole un c\'odigo de fin de interrupci\'on
(EOI: End Of Interrupt). Lo \'ultimo que hace el controlador es ejecutar una
intrucci\'on IRET (retorno de interrupci\'on) que da de nuevo el control al
proceso interrumpido.

\subsection{La interrupci\'on de teclado (INT 0x09).}

Todos los eventos del teclado pueden ser divididos en dos interrupciones: la
INT 0x09 del hardware, responsable de almacenar en el buffer las se\~nales del
teclado, y la INT 0x16 del software que las recupera y transmite a la
aplicaci\'on.

Casi todos los teclados de PC tiene un microprocesador de 8 bits, el 8048 (en
los PC's, ver ap\'endice A) o el 8042 (en los AT's y PS/2's, ver ap\'endice B),
con unos 64 bytes de RAM, una ROM con los c\'odigos de rastreo (scan codes, ver
ap\'endice C) de las teclas, y una BIOS. Cuando se pulsa, o libera, una tecla,
el 8084 busca en su ROM el scan code, y cuando la liberamos lo vuelve a emitir,
pero modifica el bit m\'as alto del scan code. Una vez decodificado,
se env\'{\i}a un byte en serie al LS322 (ver ap\'endice D) dentro ya del PC. Este
c\'odigo se env\'{\i}a siempre que el S74 (ver ap\'endice E) da "luz verde" al 8084,
reconociendo que el \'ultimo c\'odigo que ha sido enviado es leido y descifrado
por la INT 0x09. Si el c\'odigo no puede ser enviado se almacena en la RAM del
8084 (en el teclado). Si este buffer se llena, los datos se pueden perder. Para
evitarlo, el 8084 informa al sistema enviando un c\'odigo especial (0xFF) y la
INT notificar\'a al usuario un pitido de error de buffer de teclado lleno.

El scan code es recibido por el LS322, que contiene un registro de
desplazamiento de 8 bits que serializa en envio. La llegada del scan code
provoca que una IRQ (Interrupt ReQuest, ver pr\'actica 4, ap\'endice B) avise
al PIC (ver pr\'actica 4, ap\'endice C) y este a la CPU de que se ha pulsado
una tecla y su scan code ya est\'a en camino. Por supuesto, la IRQ1 que es la
que designa al teclado se habilita nada m\'as encender el ordenador (ver
registro IRR, pr\'actica 4, ap\'endices B y C). Si IRQ1 es la \'unica demanda,
PIC coloca su l\'{\i}nea de demanda de interrupci\'on a 1, para que entra a la
CPU. Si las interrupciones est\'an activadas la CPU ceder\'a a la solicitud.
Si esto ocurre, la CPU primero acaba de ejecutar la instrucci\'on que lleva
entre manos y a continuaci\'on reconoce la petici\'on del PIC enviando una
se\~nal de 3 bits al controlador del bus 8299 (BC) (ver ap\'endice F). Este
c\'odigo puede controlar 7 tipos de demandas al BC, incluyendo la se\~nal que
la CPU pretende enviar o recibir a memoria o a un puerto.

En el caso de una petici\'on de interrupci\'on, la se\~nal enviada por la CPU es el
c\'odigo de reconocimiento (luz verde), que pasa por el BC de vuelta al PIC a
trav\'es de la l\'{\i}nea de reconocimiento de interrupci\'on (INTA) de un bit.

El primer INTA enviado al PIC es usado para temporizaci\'on. El 8259A env\'{\i}a el
vector de interrupci\'on. El PIC sabe que al IRQ1 le corresponde el vector 0x09
porque en el proceso de arranque se le configuran algunos parametros. Tambi\'en
activa el Registro de Servicios (ISR) (ver pr\'actica 4, ap\'endice C) de IRQ's,
otro registro de 8 bits mediante el cual el PIC controla las interrupciones
que estan siendo servidas. La CPU utiliza este valor como \'{\i}ndice de la tabla
de vectores de interrupci\'on.

Lo primero que tiene que hacer el programa BIOS INT 0x09 es recuperar el
c\'odigo de rastreo. El c\'odigo de rastreo se recupera del puerto A (ver
ap\'endice G) del Interfaz Perif\'erico Programable (PPI, chip 8255A, ver
ap\'endice H) cuya direcci\'on es la 0x60, donde lo envi\'o el LS322 por ocho
lineas paralelas.

El PPI, en lo que respecta al teclado, sirve como recurso de c\'odigo de rastreo.
La rutina de la INT 0x09 lee el c\'odigo del puerto A, lo interpreta en su
car\'acter ASCII y almacena el caracter y su c\'odigo de rastreo en el buffer del
teclado. La interrupci\'on 0x09 no es el \'unico programa que puede leer del
puerto A, ya que su lectura no es destructiva. Una vez que INT 0x09 ha leido
el c\'odigo es seguro la lectura de un nuevo c\'odigo. Esto se lleva poniendo a
uno el bit 7 del puerto B del PPI. Este bit esta conectado a una l\'{\i}nea de
"clear" tanto del LS322 (pone a cero el registro) como de S74 (reinicializa el
basculante, que informa al 8048 que puede enviar otro c\'odiqo). Para hacer
esto se env\'{\i}a un EOI codificado como 20H al puerto 20H (command port del
PIC). La se\~nal EOI restaura el bit ISR y IRR (ver pr\'actica 4, ap\'endice C)
asociados con IRQ1, reactivando esa l\'{\i}nea de demanda. Por lo que el PIC
puede atender otra interrupci\'on.

\section{C\'odigos de rastreo.}

La INT 0x09 es especifica del hardware, de manera que no ser\'a la misma para un
teclado de 83 teclas que para uno de 101. Los c\'odigos de rastreo llevan una
decodificaci\'on por parte del teclado ante de ser depositados en el puerto A.
La BIOS mantiene en la posici\'on de memoria 0x0040:0x0017 el estado de las
Shift izquierda y derecha, Control, Alt y las biestado (Ins, BloqMayus, BloqNum
y BloqDespl), estas teclas forman parte de lo que se conoce como teclas de
KB Flags (ver ap\'endice I) y son las que vamos a utilizar en esta pr\'actica.

\section{El buffer del teclado.}

El buffer del teclado es un cl\'asico ejemplo de buffer circular. Comprende 32
bytes lineales y est\'a situado en el area de comunicaciones de la BIOS. La
posici\'on de memoria donde comienza el buffer es la 0x0040:0x001E y acaba en
la 0x0040:0x003E, inclusive (ver pr\'actica 3, ap\'endice A). Estos 32 bytes
estan agrupados en parejas: uno para el c\'odigo ASCII y otro para el c\'odigo de
rastreo (scan code). Estas direcciones de desplazamiento, 0x001E y 0x003E, se
almacenan en otra parte del area de datos de la BIOS en dos palabras
consecutivas en posiciones 0x0040:0x0080 y 0x0040:0x0082 respectivamente.
Los punteros de comienzo y fin de buffer sirven para poder cambiar la
posici\'on del mismo y su tama\~no. Los punteros de cabeza y cola, para
controlar lo que hay en el buffer y se encuentran en las direcciones de
desplazamiento 0x001A y 0x001C, respectivamente.

Como hemos comentado se puede mover y ampliar el buffer. Los punteros del
buffer son de 16 bits por lo que la nueva posici\'on del buffer esta limitada a
estar dentro del segmento 40H. Podemos utilizar parte de la memoria que el
DOS usa en la inicializaci\'on, con el inconveniente que el DOS ni asigna,
ni qestiona esa memoria, por que otros proqramas similares pueden tambi\'en
usarla.

La forma mas sencilla es aprovechar la memoria de orden inferior no usada. La capacidad
de esta memoria es de 256 bytes, comenzando en la posici\'on 0x0040:0x0200.
Este traslado trata simplemente de cambiar los punteros de principio y fin a
las posiciones 0x0040:0x0200 y 0x0040:0x0300 respectivamente. Los punteros de
cabeza y cola tambi\'en se cambian indicando al principio del nuevo buffer, con
lo cual adem\'as lo inicializamos vac\'{\i}o.

\section{Programas residentes (TSR).}

Cuando un programa termina, MS-DOS normalmente cierra cualquier fichero que el
proqrama a abierto, libera toda la memoria que le ha sido asiqnada y retorna
el control al padre, usualmente el COMMAND.COM. Cuando se dise\~n\'o MS-DOS se
pensaron mecanismos para mejorarlo y anadirle extensiones. Una de ellas fue
la funcion TSR, que cuando es llamada por un programa lo deja intacto y
residente en memoria (con toda a memoria disponible y los ficheros abiertos).
Veremos la forma general de construir una TSR y las precauciones que hay que
tomar para implementarlas.

\subsection{Cuestiones de seguridad.}

Algunas precauciones que hay que tomar para hacer una TSR segura y compatible
con otras TSR o programas:

\begin{enumerate}
 \item Elegir una 'hot-key' (tecla o combinaci\'on de teclas que activa nuestra
rutina) que no utilicen otros programas. Es una buena alternativa proveer
varias hot-key's para solucionar las colisiones.
 \item Es aconsejable hacerla lo mas peque\~na posible, con lo que ocupar\'a menos
memoria (est\'an limitadas a 64K) y ser\'a m\'as rapida. Por eso conviene
compilar con el modelo "tiny" y as\'{\i} convertir el .EXE en un .COM que
requiere menos memoria y posee c\'odigo ejecutable m\'as r\'apido. Esto se
puede hacer con la utilidad exe2com.com del MS-DOS.
 \item Cuando se manipulen registros de disco, s\'olo reservar espacio para un
registro y usar disco virtual en memoria.
 \item Comprobar que el programa est\'a residente y, si lo es, no reinstalarlo.
\end{enumerate}

\subsection{?` C\'omo dejar un programa residente.?}

Lo primero que debemos de hacer es cambiar los vectores de interrupci\'on que
vayamos a usar y redirigirlos hacia nuestro manejador de interrupciones.
Despu\'es, lo dejaremos residente estableciendo una pila para los datos, esta
pila se usar\'a cuando la rutina despierte, recordar que la pila del DOS es
peque\~na (para el caso concreto que nos ocupa no ser\'a necesario formar un pila
local, si lo ser\'{\i}a en el caso de una rutina que hace un uso exhaustivo de la
pila, p.e. un reloj residente).

Entonces salvamos la DTA (\'area de tansferencia del disco). Esta debe
restaurarse cuando el programa despierte, encontrando la direcci\'on del flag
INDOS\footnote{El flag INDOS se obtiene llamamdo a la funci\'on indocumentada
DOS 0x34 (Get INDOS Flag) (ver ap\'endice K): Para llamarla ponemos AH=0x34 y
en ES:BX devuelve la direcci\'on del flag. El valor del flag es distinto de
cero cuando se est\'a ejecutando una funci\'on DOS. Debido a la no reentrancia
del DOS, antes de despertar a un programa cuanso se pulsa la hot-key hay que
chequear que no se ejecuta en servivio del DOS. De esta forma se asigna un
m\'etodo de espera hasta que se puede llamar al DOS. Sin embargo, cuando el DOS
est\'a esperando una orden en la l\'{\i}nea de comandos el valor de INDOS es 1
porque est\'a ejecut\'andose la interrupci\'on ociosa 0x28 (tambi\'en indocumentada).
Por tanto, para activar la TSR hay que construir un gestor de intrrupci\'on que
sustituye a la INT 0x28.} que hara falta cuando est\'e residente y calculamos la
cantidad de memoria que necesitara el programa, sus datos y su pila.
El programa puede ya instalarse simplemente llamando a la funci\'on DOS 0x31 e
indicarle en el registro DX la cantidad de memoria que necesitamos (en
bloques de 16 bytes). Si usamos Turbo C podemos llamar a {\bf keep()} que
realiza lo mismo.

Como resultado de la forma de trabajar del DOS, cualquier fichero o
dispositivo que est\'e abierto cuando se llama a esta funci\'on permanece as\'{\i}
y por tanto consume recursos, particularmente descriptores de fichero.
Para evitar esto podemos cerrar aquellos descriptores que no se vayan a
usar (stdin, stdout, stdaux y stdprn).

\subsection{?` C\'omo eliminar una rutina residente.?}
En primer lugar hay que indicar que es complicado eliminar una rutina
que est\'e residente si es que ella no tiene la facultad de salir de la
memoria principal. La complejidad estriba en conseguir el PSP (ver ap\'endice
L), puesto que el PSP del programa que estamos lanzando para desinstalar
ese otro programa residente tiene un PSP muy distinto del que necesitamos
(el que est\'a residente).

\section{La pr\'actica.}
Esta pr\'actica consiste en escribir un programa en Turbo C 2.00 que haga
residente una rutina (de nombre {\bf Madre()}) que sirva como servicio de
interrupci\'on a la INT 0x09 (teclado). Dicha rutina de interrupci\'on (residente
permanentemente en nuestro ordenador, hasta que le indiquemos lo contrario)
interceptar\'a los c\'odigo de rastreo (scan codes) y emitir\'a un pitido
cuya frecuencia depende de la tecla que hemos pulsado (de su scan code).
A continuaci\'on, llamar\'a a Antigua Rutina Controladora del teclado ({\bf ACT()}, 
que originalmente debiera estar sobre la entrada 0x09 del vector
de interrupciones, ver pr\'actica 4, ap\'endice D), para que el resto de tareas
necesarias para el procesamiento de las teclas pulsadas se lleve a cabo.
Adem\'as de esta emisi\'on de pitidos, debe de programarse la posibilidad de
eliminar nuestra rutina residente, cuando ya no deseemos m\'as teclado musical,
o bien no haga falta esa memoria que estamos ocupando con nuestra rutina
{\bf Madre()}. Esta tarea de eliminaci\'on consiste en eliminar de la INT 0x09
la rutina {\bf Madre()} y reenganchar la Antigua Rutina Controladora
({\bf ACT()}).
Por tanto deberemos de dejar el vector de interrupciones como estaba y
liberar la memoria que reservamos al dejar residente nuestro programa con
la instrucci\'on {\bf keep()}. Tambi\'en se contemplar\'a la posibilidad de
que no se instale dos veces en memoria, la rutina {\bf Madre()} si es que por
descuido llamamos dos el ejecutable que debe de contener el c\'odigo que
realiza todas estas tareas. Resumiendo, la funci\'on principal {\bf main()}
realizar\'a:

\begin{enumerate}
 \item Si {\bf Madre()} est\'a ya residente, abortar instalaci\'on.
 \item Guardar la direcci\'on de la {\bf ACT()}.
 \item Instalar su llamada a una entrada libre del vector de interrupciones.
 \item Instalar {\bf Madre()}.
 \item Derjar residente todo el programa ({\bf Madre()}, {\bf KillMadre()} y 
       {\bf main()}). 
\end{enumerate}

\noindent {\bf Madre()} realizar\'a:

\begin{enumerate}
 \item Leer del puerto 0x60 el c\'odigo de exploraci\'on que nos sirve para
       provocar el zumbido.
 \item Extraer el scan code (si es que hemos leido 2 bytes) que es el
       LSB (Low Significant Byte) de lo que hemos leido de los puertos
       0x60 y 0x61.
 \item Leer la posici\'on de memoria 0x0040:0x0017 que contiene un byte con
       los BK Flags.
 \item Extraer del anterior byte las CTRL y ALT cuyo estado est\'a representado
       por los bits de peso 4 y 8 respctivamente.
 \item Si hemos pulsado CTRL+ALT (hot-keys), desinstalar Madre
       {\bf (KillMadre()}).
 \item Probocar un pitido con los 16 bits leidos de los puertos 0x60 y 0x61.
 \item LLamar a {\bf ACT()}.
\end{enumerate}

\noindent {\bf KillMadre()} realizar\'a:

\begin{enumerate}
 \item Eliminar {\bf ACT()} de la entrada del vector de interrupciones.
 \item Insertar {\bf ACT()} en la entrada 0x09.
 \item Eliminar cualquier resquicio de sonido.
 \item Liberar la memoria asignada a el ejecutable.
 \item Liberar la memoria asignada a el PSP (ver ap\'endice L).
\end{enumerate}

\section{Documentaci\'on a entregar (electr\'onicamente).}

\begin{enumerate}
 \item Fichero con el c\'odigo fuente, debidamente comentado.
 \item Fichero {\bf .EXE} y {\bf .COM}.
\end{enumerate}

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

8048. No documentado.

\end{verbatim}
\normalsize

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


                   8042 - Keyboard Controller  (AT,PS/2)
                   -------------------------------------

        8042 Status Register (port 64h read)

        |7|6|5|4|3|2|1|0|  8042 Status Register
         | | | | | | | +---- output register (60h) has data for system
         | | | | | | +----- input register (60h/64h) has data for 8042
         | | | | | +------ system flag (set to 0 after power on reset)
         | | | | +------- data in input register is command (1) or data (0)
         | | | +-------- 1=keyboard enabled, 0=keyboard disabled (via switch)
         | | +--------- 1=transmit timeout (data transmit not complete)
         | +---------- 1=receive timeout (data transmit not complete)
         +----------- 1=even parity rec'd, 0=odd parity rec'd (should be odd)

        Port Mode                 Description

        64h  read   8042 status register. Can be read at any time.  See
                    table above for more information.
        64h  write  8042 command register.  Writing this port sets Bit 3
                    of the status register to 1 and the byte is treated
                    as a controller command.  Devices attached to the
                    8042 should be disabled before issuing commands that
                    return data since data in the output register will
                    be overwritten.
        60h  read   8042 output register (should only be read if Bit 0 of
                    status port is set to 1)
        60h  write  8042 data register.  Data should only be written if
                    Bit 1 of the status register is zero (register is empty).
                    When this port is written Bit 3 of the status register
                    is set to zero and the byte is treated as a data.  The
                    8042 uses this byte if it's expecting data for a previous
                    command, otherwise the data is written directly to the
                    keyboard.

         8042 Commands Related to PC Systems  (Port 64h)

             Command                    Description

                20   Read 8042 Command Byte: current 8042 command byte is placed
                     in port 60h.
                60   Write 8042 Command Byte: next data byte written to port 60h is
                     placed in 8042 command register.  Format:

             |7|6|5|4|3|2|1|0|  8042 Command Byte
              | | | | | | | +---- 1=enable output register full interrupt
              | | | | | | +----- should be 0
              | | | | | +------ 1=set status register system, 0=clear
              | | | | +------- 1=override keyboard inhibit, 0=allow inhibit
              | | | +-------- disable keyboard I/O by driving clock line low
              | | +--------- disable auxiliary device, drives clock line low
              | +---------- IBM scancode translation 0=AT, 1=PC/XT
              +----------- reserved, should be 0

                A4   Password Installed Test: returned data can be read
                     from port 60h;  FA=password installed, F1=no password
                A5   Load Security: bytes written to port 60h will be read
                     until a null (0) is found.
                A6   Enable Security: works only if a password is already loaded
                A7   Disable Auxiliary Interface: sets Bit 5 of command register
                     stopping auxiliary I/O by driving the clock line low
                A8   Enable Auxiliary Interface: clears Bit 5 of command register
                A9   Auxiliary Interface Test: clock and data lines are tested;
                     results placed at port 60h are listed below:

                       00  no error
                       01  keyboard clock line is stuck low
                       02  keyboard clock line is stuck high
                       03  keyboard data line is stuck low
                       04  keyboard data line is stuck high

                AA   Self Test: diagnostic result placed at port 60h, 55h=OK
                AB   Keyboard Interface Test:  clock and data lines are tested;
                     results placed at port 60h are listed above with command A9
                AC   Diagnostic Dump: sends 16 bytes of 8042's RAM, current input
                     port state, current output port state and 8042 program status
                     word to port 60h in scan-code format.
                AD   Disable Keyboard Interface: sets Bit 4 of command register
                     stopping keyboard I/O by driving the clock line low
                AE   Enable Keyboard Interface: clears Bit 4 of command register
                     enabling keyboard interface.
                C0   Read Input Port: data is read from its input port (which is
                     inaccessible to the data bus) and written to output register
                     at port 60h;  output register should be empty before call.

               |7|6|5|4|3-0|  8042 Input Port
                | | | | +---- undefined
                | | | +----- 1=enable 2nd 256K of motherboard RAM, 0=disable
                | | +------ 1=manufacturing jumper not installed, 0=installed
                | +------- 1=primary display is MDA, 0=primary display is CGA
                +-------- 1=keyboard not inhibited, 0=keyboard inhibited

                C1   Poll Input Port Low Bits: Bits 0-3 of port 1 placed in
                     status Bits 4-7
                C2   Poll Input Port High Bits: Bits 4-7 of port 1 placed in
                     status Bits 4-7
                D0   Read Output Port: data is read from 8042 output port (which is
                     inaccessible to the data bus) and placed in output register;
                     the output register should be empty.  (see command D1 below)
                D1   Write Output Port: next byte written to port 60h is placed in
                     the 8042 output port (which is inaccessible to the data bus)

                |7|6|5|4|3|2|1|0|  8042 Output Port
                 | | | | | | | +---- system reset line
                 | | | | | | +----- gate A20
                 | | | | +-�------ undefined
                 | | | +--------- output buffer full
                 | | +---------- input buffer empty
                 | +----------- keyboard clock (output)
                 +------------ keyboard data (output)

                D2   Write Keyboard Output Register: on PS/2 systems the next data
                     byte written to port 60h input register is written to port 60h
                     output register as if initiated by a device; invokes interrupt
                     if enabled
                D3   Write Auxiliary Output Register: on PS/2 systems the next data
                     byte written to port 60h input register is written to port 60h
                     output register as if initiated by a device; invokes interrupt
                     if enabled
                D4   Write Auxiliary Device: on PS/2 systems the next data byte
                     written to input register a port at 60h is sent to the
                     auxiliary device
                E0   Read Test Inputs: 8042 reads its T0 and T1 inputs; data is
                     placed in output register;  Bit 0 is T0, Bit 1 is T1:

                |1|0|  Test Input Port Bits
                 | +---- keyboard clock
                 +----- keyboard data

                Fx   Pulse Output Port: Bits 0-3 of the 8042 output port can be
                     pulsed low for 6 �s;  Bits 0-3 of command indicate which
                     Bits should be pulsed; 0=pulse, 1=don't pulse; pulsing
                     Bit 0 results in CPU reset since it is connected to system
                     reset line.

               - PC systems previous to the AT use the 8255 PPI as a keyboard
                 controller and use the keyboard's internal 8048.
               - the keyboard's internal controller buffers up to 16 bytes of
                 make/break code information.  This is common among all PC systems
                 and shouldn't be confused with the (32 byte) keyboard buffer
                 maintained by the BIOS.
               - see  KEYBOARD COMMANDS for information on programming the
                 keyboards internal microprocessor

\end{verbatim}
\normalsize

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

                              INT 16 - Keyboard Scan Codes
                              ----------------------------

                      Key       Normal    Shifted   w/Ctrl    w/Alt

                       A         1E61      1E41      1E01      1E00
                       B         3062      3042      3002      3000
                       C         2E63      2E42      2E03      2E00
                       D         2064      2044      2004      2000
                       E         1265      1245      1205      1200
                       F         2166      2146      2106      2100
                       G         2267      2247      2207      2200
                       H         2368      2348      2308      2300
                       I         1769      1749      1709      1700
                       J         246A      244A      240A      2400
                       K         256B      254B      250B      2500
                       L         266C      264C      260C      2600
                       M         326D      324D      320D      3200
                       N         316E      314E      310E      3100
                       O         186F      184F      180F      1800
                       P         1970      1950      1910      1900
                       Q         1071      1051      1011      1000
                       R         1372      1352      1312      1300
                       S         1F73      1F53      1F13      1F00
                       T         1474      1454      1414      1400
                       U         1675      1655      1615      1600
                       V         2F76      2F56      2F16      2F00
                       W         1177      1157      1117      1100
                       X         2D78      2D58      2D18      2D00
                       Y         1579      1559      1519      1500
                       Z         2C7A      2C5A      2C1A      2C00

                      Key       Normal    Shifted   w/Ctrl    w/Alt

                       1         0231      0221                7800
                       2         0332      0340      0300      7900
                       3         0433      0423                7A00
                       4         0534      0524                7B00
                       5         0635      0625                7C00
                       6         0736      075E      071E      7D00
                       7         0837      0826                7E00
                       8         0938      092A                7F00
                       9         0A39      0A28                8000
                       0         0B30      0B29                8100

                      Key       Normal    Shifted   w/Ctrl    w/Alt

                       -         0C2D      0C5F      0C1F      8200
                       =         0D3D      0D2B                8300
                       [         1A5B      1A7B      1A1B      1A00
                       ]         1B5D      1B7D      1B1D      1B00
                       ;         273B      273A                2700
                       '         2827      2822
                       `         2960      297E
                       \         2B5C      2B7C      2B1C      2600 (same as Alt L)
                       ,         332C      333C
                       .         342E      343E
                       /         352F      353F

                      Key      Normal    Shifted   w/Ctrl    w/Alt

                       F1        3B00      5400      5E00      6800
                       F2        3C00      5500      5F00      6900
                       F3        3D00      5600      6000      6A00
                       F4        3E00      5700      6100      6B00
                       F5        3F00      5800      6200      6C00
                       F6        4000      5900      6300      6D00
                       F7        4100      5A00      6400      6E00
                       F8        4200      5B00      6500      6F00
                       F9        4300      5C00      6600      7000
                       F10       4400      5D00      6700      7100
                       F11       8500      8700      8900      8B00
                       F12       8600      8800      8A00      8C00

                       Key         Normal    Shifted   w/Ctrl    w/Alt

                       BackSpace    0E08      0E08      0E7F     0E00
                       Del          5300      532E      9300     A300
                       Down Arrow   5000      5032      9100     A000
                       End          4F00      4F31      7500     9F00
                       Enter        1C0D      1C0D      1C0A     A600
                       Esc          011B      011B      011B     0100
                       Home         4700      4737      7700     9700
                       Ins          5200      5230      9200     A200
                       Keypad 5                4C35     8F00
                       Keypad *     372A                9600     3700
                       Keypad -     4A2D      4A2D      8E00     4A00
                       Keypad +     4E2B      4E2B               4E00
                       Keypad /     352F      352F      9500     A400
                       Left Arrow   4B00      4B34      7300     9B00
                       PgDn         5100      5133      7600     A100
                       PgUp         4900      4939      8400     9900
                       PrtSc                            7200
                       Right Arrow  4D00      4D36      7400     9D00
                       SpaceBar     3920      3920      3920     3920
                       Tab          0F09      0F00      9400     A500
                       Up Arrow     4800      4838      8D00     9800


               - Some key combinations are not available on all systems.  The PS/2
                 includes many that aren't available on the PC, XT and AT.
               - To retrieve the character from a scan code logical AND the word
                 with 0x00FF.
               - see  INT 16  MAKE CODES~

\end{verbatim}
\normalsize

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

LS322. No documentado.

\end{verbatim}
\normalsize

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

S74. No documentado.

\end{verbatim}
\normalsize

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

                   PC, XT and AT 8 bit BUS Structure
                   ---------------------------------

                               +--------+
                       Ground -|B1    A1|- -I/O CH CHK (NMI)
                   +Reset DRV -|B2    A2|- +Data 7
                          +5V -|B3    A3|- +Data 6
                        +IRQ2 -|B4    A4|- +Data 5
                          -5V -|B5    A5|- +Data 4
                        +DRQ2 -|B6    A6|- +Data 3
                         -12V -|B7    A7|- +Data 2
                  -CARD SLCTD -|B8    A8|- +Data 1
                         +12V -|B9    A9|- +Data 0
                       Ground -|B10  A10|- +I/O CH RDY
                        -MEMW -|B11  A11|- +AEN
                        -MEMR -|B12  A12|- +Address 19
                         -IOW -|B13  A13|- +Address 18
                         -IOR -|B14  A14|- +Address 17
                       -DACK3 -|B15  A15|- +Address 16
                        +DRQ3 -|B16  A16|- +Address 15
                       -DACK1 -|B17  A17|- +Address 14
                        +DRQ1 -|B18  A18|- +Address 13
                -DACK0 (MREF) -|B19  A19|- +Address 12
                          CLK -|B20  A20|- +Address 11
                        +IRQ7 -|B21  A21|- +Address 10
                        +IRQ6 -|B22  A22|- +Address 9
                        +IRQ5 -|B23  A23|- +Address 8
                        +IRQ4 -|B24  A24|- +Address 7
                        +IRQ3 -|B25  A25|- +Address 6
                       -DACK2 -|B26  A26|- +Address 5
                          +TC -|B27  A27|- +Address 4
                         +ALE -|B28  A28|- +Address 3
                          +5V -|B29  A29|- +Address 2
                         +OSC -|B30  A30|- +Address 1
                       Ground -|B31  A31|- +Address 0
                               +--------+

                        AT 16 Bit BUS Extension
                        -----------------------

                               +--------+
                    -MEM CS16 -|D1    C1|- SBHE
                    -I/O CS16 -|D2    C2|- Address 23
                        IRQ10 -|D3    C3|- Address 22
                        IRQ11 -|D4    C4|- Address 21
                        IRQ12 -|D5    C2|- Address 20
                        IRQ15 -|D6    C6|- Address 19
                        IRQ14 -|D7    C7|- Address 18
                       -DACK0 -|D8    C8|- Address 17
                         DRQ0 -|D9    C9|- -MEMR
                       -DACK5 -|D10  C10|- -MEMW
                         DRQ5 -|D11  C11|- Data 8
                       -DACK6 -|D12  C12|- Data 9
                         DRQ6 -|D13  C13|- Data 10
                       -DACK7 -|D14  C24|- Data 11
                         DRQ7 -|D15  C15|- Data 12
                          +5V -|D16  C16|- Data 13
                      -Master -|D17  C17|- Data 14
                       Ground -|D18  C18|- Data 15
                               +--------+

               - pin numbering starts from the rear of the machine


               Signal                         Description
               ------------ ---------------------------------------------------------
               A0-A19       Address Bits 0-19 allow access to 1Mb memory and 64K of
                            port addresses.
               A17-A23      Address Bits 17-23 allow access from 1Mb memory to 16Mb
               AEN          Address Enable; When active the DMA controller has
                            control of the Address and Data BUS as well as the
                            MEMR/MEMW lines. When inactive the CPU has control of
                            these lines
               ALE          Address Latch Enable (output); used to latch addresses
                            from the CPU.  Forced active during DMA cycles.
               CARD SLCTD   Card Selected; activated by cards in the XT's slot 8
               CLK          System clock signal (actual BUS speed)
               D0-D7        Data bits 0-7 for I/O to memory and I/O
               DACK0-DACK3  DMA Acknowledge for channels 0-3; used by the controller
                            to acknowledge DMA requested.  DACK0 is used for memory
                            refresh (MREF)
               DRQ0-DRQ3    DMA Request 0-3; used by peripherals to get service from
                            the DMA controller;  Held active until the corresponding
                            DACKx signal becomes active.
               I/O CH CHK   I/O Channel Check; Generates a Non Maskable Interrupt
               I/O CH RDY   I/O Channel Ready; pulled inactive my memory or I/O
                            devices to lengthen memory or I/O cycles.  Usually used
                            by slower devices to add wait states.  Should not be
                            held inactive for more than 17 cycles.
               I/O CS16     I/O Chip Select 16 Bit; 16 bit I/O cycle
               IOR          I/O Read; instructs an I/O device to drive its data
                            onto the system BUS
               IOW          I/O Write; instructs an I/O device to read data from
                            the BUS
               IRQ2-IRQ7    Interrupt Requests 2-7; signals the CPU that an I/O
                     device needs service  (see 8259)
               MASTER       Used with DRQ to gain control of system
               MEM CS16     Memory Chip Select 16 Bit; 16 Bit memory cycle
               MEMR         Memory Read; this signal is driven by the CPU or DMA
                            controller and instructs memory to drive its data onto
                            the system BUS.  Present on both PC and AT extension BUS
               MEMW         Memory Write;  this signal is driven by the CPU or DMA
                            controller and instructs memory to read and store data
                            from the system BUS.  Present on both PC and AT
                            extension BUS
               OSC          Oscillator; 14.31818 MHz clock (70ns period); 50% duty
                            cycle
               RESET DRV    Reset Drive; used to reset system logic
               SBHE         System BUS High Enable; activates data bits 8-15 on AT
                            extension BUS
               TC           Terminal Count; pulses when the terminal count for a
                            DMA channel is reached

        - all ISA BUS signals use standard TTL levels
        - input and output are relative to the CPU

\end{verbatim}
\normalsize

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

        PC ports Description
        -------- ------------------------------
        000-00F  8237 DMA controller
                 000 Channel 0 address register
                 001 Channel 0 word count
                 002 Channel 1 address register
                 003 Channel 1 word count
                 004 Channel 2 address register
                 005 Channel 2 word count
                 006 Channel 3 address register
                 007 Channel 3 word count
                 008 Status/command register
                 009 Request register
                 00A Mask register
                 00B Mode register
                 00C Clear MSB/LSB flip flop
                 00D Master clear temp register
                 00E Clear mask register
                 00F Multiple mask register
        010-01F  8237 DMA Controller (PS/2 model 60 & 80), reserved (AT)
        020-02F  8259A Master Programmable Interrupt Controller
                 020 8259 Command port
                 021 8259 Interrupt mask register
        030-03F  8259A Slave Programmable Interrupt Controller (AT,PS/2)
        040-05F  8253 or 8254 Programmable Interval Timer
                 040 8253 channel 0, counter divisor
                 041 8253 channel 1, RAM refresh counter
                 042 8253 channel 2, Cassette and speaker functions
                 043 8253 mode control
                 044 8254 PS/2 extended timer
                 047 8254 Channel 3 control byte
        060-067  8255 Programmable Peripheral Interface  (PC,XT, PCjr)
                 060 8255 Port A keyboard input/output buffer (output PCjr)
                 061 8255 Port B output
                 062 8255 Port C input
                 063 8255 Command/Mode control register
        060-06F  8042 Keyboard Controller  (AT,PS/2)
                 060 8042 Keyboard input/output buffer register
                 061 8042 system control port (for compatability with 8255)
                 064 8042 Keyboard command/status register
        070      CMOS RAM/RTC, also NMI enable/disable (AT,PS/2)
        071      CMOS RAM data  (AT,PS/2)
        080      Manufacturer systems checkpoint port (used during POST)
        080-090  DMA Page Registers
                 081 High order 4 bits of DMA channel 2 address
                 082 High order 4 bits of DMA channel 3 address
                 083 High order 4 bits of DMA channel 1 address
        090-097  POS/Programmable Option Select  (PS/2)
                 090 Central arbitration control Port
                 091 Card selection feedback
                 092 System control and status register
                 094 System board enable/setup register
                 095 Reserved
                 096 Adapter enable/setup register
                 097 Reserved
        0A0      NMI Mask Register (PC,XT) (write 80h to enable NMI, 00h disable)
        0A0-0BF  Second 8259 Programmable Interrupt Controller (AT, PS/2)
                 0A0 Second 8259 Command port
                 0A1 Second 8259 Interrupt mask register
        0C0      TI SN76496 Programmable Tone/Noise Generator (PCjr)
        0C0-0DF  8237 DMA controller 2 (AT)
                 0C2 DMA channel 3 selector  (see ports 6 & 82)
        0E0-0EF  Reserved
        0F0-0FF  Math coprocessor (AT, PS/2)
        0F0-0F5  PCjr Disk Controller
                 0F0 Disk Controller
                 0F2 Disk Controller control port
                 0F4 Disk Controller status register
                 0F5 Disk Controller data port
        0F8-0FF  Reserved for future microprocessor extensions
        100-10F  POS Programmable Option Select (PS/2)
                 100 POS Register 0, Adapter ID byte (LSB)
                 101 POS Register 1, Adapter ID byte (MSB)
                 102 POS Register 2, Option select data byte 1. Bit 0 is card enable (CDEN)
                 103 POS Register 3, Option select data byte 2
                 104 POS Register 4, Option select data byte 3
                 105 POS Register 5, Option select data byte 4 .Bit 7 is (-CHCK). Bit 6 is reserved.
                 106 POS Register 6, subaddress extension (LSB)
                 107 POS Register 7, subaddress extension (MSB)
        110-1EF  System I/O channel
        170-17F  Fixed disk 1 (AT)
                 170 disk 1 data
                 171 disk 1 error
                 172 disk 1 sector count
                 173 disk 1 sector number
                 174 disk 1 cylinder low
                 175 disk 1 cylinder high
                 176 disk 1 drive/head
                 177 disk 1 status
        1F0-1FF  Fixed disk 0 (AT)
                 1F0 disk 0 data
                 1F1 disk 0 error
                 1F2 disk 0 sector count
                 1F3 disk 0 sector number
                 1F4 disk 0 cylinder low
                 1F5 disk 0 cylinder high
                 1F6 disk 0 drive/head
                 1F7 disk 0 status
        200-20F  Game Adapter
        210-217  Expansion Card Ports (XT)
                 210 Write: latch expansion bus data
                     read:  verify expansion bus data
                 211 Write: clear wait,test latch
                     Read:  MSB of data address
                 212 Read:  LSB of data address
                 213 Write: 0=enable, 1=/disable expansion unit
        214-215  Receiver Card Ports
                 214 write: latch data, read: data
                 215 read:  MSB of address, next read: LSB of address
        21F      Reserved
        220-26F  Reserved for I/O channel
        270-27F  Third parallel port
                 278 data port
                 279 status port
                 27A control port
        280-2AF  Reserved for I/O channel
        2A2-2A3  MSM58321RS clock
        2B0-2DF  Alternate EGA, or 3270 PC video (XT, AT)
        2E0      Alternate EGA/VGA
        2E1      GPIB Adapter  (AT)
        2E2-2E3  Data acquisition adapter (AT)
        2E8-2EF  COM4 non PS/2 UART (Reserved by IBM)
        2F0-2F7  Reserved
        2F8-2FF  COM2 Second Asynchronous Adapter
                        Primary Asynchronous Adapter for PCjr
        300-31F  Prototype Experimentation Card (except PCjr)
                        Periscope hardware debugger
        320-32F  Hard Disk Controller  (XT)
                 320 Read from/Write to controller
                 321 Read: Controller Status, Write: controller reset
                 322 Write: generate controller select pulse
                 323 Write: Pattern to DMA and interrupt mask register (see ports 0F,21,C2)
                 324 disk attention/status
        330-33F  Reserved for XT/370
        340-35F  Reserved for I/O channel
        360-36F  PC Network
        370-377  Floppy disk controller (except PCjr)
                 372 Diskette digital output
                 374 Diskette controller status
                 375 Diskette controller data
                 376 Diskette controller data
                 377 Diskette digital input
        378-37F  Second Parallel Printer. First Parallel Printer
                 378 data port
                 379 status port
                 37A control port
        380-38F  Secondary Binary Synchronous Data Link Control (SDLC) adapter
                 380 On board 8255 port A, internal/external sense
                 381 On board 8255 port B, external modem interface
                 382 On board 8255 port C, internal control and gating
                 383 On board 8255 mode register
                 384 On board 8253 channel square wave generator
                 385 On board 8253 channel 1 inactivity time-out
                 386 On board 8253 channel 2 inactivity time-out
                 387 On board 8253 mode register
                 388 On board 8273 read: status; Write: Command
                 389 On board 8273 write: parameter; read: response
                 38A On board 8273 transmit interrupt status
                 38B On board 8273 receiver interrupt status
                 38C On board 8273 data
        390-39F  Cluster Adapter
        3A0-3AF  Primary Binary Synchronous Data Link Control (SDLC) adapter
                 3A0 On board 8255 port A, internal/external sense
                 3A1 On board 8255 port B, external modem interface
                 3A2 On board 8255 port C, internal control and gating
                 3A3 On board 8255 mode register
                 3A4 On board 8253 counter 0 unused
                 3A5 On board 8253 counter 1 inactivity time-outs
                 3A6 On board 8253 counter 2 inactivity time-outs
                 3A7 On board 8253 mode register
                 3A8 On board 8251 data
                 3A9 On board 8251 command/mode/status register
        3B0-3BF  Monochrome Display Adapter (write only)
                 3B0 port address decodes to 3B4
                 3B1 port address decodes to 3B5
                 3B2 port address decodes to 3B4
                 3B3 port address decodes to 3B5
                 3B4 6845 index register, selects which register [0-11h]
                     is to be accessed through port 3B5
                 3B5 6845 data register [0-11h] selected by port 3B4,
                     registers 0C-0F may be read.  If a read occurs without
                     the adapter installed, FFh is returned.
                 3B6 port address decodes to 3B4
                 3B7 port address decodes to 3B5
                 3B8 6845 Mode control register
                 3B9 reserved for color select register on color adapter
                 3BA status register (read only)
                 3BB reserved for light pen strobe reset
        3BC-3BF  Primary Parallel Printer Adapter
                 3BC parallel 1, data port
                 3BD parallel 1, status port
                 3BE parallel 1, control port
        3C0-3CF  EGA/VGA
                 3C0 VGA attribute and sequencer register
                 3C1 Other video attributes
                 3C2 EGA, VGA, CGA input status 0
                 3C3 Video subsystem enable
                 3C4 CGA, EGA, VGA sequencer index
                 3C5 CGA, EGA, VGA sequencer
                 3C6 VGA video DAC PEL mask
                 3C7 VGA video DAC state
                 3C8 VGA video DAC PEL address
                 3C9 VGA video DAC
                 3CA VGA graphics 2 position
                 3CC VGA graphics 1 position
                 3CD VGA feature control
                 3CE VGA graphics index
                 3CF Other VGA graphics
        3D0-3DF  Color Graphics Monitor Adapter (ports 3D0-3DB are write only)
                 3D0 port address decodes to 3D4
                 3D1 port address decodes to 3D5
                 3D2 port address decodes to 3D4
                 3D3 port address decodes to 3D5
                 3D4 6845 index register, selects which register [0-11h]
                     is to be accessed through port 3D5
                 3D5 6845 data register [0-11h] selected by port 3D4,
                     registers 0C-0F may be read.  If a read occurs without
                     the adapter installed, FFh is returned.
                 3D6 port address decodes to 3D4
                 3D7 port address decodes to 3D5
                 3D8 6845 Mode control register (CGA, EGA, VGA, except PCjr)
                 3D9 color select palette register (CGA, EGA, VGA)
                 3DA status register (read only)
                 3DB Clear light pen latch (any write)
                 3DC Preset Light pen latch
                 3DF CRT/CPU page register (PCjr only)
        3E8-3EF  COM3 non PS/2 UART (Reserved by IBM)
        3F0-3F7  Floppy disk controller (except PCjr)
                 3F0 Diskette controller status A
                 3F1 Diskette controller status B
                 3F2 controller control port
                 3F4 controller status register
                 3F5 data register (write 1-9 byte command)
                 3F6 Diskette controller data
                 3F7 Diskette digital input
                 3F8-3FF  COM1 Primary Asynchronous Adapter
      3220-3227  PS/2 COM3
      3228-322F  PS/2 COM4
      4220-4227  PS/2 COM5
      4228-422F  PS/2 COM6
      5220-5227  PS/2 COM7
      5228-522F  PS/2 COM8

\end{verbatim}
\normalsize

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

8255A. No documentado.

\end{verbatim}
\normalsize

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

                         Keyboard Flags Bytes 0 and 1
                         ----------------------------

                |7|6|5|4|3|2|1|0|  40:17  Keyboard Flags Byte 0
                 | | | | | | | +---- right shift key depressed
                 | | | | | | +----- left shift key depressed
                 | | | | | +------ CTRL key depressed
                 | | | | +------- ALT key depressed
                 | | | +-------- scroll-lock is active
                 | | +--------- num-lock is active
                 | +---------- caps-lock is active
                 +----------- insert is active

                |7|6|5|4|3|2|1|0|  40:18  Keyboard Flags Byte 1
                 | | | | | | | +---- left CTRL key depressed
                 | | | | | | +----- left ALT key depressed
                 | | | | | +------ system key depressed and held
                 | | | | +------- suspend key has been toggled
                 | | | +-------- scroll lock key is depressed
                 | | +--------- num-lock key is depressed
                 | +---------- caps-lock key is depressed
                 +----------- insert key is depressed

                         Keyboard Flags Bytes 2 and 3
                         ----------------------------

                |7|6|5|4|3|2|1|0|  40:97  LED Indicator Flags
                 | | | | | | | +---- scroll lock indicator
                 | | | | | | +----- num-lock indicator
                 | | | | | +------ caps-lock indicator
                 | | | | +------- circus system indicator
                 | | | +-------- ACK received
                 | | +--------- re-send received flag
                 | +---------- mode indicator update
                 +----------- keyboard transmit error flag

                |7|6|5|4|3|2|1|0|  40:96  Keyboard Mode/Type
                 | | | | | | | +---- last code was the E1 hidden code
                 | | | | | | +----- last code was the E0 hidden code
                 | | | | | +------ right CTRL key depressed
                 | | | | +------- right ALT key depressed
                 | | | +-------- 101/102 enhanced keyboard installed
                 | | +--------- force num-lock if Rd ID & KBX
                 | +---------- last char was first ID char
                 +----------- read ID in process

\end{verbatim}
\normalsize

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

                     DTA - Disk Transfer Area  (partially undocumented)
                     ------------------------

               DTA contains data, of which the first 21 bytes (00-15h) are known
               as being "reserved for DOS use on subsequent find next calls"

             Offset Size          Description
             ------ ----       ---------------------------------------
               00   byte       attribute of search (undocumented)
               01   byte       drive used in search  (undocumented)
               02  11bytes     search name used (undocumented)
               0D   word       directory entry number (0 based, DOS 3.x+, undoc.)
               0F   word       starting cluster number of current directory
                               zero for root directory (DOS 3.x+, undocumented)
               11   word       reserved (undocumented)
               13   word       starting cluster number of current directory
                               zero for root directory (DOS 2.x+, undocumented)
               15   byte       attribute of matching file
               16   word       file time  (see FILE ATTRIBUTES)
               18   word       file date  (see FILE ATTRIBUTES)
               1A   word       file size
               1E 13bytes      ASCIIZ filename and extension in the form NAME.EXT
                               with blanks stripped


               - fields of DTA change dependent upon function call in progress
               - the DTA cannot span a 64K segment boundary
               - for compatibility with CP/M the default DTA is at offset 80h
                 in the PSP;  this area is also used for the command tail. To
                 avoid collision, set another DTA (INT 21,1A) or preserve the
                 command tail before using FCB function calls

               - see  INT 21,4E  INT 21,1A  INT 21,2F

\end{verbatim}
\normalsize

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

          DOS Undocumented Interrupts, Functions and Structures
          -----------------------------------------------------

         INT 15,20   PRINT.COM Critical Region Flag (DOS 3.x+)
         INT 21,1F   Get pointer to current drive parameter table
         INT 21,32   Get pointer to drive parameter table
         INT 21,34   Get address to DOS critical flag (INDOS flag)
         INT 21,37   Get/set switch char
         INT 21,4B   EXEC/Load and execute (Function 1 undocumented)
         INT 21,50   Set current process id (DOS 2.x)
         INT 21,51   Get current process id (DOS 2.x)
         INT 21,52   Get pointer to DOS "INVARS"
         INT 21,53   Generate drive parameter table
         INT 21,55   Create new PSP~
         INT 21,58   Get/set memory allocation strategy (DOS 3.x+)
         INT 21,5D   Critical error information (DOS 3.x+)
         INT 21,60   Get fully qualified file name (DOS 3.x+)
         INT 21,64   Set device driver look ahead  (DOS 3.3+)
         INT 21,69   Get/set disk serial number (DOS 4.0+)
         INT 21,F8   Set INT 21 OEM handler
         INT 28      DOS idle loop/scheduler
         INT 29      Fast character output
         INT 2E      Execute command using base level COMMAND.COM

                          BCB        Batch Control Block
                          DTA        Disk Transfer Area  (partially undocumented)
                          MCB        Memory Control Block
                          PSP        Program Segment Prefix Layout (partially undocumented)
                          SFT        System File Table

               - the above items are undocumented with respect to IBM/Microsoft
                 and should be not be used unless one fully understands the
                 repercussions
               - several functions are version dependant and OEM specific

\end{verbatim}
\normalsize

\section*{Ap\'endice L. El prefijo de segmento de programa (PSP).}

Cuando el DOS carga un programa, aparta un bloque de memoria de
256 bytes para el programa: el prefjo del segmento del programa (psp).
El PSP contiene informaci\'on de diversa \'{\i}ndole que el DOS \'utiliza para
ayudar al funci\'onamiento del programa. Hay un PSP asociado a cada
programa del DOS, sin importar el lenguaje de programaci\'on en el
que est\'a escrito. Sin embargo, para prop\'ositos de programaci\'on, la
informaci\'on almacenada en el PSP es mas relevante para programas
que esten escritos en lenguaje ensamblador que para programas que
est\'en escritos en lenguajes de alto nivel. Esto se debe a que, con los
lenguajes de alto nivel, el propio lenguaje est\'a, normalmente, a cargo
del entorno de trabajo del programa, \'utilizaci\'on de la memoria y
control de ficheros toda la informaci\'on que concierne al PSP. Por
tanto, usted normalmente podra hacer buen uso del PSP solo si su
programa est\'a basado en lenguaje ensamblador.

Antes de que describamos los diferentes elementos del PSP necesitaremos
ver las relaciones entre el PSP y el programa que soporta.

El DOS siempre construye el PSP del programa en memoria justo
por encima del \'area de memoria asignada al propio programa. Cuando el
programa recibe el control por parte del DOS, los registros de
segmento DS y ES apuntan al comienzo del PSP. Debido a que
algunas veces necesita localizar informaci\'on del PSP, el DOS mantine
una copia del valor del segmento del PSP internamente.

La mejor manera de explicar como trabajan juntos el PSP y el
programa es saltar a la propia estructura interna del PSP. Revelaremos
el prop\'osito y el uso potencial de cada elemento a medida que los
vayamos explicando.

Como descubrir\'a pronto, el PSP contiene una mezcla confusa de
elementos. La base y la historia del DOS tiran de \'el
en diferentes direcci\'ones (hacia atras, hacia el primigenio sistema
CPM, y hacia adelante, hacia los entornos operativos del tipo UNlX.
Como resultado, el PSP contiene elementos que sirven a diferentes
prop\'ositos y que est\'an orientados a diferentes metodos de programaci\'on.
Trataremos los elementos en el orden en que vayan apareciendo.

\begin{verbatim}

Desplazamiento  Longitud
 Hex   Dec       (bytes)           Descripcion
----- -----     ---------   ---------------------------------------------------
 OOH     O           2      instruccion INT 20H
 02H     2           2      Tamanho de la memoria (en parrafos)
 04H     4           1      (Reservado; normalmente O)
 05H     5           5      Llamada al planificador de funciones del DOS
 0AH    10           4      direccion de la interrupcion 0x22 (Terminar)
 0EH     4           4      direccion de la interrupcion 0x23 (Ctrl-C)
 12H    18           4      direccion de la interrupcion 0x24 (Errores criticos)
 16H    22          22      (Reservado)
 2CH    44           2      direccion del segmento de entorno
 2EH    46          34      Reservado
 50H    80           3      instrucciones INT 0x21, RETF
 53H    83           9      (Reservado)
 5CH    92          16      FCB # I
 6CH   108          20      FCB # 2
 80H   128         128      parametros de la l\'{\i}nea de comandos y \'area de
                            transferencia de disco (DTA) por defecto

\end{verbatim}

El campo en el desplazamiento 0x00 (2 bytes) contiene los bytes
0xCD y 0x20, la instrucci\'on de la interrupci\'on 0x20. Como hemos visto
esta interrupci\'on es s\'olo una de las diversas formas estandar de terminar
un programa. Esta instrucci\'on est\'a situada al comienzo del PSP (en el
desplazamiento 0x00), as\'{\i} que un programa puede finalizar por si mismo
saltando a esta posici\'on cuando el registro CS apunte al PSP. Como puede ver
est\'a no es la manera mas inteligente en la que un programa puede finalizar;
siempre es mejor salir a traves de la llamada apropiada a una interrupci\'on o
funci\'on. Este curioso metodo de terminaci\'on de programa es ya una
reliquia de los d\'{\i}as en que la compatibilidad con el CP/M era importante.

El campo en el desplazamiento 0x02 (2 bytes) contiene la direcci\'on
del segmento del \'ultimo p\'arrafo de la memoria asignada al programa
El DOS, normalmente, carga un programa en el primer \'area de
memoria suficientemente grande para contenerlo. Un programa puede
\'utilizar este campo para determinar el tama\~no real de la memoria que
tiene asignada.

En la pr\'actica, hay una manera mejor de determinar la cantidad de
memoria asignada a un programa. La funci\'on 0x4A de la interrupci\'on
0x21 puede devolver el tama\~no de cualquier bloque de memoria, no
s\'olo del bloque en el cual el programa est\'a cargado.

El campo en el desplazamiento 0x05 (5 bytes) contiene una llamada
externa a la funci\'on planificadora del DOS, la rutina interna del DOS
que examina el n\'umero de la funci\'on que se le pasa y ejecuta la rutina
de servicio correspondiente. Este campo tambi\'en es un remanente de
los d\'{\i}as en que la compatibilidad con el CP/M era importante para los
programadores en DOS. Un programa puede hacer una llamada
cercana al desplazamiento 0x05 del PSP con un n\'umero de funci\'on en
el registro CL y obtener el mismo resultado que si hubiese cargado
AH con el n\'umero de la funci\'on y ejecutado la interrupci\'on 0x21.
No es necesario decir que esta t\'ecnica no es muy \'util en el mundo
real de los programas del DOS.

Los campos en los desplazamientos 0x0A, 0x0E y 0x12 (4 bytes cada
uno) contienen la direcci\'on segmentada de las rutinas de tratamiento
por defecto de las interrupci\'ones 0x22 (terminar), 0x23 (Ctrl-C) y 0x24
(error cr\'{\i}tico). Estas direcciones est\'an almacenadas en el PSP para su
conveniencia. Si sustituye una de las rutinas de tratamiento por defecto
del DOS por una hecha a medida, puede restaurar la rutina original
copiando su direcci\'on desde el PSP a su correspondiente vector de
interrupci\'on.

En las versiones 2.0 y posteriores del DOS, el campo en el desplazamiento
0x2C (2 bytes) contiene la direcci\'on del p\'arrafo del bloque de
entorno del programa. El bloque de entorno contiene una lista de
cadenas ASCIIZ (cadenas de caracteres ASCII terminadas cada una en
un byte cero) que definen varias clases de informaci\'on. El final del
bloque de entorno est\'a marcado por una cadena de longitud cero (un
solo byte cero) donde se esperar\'{\i}a encontrar el primer byte de la
siguiente cadena. Los bloques de entorno que comienzan con una
cadena de longitud cero no contienen ninguna cadena.

Cada cadena de entorno es de la forma NOMBRE = valor, donde
NOMBRE est\'a en mayusculas con cualquier longitud razonable y
valor puede ser casi cualquier cosa. El entorno, de esta forma, contiene
una lista de variables globales, cada una de las cuales contiene
informaci\'on que su programa puede ser capaz de utilizar. Por ejemplo, si el
bloque de entorno contiene la variable de entorno PATH (esto es, una
cadena que comienza con PATH=), cualquier programa, incluyendo
el propio DOS, puede examinar su bloque de entorno para determinar
en que subdirectorios buscar los ficheros ejecutables (y en que orden).
De esta manera, el bloque de entorno proporciona una forma de pasar
informaci\'on a los programas que lo examinen. (Puede cambiar el
contenido del bloque de entorno \'utilizando el comando SET del
DOS.)

El DOS hace una copia del bloque de entorno cada vez que carga
un programa para ser ejecutado, y pone la direcci\'on del p\'arrafo
(segmento) de la copia en el PSP del programa. Para obtener la
informaci\'on del bloque de entorno, un programa debe obtener primero su
segmento del PSP, y despues examinar cada una de las cadenas
terminadas en cero. Algunos lenguajes de alto nivel contienen ciertas
funciones que hacen este trabajo por usted. Por ejemplo, en C, la
funci\'on de libreria getenv( ) hace todo el trabajo.

Muchos programas sofisticados del DOS conf\'{\i}an en la informaci\'on
del bloque de entorno. tambi\'en, el concepto de entorno se encuentra
en otros potentes sistemas operativos, incluidos el UNIX y el OS/2.
Cada vez que necesite pasar informaci\'on configurable por el usuario a
un programa, le recomendamos especialmente que utilice el bloque de
entorno.

El campo en el desplazamiento 0x50 contiene dos instrucci\'ones
ejecutables del 8086: INT 0x21 y RETF (far return).

Esta es otra posibilidad que le permite llamar a funci\'ones del DOS
indirectamente de alguna manera. Para utilizar esta caracter\'{\i}stica
establezca todo lo necesario para llamar a una funci\'on de la interrupcion
0x21 (seleccionando la funci\'on en AL, etc.). Despues, en vez de ejecutar
perfectamente, una interrupci\'on 0x21 (una instrucci\'on de 2
bytes), haga una llamada lejana al desplazamiento 0x50 del PSP (una
instrucci\'on de 5 bytes).

Podr\'{\i}a esperarse que esta caracter\'{\i}stica fuera otra reminiscencia del
pasado, un fragmento de la compatibilidad con el CP/M, pero realmente fue
introducida en la version 2.0 del DOS y no funci\'onara con
las versiones anteriores. Podr\'{\i}a encontrar que efectuar una llamada
lejana con desplazamiento 0x50 al PSP resulta \'util si intenta componer
la direcci\'on de un planificador de funci\'on diferente en su c\'odigo, pero,
en la mayor\'{\i}a de los casos, una INT 0x21 ser\'a suficiente.

Los campos en los desplazamientos 5CH y 6CH soportan un modo
de procesar ficheros pasado de moda, \'utilizando los bloques de control
de fichero, o FCB. Los FCB pueden \'utilizarse para la entrada/salida
de ficheros en todas las versiones del DOS, pero su uso no tiene
sentido a partir de la version 2.0, donde un sistema mas moderno de
E/S de ficheros est\'a disponible a traves de la utilizacion de handles a
ficheros. Vease p\'agina 350\cite{Guia} para m\'as informaci\'on acerca de los
bloques de control de fichero, y p\'agina 360\cite{Guia} para m\'as informaci\'on
acerca de los handles de ficheros.

Este \'area del PSP fue disenada para hacerle la vida mas f\'acil a los
programas que reciben uno o dos nombres de fichero como par\'ametros. La idea
b\'asica, y pensamos que buena, es la de permitir al DOS
construir los FCB necesarios fuera de los dos primeros par\'ametros de
la l\'{\i}nea de comandos (los par\'ametros dados en la l\'{\i}nea de comandos
seguidos del nombre del programa). Si un programa necesita alguno
de los FCB, puede abrirlos y utilizarlos sin tener que decodificar los
par\'ametros de la l\'{\i}nea de comandos y construir su propio FCB.

Si \'utiliza esta caracter\'{\i}stica del PSP debe tener en cuenta tres
complicaciones posibles: primero, los dos FCB solapan el lugar donde
se pongan. Si un programa necesita solo el primero, bien; pero si
tambi\'en necesita el segundo FCB, uno o los dos deben moverse a
alg\'un otro sitio antes de \'utilizarse. Segundo, estos FCB pueden incluir
extensiones de FCB, un hecho olvidado en la mayor\'{\i}a de la documentaci\'on
del DOS sobre el PSP. Finalmente, si utiliza una funci\'on del
DOS que necesite un FCB extendido, debe tener el cuidado de copiar
los FCB por defecto a otro \'area de memoria donde las extensiones del
FCB no solapen otros datos del PSP.

Tenga presente que el uso de los FCB est\'a considerado obsoleto,
pero si quiere \'utilizarlos esta informaci\'on puede serle \'util.

El campo en el desplazamiento 0x80 sirve para dos prop\'ositos:
cuando el DOS construye por primera vez el PSP, llena este campo
con los par\'ametros de la l\'{\i}nea de comandos tecleados por el usuario
cuando este llamo al programa. La longitud de la l\'{\i}nea de comando
est\'a en el byte del desplazamiento 0x80. Una cadena que contiene los
par\'ametros de la l\'{\i}nea de comandos va a continuacion en el desplazamiento
0x81.

Esta cadena tiene algunas peculiaridades: no contiene el nombre
del programa que fue llamado. En vez de ello, comienza con el caracter
que va inmediatamente detras del nombre del programa, el cual es
generalmente un blanco. Los separadores, como los blancos o las
comas, no est\'an comprimidos. Si \'utiliza la l\'{\i}nea de comandos, tiene
que estar preparado para explorarla, reconociendo los separadores
estandar. Afortunadamente, los lenguajes de alto nivel proporcionan a
menudo funci\'ones que analizan los par\'ametros de la cadena de comandos
por usted. En C, por ejemplo, los valores argc y argv se pasan
a la rutina principal de arranque en todos los programas C. Estos dos
valores contienen el n\'umero de par\'ametros de la l\'{\i}nea de comandos y
la direcci\'on de una lista de los par\'ametros individuales. Normalmente
es m\'as f\'acil confiar en su lenguaje de programacion de alto nivel para
extraer los par\'ametros de la l\'{\i}nea de comandos del PSP que hacerlo
por si mismo en lenguaje ensamblador.

A partir de la version 2.0 del DOS, la l\'{\i}nea de comandos se
modifica de una manera particular: el DOS quita los par\'ametros de
redirecci\'on (como < o > ) y reconstruye la l\'{\i}nea de par\'ametros como si
esos elementos no estuvieran. Como resultado de esas dos operaciones
en la cadena de comandos, un programa no puede saber si su E/S
estandar est\'a siendo redireccionada ni su propio nombre.

El otro prop\'osito al que sirve el campo en el desplazamiento 0x80
del PSP concierne al \'area de transferencia de disco (DTA) por defecto.
Este \'area buffer por defecto es establecida por el DOS s\'olo en el caso
de que llame a un servicio que necesite el DTA y todav\'{\i}a no haya
configurado su propio buffer DTA.

\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}
