ALIPSO.COM - Trabajos prácticos, monografías, apuntes, tesis, manuales, material educativo y mucho más.
 

Página de inicio | Agregar a Favoritos | Contactate con nosotros | Publicidad

Alipso.com
 

Monografías

Examenes

Enlaces

Publicar material o sitio

Foros

ABC del estudio

Diversión

  Buscar material sobre...
Todas las palabras Cualquier palabra Frase Exacta
El sitio en el que encontrás
todo el material que buscás.

   

Enlaces recomendados
   

Material relacionado
 

Material educativo de Alipso relacionado con 88 modulo INTemulasm (Capitulo

  • Una relexion sobre la historia de john ssabunnya: ...
  • Los hechos de Feitesm 2000-2001: Venta de libros en el campus, Conferencia: “Invierte bien tu dinero” por Lic. Julio Baca de ACTINVER, Módulo de estudiantes Foráneos, Reforma del Estado, La nueva libertad de expresión, Fiesta Mexicana.
  • Analisis psicologico de la serie friends: Capitulo: 43 “el de la varicela”.
  • Informática general. Circuitos Secuenciales.: Biestable RS con reloj. (Sincrono). Biestable JK. Biestable D. Contadores. Contador ascendente modulo 4. Registros.


  • Enlaces externos relacionados con 88 modulo INTemulasm (Capitulo

    Ver enlaces

     

    Publicidad
       

    Monografías
     
    8.8. El módulo INTemul.asm (Capitulo 8)
    8.8. El módulo INTemul.asm, todos los procedimientos, las funciones, los modulos y una conclusion.

    Agregado: 29 de AGOSTO de 2000 | Palabras: 7634 | Votar! | Sin Votos | Sin comentarios | Agregar Comentario
    Categoría: Apuntes y Monografías > Computación > Varios >

      Imprimir Recomendar a un amigo Recordarme el recurso Descargar como pdf

    8.8.     El módulo INTemul.asm

    En este módulo se encuentran tres procedimientos que sirven de apoyo para el monitor de V86.

    8.8.1.     Procedimiento Cargar y Ejecutar Programa

    Interrupción: 21h.

    Función: 4Bh.

    Descripción: Cargar y ejecutar programa.

    Nota: No se emulará esta función, sino que mas bien lo que hacemos es

              interceptarla  para coger el nombre del programa que se va a ejecutar  y   

              luego ejecutamos la verdadera llamada a este servicio.

     

                Este procedimiento ha sido creado para interceptar la interrupción 21h, servicio 4Bh y coger el nombre del fichero que se va a ejecutar y ponérselo como nombre a la tarea V86 que se está ejecutando. De esta forma la tarea V86 queda reconocida con el nombre del programa que ejecuta.

    8.8.2.     Procedimiento Mover datos desde/hacia memoria extendida

    Interrupción: 15h.

    Función: 87h.

    Descripción: Mover bloque de datos desde/hasta la memoria extendida

    Nota: La función 87h ha de ser emulada porque dentro del código de esta función

              se conmuta el procesador al modo protegido por parte de la BIOS para

              acceder a la memoria extendida.

     

                Cuando una tarea V86 intenta acceder a la memoria extendida, lo hace a través de este servicio de la BIOS. Como la BIOS conmuta el procesador al modo protegido para llevar a cabo este servicio, se producirá una excepción por falta de protección general al intentar activar el modo protegido desde el modo V86. Para que no se produzca esta excepción, es necesario emular este servicio desde DMT para no volver a conmutar el procesador a modo protegido. En los listados fuentes de DMT se puede ver como se ha emulado este servicio.

    8.8.3.     Procedimiento Establecer modo de Vídeo

    Interrupción: 10h.

    Función: 00h.

    Descripción: Establece modo de vídeo.

    Nota: Si el nuevo modo de vídeo es un modo gráfico se terminará la tarea si, por el

             contrario, es un modo de texto se permitirá la llamada.

     

                Cuando se solicita un servicio de la BIOS para cambiar el modo de vídeo, este procedimiento se pone en marcha detectando si el nuevo modo de vídeo es uno de los modos textos o gráficos. Si el nuevo modo de vídeo es gráfico, se finaliza la tarea a través de un mensaje por pantalla indicando “Modo de Vídeo no soportado por DMT”.

         push    eax

         mov     al, ss:esp[2*4]    ; contenido de AL antes de la excepción

         and     al, not 80h             ; desactivamos septimo bit

         cmp     al, 04h                     ; ¿320*200 grafico (4 colores)?

         je      matarTar                    ; si

         cmp     al, 05h                    ; ¿320*200 grafico (4 colores)?

         je      matarTar                   ; si

         cmp     al, 06                        ; ¿640*200 grafico (2 colores)?

         je      matarTar                 ; si

         cmp     al, 0dh                   ; ¿resto de modos graficos?

         jae     matarTar                 ; si

         pop     eax

         ret

    matarTar:

         mov     ax, SelData32

         mov     ds, ax

         sti

     esperarPlano:

         mov     eax, [Tactiva]

         cmp     eax, [TPrimerPlano]

         jne     esperarPlano

         sti

         mov     [EXC], 2                        ; excepcion de video

         mov     [KeyVect+56], 1

         mov     [KeyVect+29], 1

         mov     [KeyVect+50], 1

    matarT:

        jmp      matarT                      ; esperamos a que se mate la tarea

     

     
                DMT no permite la utilización de ningún modo de vídeo debido a que cada uno de ellos se programa de una forma diferente, lo que complicaría notablemente la gestión de la pantalla virtual de una tarea en segundo plano. Además, algunos modos gráficos poseen una alta resolución lo que implica un gran gasto de memoria y la implementación obligatoria de un sistema de memoria virtual para hacer frente a tal demanda de memoria. Este procedimiento comprueba si el nuevo modo de vídeo corresponde a algún modo gráfico a través del siguiente código:

     

     

     

     

     

     

     

     

     

     

     

     

     

    8.9.     El módulo Mem32.asm

    Este módulo contiene dos funciones que se encargan de reservar memoria convencional y memoria extendida para cada una de las tareas V86.

    8.9.1.     Función ReserXMS

    Función: ReserXMS

    Descripción: Aloja EAX bloques de 4k de la memoria XMS

    Entrada: EAX = numero de páginas de 4k a alojar

     Salida: Si CF = 0 entonces

                EBX = numero de bloques de 4Kb alojados

                EDX = offset desde SelExt de la memoria alojada

                Si CF = 1 entonces no se ha podido alojar memoria

     

                Esta función reserva memoria para un conjunto de bloques de 4 Kb de memoria extendida. Para controlar la memoria extendida libre, utilizamos dos variables que nos indican el valor tope de memoria extendida y el valor de la memoria extendida que es usada actualmente. Cuando solicitamos memoria extendida, la variable que indica la memoria extendida usada se va incrementando hasta alcanzar el valor máximo de memoria extendida.

    8.9.2.     Función ReserMem32

    Función: ReserMem32

    Descripción: Aloja EAX bytes de memoria convencional

    Entrada: EAX = numero de bytes a alojar

    Salida: Si CF = 0 entonces

               EDX = dirección lineal del comienzo del bloque alojado

               Si CF = 1 entonces no se ha podido alojar memoria

     

                Esta función es utilizada por DMT para gestionar la memoria convencional que va utilizando para crear las estructuras necesarias para el modo protegido. Cuando se crea una nueva tarea, ésta necesita un directorio de páginas y una tabla de páginas de 4 Kb, toda esta memoria se coge de la memoria convencional, es decir, de la memoria por debajo del primer Mbyte físico.

    8.10.     El módulo NewIRQ.asm

    Los procedimientos que se ofrecen en este módulo se han “anclado” en las entradas correspondientes de la IDT para tratar las interrupciones del teclado y del ratón. La razón de ello, es que queremos que cuando el usuario pulse una tecla o realice una acción con el ratón, ésta vaya a parar a la tarea que está en primer plano y no a la tarea que está atendiendo el procesador actualmente.

    8.10.1.     Procedimiento NewInt09

    Procedimiento: NewInt09.

    Descripción: Rellena el vector de teclas pulsadas y llama a la  verdadera Int 09h.

    Entrada: Nada.

    Salida: Nada.

     

                Cuando el procesador está atendiendo a una tarea, éste no puede ver más allá del espacio de direcciones de la tarea que está atendiendo. Ya que el procesador utiliza el directorio y tablas de páginas de esa tarea que sólo contienen el direccionamiento en memoria de esa tarea. Si se pulsa una tecla por parte del usuario, se generará una interrupción en el 80386 y se llamará a la rutina correspondiente para el tratamiento de esa interrupción que hay instalada en la tarea que está procesando. Es decir, si el procesador está ejecutando en un momento dado la tarea A y el usuario pulsa una tecla, el 80386 llamará a la rutina correspondiente para el tratamiento de esa interrupción que se encuentra en el espacio de direcciones de la tarea A. Normalmente, la rutina de cada tarea que se encarga de manejar la interrupción de teclado se encarga de descodificar el código de la tecla enviada por el teclado y depositar el código ASCII de esa tecla dentro del espacio de direcciones de la tarea en curso.

                Todo lo comentado anteriormente es lo que el 80386 hace por defecto, pero a veces esto no nos interesa. Supongamos que tenemos dos tareas ejecutándose concurrentemente, tarea A y tarea B, y la tarea A está en primer plano. En estos momentos imaginemos que el procesador está atendiendo a la tarea A y el usuario pulsa una tecla. El 80386 llamará a la rutina de la interrupción de teclado de la tarea A, ésta rutina se encargará de depositar el código ASCII de la tecla pulsada dentro del espacio de direcciones de la tarea A, donde más tarde se recogerá el código ASCII de la tecla por el programa que se está ejecutando dentro de la tarea A.

                Hasta aquí todo va bien, ya que el usuario ha pulsado una tecla y seguramente ha visto su impresión por pantalla, ya que la tarea A estaba en primer plano. Supongamos ahora que el procesador está atendiendo a la tarea B y el usuario vuelve a pulsar una tecla, el 80386 llamará a la rutina de interrupción de la tarea B donde se llevará a cabo la descodificación de la tecla pulsada y se depositará el código ASCII de dicha tecla en el espacio de direcciones de la tarea B. ¿Está todo correcto? Desde el punto de vista del procesador todo se ha realizado tal y como debería ser, pero desde el punto de vista del usuario parecerá que la tecla no ha sido pulsada, ya que ha ido a parar a una tarea que estaba en segundo plano y no ha visto por tanto su impresión en pantalla, o lo que es lo mismo, la tecla no ha sido recogida por la tarea A que es la que estaba en primer plano.

                Nuestro problema es que debemos de establecer un mecanismo que nos asegure que la tecla que el usuario pulse vaya a parar a la tarea que está en primer plano. He pensado en muchos mecanismos que me podrían solucionar el problema pero siempre llegaba a que no era lo que el usuario desearía. Tras muchas vueltas llegué a la solución final que aseguraba que toda tecla iba a parar a la tarea en primer plano de una forma elegante y cuyo resultado era el deseado por el usuario. A continuación hago una breve mención de algunos mecanismos que pensé que parecían llevar a la solución del problema pero no eran correctos en el momento de su ejecución:

     

    ·      Realizar una conmutación a la tarea que estaba en primer plano justo cuando se producía la interrupción de teclado. A simple vista esto parece correcto pero si conmutamos a la tarea en primer plano se seguirá ejecutando esa tarea por el punto que se quedó y no se llevará a cabo el tratamiento de la interrupción del teclado, ya que ésta ya se ha producido. Si el lector no ve cual es el fallo de esta posible solución, investigue cómo es el proceso exacto de una conmutación de tareas y el proceso de una interrupción hardware.

    ·      Una vez que se produce la interrupción del teclado en la tarea en segundo plano, guardar el código de la tecla generada por el teclado en un buffer de teclas y cuando se atienda a la tarea en primer plano, entregarle todas las teclas que hay en el buffer de teclas. Esta idea parece correcta y sencilla, pero su implementación es bastante costosa. En primer lugar, si recogemos el código de la tecla procedente del teclado cogeremos su código scan y no su código ASCII que es lo que nos interesa para depositar en la tarea en primer plano. En segundo lugar, si la rutina de interrupción del teclado de la tarea en primer plano ha sido interceptada por el usuario, nunca se llamará a esa rutina cuando se produzca la interrupción en una tarea en segundo plano, ya que únicamente se almacenará en el buffer de teclas.

                Son algunas otras soluciones las que se han estudiado pero tampoco resultaron convenientes. Por fin se llegó a la solución final y su descripción se muestra a continuación.

                La idea es bastante simple pero debemos de cambiar un poco todos los procedimientos que se encargan del manejo de interrupciones software (como el procedimiento INT_16) y hardware para que permitan llevar a cabo la nueva solución. Cuando el usuario pulsa una tecla y el procesador se encuentra atendiendo a una tarea en segundo plano, se producirá una interrupción de teclado y se ejecutará el código correspondiente a la interrupción de teclado de la IDT que ha instalado DMT. En ese código debemos de comprobar si la tarea en la que se ha producido la interrupción era la que estaba en primer plano. Como la interrupción se ha producido sobre una tarea en segundo plano debemos de cambiar el registro CR3 de la tarea en segundo plano por el registro CR3 de la tarea en primer plano. Es decir, lo que hacemos es cambiar el espacio de direcciones de la tarea en segundo plano por el espacio de direcciones de la tarea en primer plano y luego llamaremos a la rutina de interrupción del teclado que instaló el MS-DOS. Con esto la tecla se almacenará en la tarea que está en primer plano y aparecerá además en pantalla. Una vez que se ha llamado la interrupción original de teclado instalada por el MS-DOS, debemos de volver a recargar el registro CR3 de la tarea en segundo plano con el contenido que tenía anteriormente.

                Con todo esto el problema del teclado se ha solucionado. A continuación se describe el problema del ratón que se resuelve de la misma forma que el teclado.

    8.10.2.     Procedimiento MouseINT

    Procedimiento: MouseInt.

    Descripción: Nueva rutina para la IRQ del ratón (sólo PS/2).

    Entrada: Nada.

    Salida: Nada.

                El ratón ofrece el mismo problema que el teclado y se resuelve de la misma forma. Cuando el usuario realiza una acción con el ratón, como puede ser moverlo, se producirá una interrupción sobre la tarea que esté atendiendo el procesador y que a veces no es la tarea en primer plano. Por tanto, deseamos que toda acción que se produzca en el ratón vaya a parar a la tarea que está en primer plano.

                Para solucionar el problema del ratón debemos de cambiar nuevamente el espacio de direcciones de la tarea en segundo plano por la tarea que está en primer plano y con ello el resultado es perfecto.

                Si observa el código fuente de este procedimiento y del anterior, observará que en ambos hay una etiqueta llamada discoTrabajando y DiscoNoTrabajando. El código que encapsulan estas etiquetas no fue original para tratar el problema que tanto el ratón como el teclado ofrecen. El código de estas dos etiquetas se implementó debido a un problema que aparecía con las operaciones de disco. Este problema se describe a continuación.

                Cuando se implementó los procedimientos NewInt09 y MouseInt, todo funcionaba correctamente, excepto cuando la tarea en segundo plano, sobre la que se producía la interrupción de teclado, estaba realizando una operación de disco. Para ver el problema claramente vamos a suponer un nuevo ejemplo. Supongamos que tenemos la tarea A y la tarea B ejecutándose en memoria y la tarea A está en primer plano y la tarea B, que está en segundo plano, está chequeando el disco duro. Si el usuario pulsa una tecla sobre la tarea B se cambiará el CR3 de la tarea B por el de la tarea A. Si después de restaurar el registro CR3 de la tarea B, tras haber finalizado la rutina de interrupción de teclado, observamos la tarea B y veremos que seguramente se ha parado y parece bloqueada. Este problema surge debido al cambio que se produce del registro CR3 justo antes de realizar una transferencia de disco.

                Inicialmente observé que la tarea en segundo plano se bloqueaba cuando estaba realizando una operación de disco y se pulsaban teclas del teclado. No encontraba explicación ha esto ya que la idea del cambio del registro CR3 me parecía correcta. Cuando casi me doy por vencido, decidí ver en que dirección de memoria se quedaba bloqueada la tarea en segundo plano. Observé que siempre se quedaba bloqueada en un rango no muy grande de direcciones y decidí realizar el desensamblado de esas posiciones de memoria. Esas posiciones de memoria correspondían al código de la interrupción 13h, “Operación de disco”, de la BIOS y se trataba de un bucle que no finalizaba hasta que una variable de la BIOS Data Area estaba puesta a uno. Cogí rápidamente un manual que explicaba cada uno de los datos de la BIOS Data Area y comprobé que la variable anterior correspondía a disco no inicializado. Esta variable es puesta a uno cuando el disco está preparado para mandar o recibir información. La tarea en segundo plano se bloqueaba porque cuando se realizaba el cambio del registro CR3 el disco ponía a uno la variable anterior en la tarea que estaba en primer plano y cuando se volvía a restaurar el CR3, la tarea en segundo plano seguía con la variable anterior a cero, con lo que el bucle nunca terminaba.

                En ambos procedimientos se observa si al restaurar el registro CR3 se ha cambiado la variable disco no inicializado de la BIOS Data Area. Si se ha cambiado dicha variable en la tarea en primer plano, indicará que la tarea en segundo plano iba a realizar una operación de disco y tendremos que poner manualmente esa variable a uno en la tarea en segundo plano para que siga funcionando correctamente.

    8.10.3.     Procedimientos COM1 y COM2

    Procedimiento: COM1.

    Descripción: Nueva rutina para la IRQ del 1er puerto serie (ratón en COM1).

    Entrada: Nada.

    Salida: Nada.

     

    Procedimiento: COM2.

    Descripción: Nueva rutina para la IRQ del 2do puerto serie (ratón en COM2).

    Entrada: Nada.

    Salida: Nada.

     

                Debido a que algunos ratones se pueden anclar en la IRQ del primer puerto serie  el segundo puerto serie, debemos de realizar una copia del procedimiento MouseInt en las entradas de la IDT correspondientes al primer y segundo puerto serie, donde la única diferencia es que cada una de ellas llama a una interrupción software diferente.