 LECCION 4:
 ----------


      ASM POR AESOFT. (leccin 4).
      ----------------------------

     - ENTRADA/SALIDA (COMUNICACION CON EL HARDWARE I).
     - INTERRUPCIONES (COMUNICACION CON EL HARDWARE II).
     - LA PILA DEL 8086.
      --------------------------------------------------------------------

     Hola a todos. En esta leccin vamos a tratar aspectos muy interesantes
     de la programacin del Pc, interrupciones, puertos, etc.
     Espero que tengais claro lo del error que os comentaba en la leccin 1,
     acerca de los buses. Si no es as, a qu esperais para preguntar...
     Bueno, seguimos con lo nuevo:


     - ENTRADA/SALIDA (COMUNICACION CON EL HARDWARE I).
     ------------------------------------------------
     La comunicacin entre un programa y el hardware, es decir los chips de
     apoyo y las tarjetas de ampliacin, se efecta mediante los llamados
     Ports (puertos, en castellano). Estos puertos son zonas de memoria
     de 1 o 2 bytes de tamao, en las cuales se depositan los datos que van
     a ser utilizados por los chips o tarjetas, y tambin se depositan los
     datos que devuelven estos chips o tarjetas al procesador.

     En el Pc, existe una zona de memoria de 64 Ks, ajena a la memoria
     principal, dedicada a los puertos. Es decir, estos 64 Ks de memoria
     no tienen nada que ver con la memoria disponible para los programas.

     Para realizar los movimientos de datos entre puertos y procesador
     existen instrucciones especiales: IN y OUT.
     Tanto IN como OUT tienen dos formas de uso, las cuales utilizan el
     registro AL o AX para almacenar los datos a leer o escribir. La forma
     difiere en funcin de que se quiera acceder a un puerto menor de 256 o
     mayor.

     + Mtodo directo o esttico: corresponde cuando se quiere acceder a un
       puerto menor de 256.

       IN AL,10H  ---> lee un byte del puerto 10h
       IN AX,10H  ---> lee una palabra del puerto 10h
       OUT 0FFH,AL --> escribe el valor de AL en el puerto 0FFH

     + Mtodo inndirecto o dinmico: corresponde al caso de querer acceder a
       un puerto mayor de 256, para lo cual se utiliza el registro DX indicando
       el nmero de puerto.

       IN AL,DX  ----> lee un byte del puerto indicado por DX.
                      (Antes hemos tenido que introducir en DX la direccin
                      del puerto).
       OUT DX,AX ----> escribe la palabra contenida en AX en el puerto DX.

       Algunos ejemplos de puerto son:
       60H ----------> acepta entradas de teclado.
       61h ----------> controla el altavoz.
       3F0H-3F7H ----> Opera sobre la controladora de discos.


       En el PC cualquier subsistema, exceptuando la memoria, est controlado
       por el procesador a travs de los puertos.


     - INTERRUPCIONES (COMUNICACION CON EL HARDWARE II).
     ---------------------------------------------------
     Las interrupciones constituyen la forma en que la circuitera externa
     informa al microprocesador de que algo ha sucedido (como que se ha pulsado
     una tecla, por ejemplo) y solicita que se emprenda alguna accin.
     Pero no acaba ah su utilidad, ya que las interrupciones adems son
     el medio principal de comuniccin entre las funciones de la BIOS y el DOS.
     En este segundo caso, son mal llamadas interrupciones. Ms bien habra
     que decir funciones, ya que nos sirven para hacer una llamada a una
     funcin BIOS o DOS, como por ejemplo la accin de cambiar de modo de video,
     para la cual se utiliza la interrupcin 10h (Driver o controlador de vdeo),
     con el nmero adecuado de funcin. Ms adelante veremos cmo llamar a una
     funcin.

     Al primer tipo de interrupciones se les denomina interrupciones de
     hardware, y son las interrupciones reales. Esto es, que estando un programa
     en ejecucin, se interrumpe ste para ejecutar un trozo de cdigo necesario
     para atender a la peticin de un dispositivo, como puede ser el teclado.
     Acto seguido, se reanuda la ejecucin del programa en cuestin.
     Son las interrupciones que vimos en la leccin 3, al hablar del PIC.

     Al segundo tipo de interrupciones se les denomina interrupciones de
     software, y son las 'ficticias', ya que no hay ningn dispositivo pidiendo
     atencin del procesador, sino que es el programa del usuario el que
     ejecuta una funcin BIOS o DOS, mediante una interrupcin.
     En este caso, no se interrumpe el programa de forma sbita, sino que es
     dicho programa el que lanza una interrupcin, la cual tiene su rutina
     de atencin a la interrupcin (como vimos en la leccin 3) 'conectada'
     a un grupo de funciones o rutinas.

     Veamos las interrupciones con ms detalle:

     + La tabla de vectores:
       ---------------------
       Toda interrupcin aceptada conduce a la ejecucin de un subprograma
       especfico, como hemos visto. Pero cmo sabe el procesador dnde empieza
       este subprograma, una vez que atiende a la interrupcin... La respuesta
       nos la da la tabla de vectores.

       Esta tabla de vectores contiene las direcciones de comienzo o punteros
       al subprograma de atencin a la interrupcin.
       La tabla est compuesta de 256 entradas. Es decir, son posibles 256
       interrupciones diferentes en el PC.

       Cada una de estas entradas, contiene la direccin de inicio del cdigo
       de atencin a una interrupcin, en la siguiente forma:
       2 primeros bytes (una palabra) que contienen la direccin base del
       segmento, y los 2 ltimos bytes que contienen el desplazamiento.
       En total 4 bytes para indicar el comienzo de una interrupcin, en la
       forma segmento:desplazamiento.

       Ya vimos en la segunda leccin cmo transformar una direccin segmentada
       (segmento:desplazamiento) en una direccin fsica o real.

       Durante la aceptacin de una interrupcin, el 8086 carga la direccin
       base del segmento en el registro CS y el desplazamiento en el contador
       de programa IP. De esta forma, la siguiente instruccin a ejecutar, que
       viene dada por los registros CS:IP, ser la primera del subprograma
       de atencin a la interrupcin.

     + Pines (lneas de bus) para demandar interrupcin desde el exterior.
       -------------------------------------------------------------------
       Existen 3 lneas externas jerarquizadas que son, por orden de prioridades
       decrecientes: RESET, NMI e INTR. Slo INTR es enmascarable (cuando un
       pin de demanda de interrupcin est enmascarado -inhabilitado- la
       activacin del pin, no produce ninguna interrupcin).

       Es decir, que si se activan los pines RESET o NMI, siempre van a conducir
       a la ejecucin de una interrupcin. Pero si se activa el pin INTR,
       tenemos dos opciones (dependiendo de si est enmascarado o no), que son
       hacer caso omiso de la peticin de interrupcin, o atender dicha
       interrupcin, respectivamente.

       Pin INTR:
        Una peticin de interrupcin sobre este pin es enmascarable mediante
        el bit IF (bandera de interrupcin) del registro FLAGS o registro
        de estado.
        Este bit IF, es la mscara de INTR. Para saber si est enmascarada o no
        la lnea INTR, se mira este flag. El cual puede tener (obviamente) dos
        valores: 0 y 1. Enmascarado es 0.

        Para manipular este bit, disponemos de dos instrucciones en ensamblador:
        CLI (Clear IF, o borrar flag IF) que lo pone con valor 0.
        STI (Set IF, o activar flag IF) que lo pone con valor 1.

        La peticin de interrupcin se realiza activando el pin INTR con nivel
        alto (1) y debe mantenerse as hasta que por el pin INTA (pin asociado
        al pin INTR. Es activo a nivel bajo (0), indicando que se ha aceptado
        la interrupcin solicitada por medio del pin INTR) el 8086 indique que
        ha sido aceptada.

        Entonces... Contamos con el pin INTR para pedir al procesador atencin a
        una interrupcin, y con el pin asociado INTA que estr con valor (0)
        cuando la interrupcin haya sido aceptada.

        INTR ---> Interrupt Request (peticin de interrupcin).
        INTA ---> Interrupt Accepted (interrupcin aceptada).

        Veamos cmo acta la CPU desde que se activa el pin INTR hasta que
        se retorna del subprograma de atencin a la interrupcin:

        Debido a que la interrupcin interrumpir al programa en ejecucin en
        cualquiera de sus instrucciones, es necesario resguardar el contenido
        del registro de estado (FLAGS), para que al volver de la interrupcin,
        tengan las banderas el mismo valor.
        Y sobre todo, hay que guardar la direccin de la siguiente instruccin
        a ejecutar en el programa actual.

        Pero dnde se guardan todos estos datos... En una zona de memoria
        denominada PILA, la pila del procesador. (Explicacin en el ltimo
        apartado de esta leccin).
        Al acto de introducir un dato en la pila se le denomina apilar, y a
        sacarlo de la misma se le denomina desapilar.

        Pues bien, el procesador har lo siguiente:
         - Apila el contenido del registro de estado (flags)
         - Apila la direccin de retorno (contenido de los registros CS e IP).
         - Inhibe las interrupciones (IF=0 y TF=0, ms adelante se comenta
           la utilidad del flag TF o TRACE).
           Esto se hace para que no se produzca otra interrupcin durante la
           secuencia de aceptacin de la interrupcin. Esto es muy importante.
         - Activa el pin INTA (lo pone a nivel bajo). El dispositivo que ha
           solicitado la interrupcin, al notar el cambio en el pin INTA,
           queda enterado de la aceptacin de la interrupcin.
         - Lee el nmero del vector de interrupcin del bus de datos.
           Previamente, el dispositivo lo ha depositado en respuesta a la
           activacin del pin INTA.
         - Obtiene la direccin del subprograma de atencin a la interrupcin.
           Dicha direccin se encuentra (como hemos visto antes) almacenada
           en la tabla de vectores.
         - El 8086 ejecuta la subrutina que finaliza con la instruccin IRET,
           o Retorno de Interrupcin, cuya ejecucin restituye en CS e IP la
           direccin de retorno salvada en la pila, y en el registro de estado
           el valor de los flags.

           Al restaurar los flags, se anula la inhibicin anterior de IF y TF,
           con lo cual, otra vez se aceptan interrupciones. Pudiendo as
           tener interrupciones en cascada.

           Repasar el ejemplo de la pulsacin de tecla de la leccin 3, a ver
           si ahora se v con ms claridad.

       Pin NMI:
        Este pin est reservado a acontecimientos graves, como puede ser un
        corte de corriente, un error de memoria, del bus, etc.

        La activacin de NMI no conlleva ninguna lectura en el bus de datos del
        n de vector de interrupcin, sino que la CPU directamente busca el
        vector de interrupcin nmero 2.

       Pin RESET:
        Inicializa el sistema.
        En la peticin de RESET no se almacena nada en la pila ni se accede a
        la tabla de vectores para conseguir la direccin de comienzo.
        Al activar el pin RESET, el registro de estado queda borrado (0).
        CS = 0FFFFh.
        IP = 00000h.
        De esta manera, la siguiente instruccin a ejecutar por el procesador
        es la contenida a partir de FFFF:0, cdigo de reinicializacin y carga
        del sistema operativo. Son los ltimos bytes de la ROM.
        El resto de registro de segmentos quedan con valor 0.
        DS = 0000
        ES = 0000
        SS = 0000

     + Interrupciones internas o desvos.
       ----------------------------------
       El microprocesador 8086 tiene 2 interrupciones internas:
       'Divisin imposible' y 'funcionamiento paso a paso (TRACE)'.

       Divisin imposible:
        Se produce cuando se divide por 0, o cuando el cociente resultante
        de la divisin no cabe en el registro preparado para contenerlo.
        En ambos casos, se ejecuta la interrupcin 0.

      Funcionamiento paso a paso:
        Si el programador coloca a (1) el bit TF (TRACE) del registro de estado,
        al final de cada instruccin, la CPU bifurcar a la posicin de memoria
        indicada por el vector de interrupcin nmero 1.
        Esto es lo que utilizan los debuggers o depuradores de cdigo para
        hacer un seguimiento del programa, instruccin por instruccin.


     Ms adelante, cuando hablemos acerca de la programacin de utilidades
     residentes, entraremos en la programacin prctica de las interrupciones.
     Valga lo dicho hasta ahora como base terica.


     - La pila del procesador:
     -------------------------
     La pila es una caracterstica interna del 8086. Es una estructura de
     datos situada en la RAM. Proporciona a los programas un lugar donde
     almacenar datos de forma segura, pudiendo compartirlos con otros
     procedimientos o programas de forma cmoda y prctica.

     La funcin ms importante de la pila es la de mantener las direcciones
     de retorno en las llamadas a procedimientos e interrupciones, as como
     guardar los parmetros pasados a estos procedimientos.
     La pila tambin se utiliza para almacenamiento temporal de datos dentro
     de un programa, y para muchas cosas ms que se aprenden con la prctica.

     La pila tiene su nombre por analoga con los montones de platos apilados
     (pilas de platos). Cuando un dato nuevo es introducido en la pila, se dice
     que es apilado (push) debido a que se sita por encima de los dems, es
     decir se sita en la CIMA de la pila.

     Una pila opera en el orden  ltimo-en-entrar - primero-en-salir:
     LIFO (LAST IN FIRST OUT) o lo que es lo mismo, el ltimo en entrar es
     el primero en salir.

     Esto significa que cuando la pila se utiliza para seguir la pista de los
     retornos de las subrutinas, la primera llamada a subrutina que se hizo,
     es la ltima que se devuelve. De esta manera, la pila mantiene ordenado el
     funcionamiento del programa, las subrutinas y rutinas de tratamiento de
     interrupcin, sin importar la complejidad de la operacin.

     La pila crece en orden inverso. Es decir, a medida que se aaden nuevos
     datos, la cima de la pila se acerca ms a posiciones ms bajas de memoria.

     Existen 3 registros destinados a gestionar la pila.
     Registro de segmento de pila (SS): que indica la direccin base del
     segmento de pila
     Puntero de pila (SP): que apunta a la cima de la pila.
     Puntero base de pila (BP): que se usa para moverse a travs de la pila
     sin cambiar la cima. Se suele utilizar para acceder a los distintos
     parmetros al llamar a una funcin.

     Los elementos que se almacenan en la pila son del tipo palabra (2 bytes).
     Esto quiere decir, entre otras cosas, que el puntero de pila (SP), as como
     el puntero base de pila (BP), incrementan/decrementan en 2 su valor para
     apuntar a un nuevo elemento dentro de la pila, fruto de apilar o desapilar
     un elemento.

     Tambin conlleva el que si queremos almacenar un byte en la pila, primero
     lo debemos convertir en palabra (2 bytes), y luego almacenar esa palabra.
     Esto es muy sencillo, slo hay que meter ese byte o registro de 8 bits
     en un registro de 16 bits y almacenar este registro.

     Las instrucciones para manejar la pila son:
     PUSH ---> Guarda un dato en la pila. Decrementando SP en 2 unidades, para
               que apunte al nuevo elemento a introducir.
               Ejemplo: PUSH AX --> Apila el contenido de AX en la cima de la
                        pila.

     POP ----> Obtiene un dato de la pila. Incrementando SP en 2 unidades, para
               que apunte al nuevo elemento a introducir.
               Ejemplo: POP AX --> Desapila el contenido de la cima de la pila
                        en el registro AX. Es decir, AX contendr el valor
                        que hubiera en la cima de la pila, y el puntero de pila
                        se actualiza incrementndolo en 2.

     PUSHF --> Guarda el contenido del registro de estado (FLAGS) en la pila.
               Decrementando SP en 2 unidades, para que apunte al nuevo elemento
               a introducir.
               No es necesario indicar sobre qu acta esta instruccin, lo
               lleva implcito en su nombre PUSHF (PUSH FLAGS).

     POPF ---> Introduce en el registro FLAGS el contenido de la cima de la
               pila. Incrementando SP en 2 unidades, para que apunte al nuevo
               elemento a introducir.
               Al igual que con la instruccin anterior, no es necesario indicar
               sobre qu acta esta instruccin POPF (POP FLAGS).



     Conviene recordar el hecho de que la pila crece en orden inverso al
     normal, es decir de direcciones de memoria altas a direcciones bajas.
     Por lo tanto es necesario tener en cuenta el uso que se va a hacer de
     la pila en el programa, debido a que si reservamos espacio en nuestro
     programa para una pila pequea, en caso de sobrepasarla haciendo muchos
     push seguidos, machacara nuestro programa.

     Hay que tener en cuenta que no slo es nuestro programa el que utiliza
     la pila mediante la instruccin PUSH y mediante llamadas a procedimientos,
     interrupciones, etc. Sino que mientras nuestro programa corre se estn
     sucediendo numerosas interrupciones que conllevan muchos PUSH.
     Por ejemplo, 18'2 veces por segundo se produce la interrupcin de reloj,
     con lo cual, todas estas veces se est apilando y posteriormente
     quitando informacin de la pila.

     Por regla general, basta con tener una pila de unos 2 KS, es decir, espacio
     para almacenar 1024 elementos. Es muy difcil que se sobrepase este tamao.


---


     Bueno... Aqu seguro que hay dudas.
     Venga, decidme qu quereis que explique ms detenidamente, que dentro
     de un par de lecciones empezamos a programar, y hay que tenerlo todo claro.

     Un saludo.
     AESOFT....
