42
UNIVERSIDAD AUTONOMA METROPOLITANA UNIDAD IZTAPALAPA 'DIVISION CBI / LICENCIATURA: INGENIERIA ELECTRONICA EN COMPUTACION REPORTE DEL PROYECTO TERMINAL II A SINTESIS DE VOZ POR MEDIO DE LA PC" n ASESOR DE PROYECTO : PROFESOR : GONZALO I. DUCHEN SANCHEZ. INTEGRANTES: ,/ ' ALEJANDRO JIMÉNEZ HERNÁNDEZ. MISAEL RíOS ISLAS. MEXICO, D.F. A 3 DE MAYO DE 1995. -

LICENCIATURA: INGENIERIA ELECTRONICA EN …148.206.53.84/tesiuami/UAM5690.pdf · excepto para sintetizadores con vocabularios muy pequeños. Los sintetizadores de lenguaje representan

Embed Size (px)

Citation preview

UNIVERSIDAD AUTONOMA METROPOLITANA UNIDAD IZTAPALAPA

'DIVISION CBI

/ LICENCIATURA: INGENIERIA ELECTRONICA EN COMPUTACION

REPORTE DEL PROYECTO TERMINAL I I

A SINTESIS DE VOZ POR MEDIO DE LA PC" n

ASESOR DE PROYECTO : PROFESOR : GONZALO I. DUCHEN SANCHEZ.

INTEGRANTES: ,/'

ALEJANDRO JIMÉNEZ HERNÁNDEZ. MISAEL RíOS ISLAS.

MEXICO, D.F. A 3 DE MAYO DE 1995. -

hdice

Introduccidn Síntesis del Lenguaje

Principios del la síntesis del lenguaje

Tamaño de la unidad de lenguaje almacenado

Tipos diferentes de unidades de lenguaje para concatenar.

Tamaño de memoria. Método de síntesis

Sistemas de texto limitado (respuesta en voz) Sistemas de texto sin restricción (texto a lenguaje)

Solucidn por mddulos

Programación de la tarjeta de sonido

Programación de la memoria expandida Programación del TSR

Conclusiones Aphdice A Apendice B Bibliografía

3 4 5 5 6

6

7

a a 9 11

13

17

30 32 35 42

Introducci6n

Hoy en día existe un gran número de programas computacionales los cuales intentan ser amigables al usuario, estos sistemas generalmente usan una gran variedad de mensajes escritos, muchos de estos intentos de hacer programas amigables son bastante malos.

Notando que los mensajes hablados podrían hacer que un programa fuera más amigable con el usuario; especialmente con aquellos que están privados del sentido de la vista; se decidió tomar uno de los programas más usados, pero, desgraciadamente uno de los menos amigables con el usuario; el MS-DOS; durante este proyecto se diseñará un programa para MS-DOS, el cual será usado para indicar verbalmente al usuario cuando se ha cometido un error.

Para lograr lo anterior se decidió usar una tarjeta de sonido Pro Audio Spectrum 76, la cuál esta capacitada para reproducir señales analógicas, también se hará uso de la memoria expandida y de toda la teoría de los programas residentes (TSR's).

Este proyecto se organizará en 4 partes, la primera de ellas esta relacionada a la programación de la tarjeta de sonido, la segunda parte está relacionada con la programación de la memoria expandida, en la tercera parte se diseña el programa residente, el cuál posteriormente contendrá a las demás partes, esto se realizará en la cuarta parte donde uniremos todas las piezas del programa.

La forma de organizar el reporte no significa que el programa se desarrolló estrictamente en ese orden, de hecho se programaron las partes dos y tres simultáneamente, mientras se trataba de recopilar información acerca de la programación de la tarjeta de sonido.

SíNTESIS DE LENGUAJE.

Síntesis de lenguaje, la generación automática de las formas de onda del lenguaje, ha sido desarrollado en los años recientes. El lenguaje sintetizado fue generado primeramente en computadoras grandes, algunas veces como interface con un modelo de área vocal análogo. Ahora los diferentes dispositivos de" sintetizador de lenguaje" desde programas de software baratos para computadoras personales hasta maquinas lectoras para lo oculto. La reciente explosión de sintetizadores comerciales es debido primeramente a los avances en la tecnología de circuitos integrados, pero también han ido mejorando en la metodología de la síntesis de lenguaje. Los sintetizadores reproducen lenguaje en un rango de ancho de banda desde 3 khz. (para aplicaciones telefónicas) hasta 5 khz. (para calidad alta). Las frecuencias arriba de los 3 khz. son suficientes para la percepción de las vocales desde que las vocales son adecuadamente especificadas por un formato. La percepción de algunas consonantes, sin embargo, es ligeramente perjudicada si la potencia en el rango de 3-5 khz. es omitida.

Las frecuencias por debajo de los 5 khz. son útiles para mejorar la claridad del lenguaje natural y para agregar un poco de inteligencia al lenguaje. Si nosotros asumimos que el sintetizador reproduce lenguaje arriba de los 4 khz. , una velocidad de 8000 muestraslseg. es necesitada. Aquí PCM lineal requiere 12-1 3 bits/muestra para lenguaje de calidad, el resultado almacena velocidades cercanas a los 100 kbitsheg. lo cual es prohibido excepto para sintetizadores con vocabularios muy pequeños.

Los sintetizadores de lenguaje representan tratos entre las demandas conflictivas de maximizar la calidad del lenguaje, mientras que minimiza el espacio en memoria , complejidad algoritmica, y periódicamente en computación. Una preocupación básica es el requerimiento de memoria, el cual es con frecuencia proporcional al vocabulario del sintetizador.

Usualmente los sacrificios hechos para reducir el tamaño de la memoria para sintetizadores .

Principios de la síntesis del lenguaje.

La síntesis del lenguaje comprende la conversión de un texto de entrada (consistente de palabras o sentencias) en formas de onda del lenguaje, usando algoritmos y algunas formas de datos previamente codificados. El texto puede ser introducido por el teclado o por el reconocimiento óptico de un caracter o obtenerlo desde una base de datos almacenado. Los sintetizadores del lenguaje pueden estar caracterizados por el tamaño de las unidades del lenguaje, concatenadas para producir el lenguaje de salida, como por el método usado para codificar, almacenar, y sintetizar el lenguaje.

Usando unidades largas de lenguaje, tal como frases y sentencias, pueden dar una alta calidad al lenguaje de salida pero requiere mucha memoria. Métodos eficientes de codificación reducen la memoria necesitada pero con frecuencia degradan la calidad del lenguaje.

TamaAo de la unidad de lenguaje almacenado.

La síntesis simplemente concatena palabras almacenadas o frases. Esta aproximación puede producir lenguaje con una calidad alta (dependiendo del método de síntesis) pero es limitado por la necesidad de almacenarlo en memoria (solo lectura) todas las frases para ser sintetizadas después de que sean habladas aisladamente o en sentencias de contexto. Para máxima naturaleza en el lenguaje sintetizado, cada palabra o frase puede ser originalmente pronunciada con tiempo y entonación apropiada para todas las frases en la cual pueda ser usada. Así, si una palabra puede ocurrir en diferentes estructuras sintácticas, esta pronunciación debe ser grabada y almacenada usando sentencias simulando los diferentes contextos.

Tipos diferentes de unidades de lenguaje para concatenar.

Para síntesis de texto sin restricción, los sistemas avanzados generan lenguaje de secuencias básicas de sonido, las cuales substancialmente reducen requerimientos de memoria, aquí los lenguajes pueden tener solamente de 30 a 40 fonemas. Donde quiera la semejanza del espectro de esos sonidos cortos concatenados (50-200 ms) puede ser pulido en su limite para evitar saltos, lenguaje descontinuado.

El problema es que la pronunciación de un fonema en una palabra o frase es tener dependencia fonética de este contexto (e. g. fonemas cercanos, entonación, y velocidad de hablar). El pulido y ajuste de los procesos así como la necesidad para calcular una entonación apropiada para los resultados de cada contexto en sintetizadores complejos con menos salida natural en el lenguaje.

Mientras que los sintetizadores comerciales tienen que estar basados primeramente en palabras o concatenación de fonemas, otras posibilidades enlazan unidades de tamaño intermedio de lenguaje almacenado tales como sílabas, disilabas o difonemas. Una sílaba consiste de un núcleo (otro una vocal o diptongo).

Tamaiio de memoria.

Generalmente un algoritmo sintetizador consiste de (a) un almacenamiento de memoria de parámetros de lenguaje, obtenidos desde lenguaje natural y organizado en términos de unidades de lenguaje y (b) un programa de reglas para concatenar esas unidades, puliendo los parámetros para crear algunas trayectorias que sean necesarias. Mientras esto dificulta la calidad del programa o la complejidad del calculo para diferentes síntesis aproximadas, el total de memoria necesitada para las unidades del lenguaje simplemente para determinar el tamaño.

M6todo de síntesis.

Los sintetizadores pueden ser clasificados por parametrizar el lenguaje para almacenar y sintetizar. El lenguaje de alta calidad requiere síntesis usando código en forma de onda y memorias largas. Los sistemas más eficientes pero de baja calidad usan voz. Sintetizadores de voz son considerados sintetizadores analógicos terminales porque su modela el lenguaje de salida de la vocal en la traquea sin explícitamente tomar en cuenta los movimientos articulados. Un tercer camino para generar lenguaje es síntesis articulatoria, la cual representa directamente la vocal de la traquea, usando datos derivados desde análisis del arreglo-X de la producción de lenguaje. Debido a la dificultad de obtener seguridad en tres dimensiones de la representación de la vocal traquea y de modelar el sistema con un limite obtenido de parámetros, este método pasado tiene baja calidad de lenguaje y tiene todavía que ver con la aplicación comercial.

La elección del método es influenciada por el tamaño del vocabulario sintetizado. Porque puede modelar todas las posibles expresiones, sistemas de texto sin limite que pueden ser más complejos y producir un lenguaje de baja calidad que responda a los sistemas de voz. Los avances tecnológicos en memoria pueden incrementar el vocabulario de sintetizar formas de onda de bajo costo, pero para mayor flexibilidad, los métodos paramétricos son necesarios.

La síntesis paramétrica normalmente produce lenguaje de calidad sintético solamente porque modela inadecuadamente la producción del lenguaje natural. Los sintetizadores paramétricos de texto sin limite usan pequeñas unidades de lenguaje (fonemas o difonemas) aquí la calidad no se incrementa suficientemente con unidades largas para justificar la demasiada memoria necesitada. Son más populares los sintetizadores de fonemas, los cuales normalmente almacenan uno o dos obtenciones de amplitMd . , y parámetros espectrales pqrq cpda uno de los 37 fonemas llrs [email protected],upan 2 kbits.

Sistemas de texto limitado (respuesta en voz).

El más común de los lenguajes sintéticos viene de los sistemas que decodifican el lenguaje. Esos sistemas son limitados para combinaciones de las unidades de lenguaje original, usualmente con sus entonaciones originales. Esto es adecuado para muchas aplicaciones como juguetes que hablan, sistemas de prevención en maquinas, y asistencia del directorio telefónico automático. Donde quiera si una voz estandar y vocabulario son insuficientes para una aplicación dada, la fabricación de síntesis puede procesar el lenguaje deseado para establecer un vocabulario rápido, y no excederse en costo por palabra.

Sistemas de texto sin restriccirjn (texto a lenguaje).

Una complejidad adicional en sintetizadores que aceptan texto sin limite es la necesidad para un procesador lingüístico para convertir el texto a una forma apropiada para accesar unidades de lenguaje almacenadas. El procesamiento lingüístico desarrolla la traducción de las sentencias de entrada a una secuencia de códigos lingüísticos para buscar las unidades almacenadas apropiadas y determinar los parámetros de entonación del texto para variar y la duración propiamente. El primer problema es usualmente el encabezado por obtener las reglas del lenguaje dependiente para convertir una serie de letras en una secuencia de fonemas. Esas reglas examinan el contexto de cada letra para determinar como es pronunciada . Muchas palabras usadas frecuentemente violan las reglas de la pronunciación básica y requiere listas de excepciones para ser examinadas antes de que las reglas básicas sean aplicadas.

SOLUClbN POR M6DULOS

Para hacer frente al problema planteado, es decir, al problema de hacer una extensión de MS-DOS que pueda comunicarse verbalmente con el usuario para indicarle que ha ocurrido un error; construiremos un programa que funcionará como sintetizador de lenguaje del tipo de texto limitado el cuál se activará en el momento de que ocurra un error. Decidimos construir este tipo de sistema puesto que los mensajes que se necesitan están determinados y son los mensajes de error que usa MS-DOS y que todos conocemos.

De esta forma las unidades de lenguaje almacenado serán frases completas, lo cuál nos dará una muy buena calidad de sonido y una buena entonación, pero, trataremos de acomodarlas dentro de la memoria de la PC de manera que estén disponibles cuando se necesiten y estén ocultas al usuario en caso contrario.

El método de síntesis que se planea usar es el de formas de onda almacenadas en memoria. Estas formas de onda será reproducidas por una tarjeta de sonido Pro Audio Spectrum 16; se decidió usar esta tarjeta puesto que ya se disponía de ella antes de iniciar el proyecto, aunque se podría usar cualquier otra como por ejemplo una Sound Blaster, pero, en este caso se tendría que reescribir la parte del programa que se encarga de reproducir las formas de onda.

Puesto que las formas de onda estarán cargadas en memoria, deberá existir también una forma de almacenarlas permanentemente en algún tipo de archivo; existen principalmente dos candidatos de formatos que podemos usar, estos son los archivos . VOC y los . WAV; estos tipos de archivos almacenan sonidos digitalizados con una velocidad de muestre0 determinada. La decisión de usar alguno de estos formatos dependerá de la información que se obtenga de como usarlos con la tarjeta de sonido.

La construcción de este programa estará basada en un TSR (Terminate and Stay Resident) o programa residente combinado con el uso de memoria expandida y la programación de la tarjeta de sonido. Así, tendremos que averiguar la forma de tomar el control de la PC cuando ocurra alguno de los errores críticos dentro de MS-DOS y hacer una llamada a una función hecha por nosotros mismos la cuál se encargará de manejar este error adecuadamente ya sea llamando a la función que atiende a la interrupción h24(Critical Error) o haciéndolo por si misma, además esta función deberá ser capaz de salvar el ambiente existente en ese momento en la PC, hacer que se reproduzcan los mensajes sonoros correspondientes, los cuales estarán previamente guardados en una región de la memoria expandida y por último deberá ser capaz de dejar que la PC siga su t e j o normal restableciendo el ambiente.

Programaci6n de la Tarjeta de Sonido Pro Audio Spectrum 16

La tarjeta de sonido Pro Audio Specfum 16 como la mayoría de los sistemas hardware se complementa con una parte de software, en este caso el controlador MVSOUNDS.SYS es el encargado de darle vida a la tarjeta de sonido, para hacer uso de este controlador se recurre a la INT 2Fh, la cual es el punto de entrada a una colección de funciones, de las que solo pudimos encontrar información de las que a continuación se presentan.

Descripcich Registros de entrada Registros de salida

Obtiene versión. BX=ASCII version mayor

CX=ASCII versión menor

Verifica instalación. AX=BCOOh Si instalado, BX xor CX xor

BX=3F3h DX = 4D56h (“V‘) CX=0000h

DX=0000h

AX=BCOl h

BX=6D20h(‘m’)

CX=2076h(‘v’)

DX=2020h(‘ ’) Obtiene puntero a la tabla AX=BC02h

de estado

Obtiene el puntero a la tabla AX=BC03h

de función.

Obtiene canales de DMA e AX=BC04h

IRQ.

Obtiene cadena de status AX=BCO6h

AX=BCOBh

BX:DX->tabla de estado

BX:DX->Tabla de función

AX=4D56h (‘MV’) BL=canal DMA

CL=numero de IRQ

AX=4D56 (“V’)

DX:BX->cadena de status

BX:DX->ASCII camino hacia

MVPROAS.EXE

o 0000h:0000h si no

disponible

Una alternativa hubiera sido el ignorar al controlador de esta tarjeta y progrmarla a un nivel mas bajo usando las direcciones de los registros que se encuentran en la Guia de Instalacidn y del Usuario Double Fusion U, esto resultaría un tanto mas problemático porque aunque tenemos las direcciones de estos registros tenemos muy poca información de como usarlos.

Programacidn de la Memoria Expandida

Programa para manejar la memoria expandida de la computadora atravéz del EMM386

Procedimiento general para usar memoria expandida por un progama de aplicación

SI

I

d5 Termina

El primer paso es verificar que el EMM este presente, esto es debe de hacer una llamada a la función obtener estado del EMM(int 67h función 40h), para asegurarse de que el hardware de la memoria expandida este presente y funcionando. El segundo paso consiste en verificar si hay suficientes paginas disponibles, donde quiera el programa puede hacer una llamada mediante la función alojar memoria(int 67h función 43h). El ultimo paso en obtener memoria expandida, es averiguar la dirección de segmento del Page- Frame mediante (int 67h función 41 h). Para implementar este programa que manejara memoria expandida, se utilizo el método "vector de interrupción" por ser el más sencillo de implementar , ya que utiliza la interrupción 67h ,este método es bueno porque inspecciona la memoria que no es propia del programa en cuestión.

#include <dos.h> #include <stdio.h>

void emmqresente(); void estado-enun(); void aloja-memoria(); void dirpg() ; void poner-mapping(); void liberar-memoria(); void contarqag();

unsigned int manejador; unsigned int PageFrame;

main0

clrscr(); emqresenteo;

/*Archivos cabecera de*/

I* Prototipos de funciones*/

I* variables de tipo global */

/* Cuerpo principal de nuestro programa*/

I* verifica que el EMM386 se encuentre presente*/

/* obtener el número de paginas del EMS*/ I* alojar una determinada cantidad de paginas*/ /* averiguar la dirección del Page-Frame*/ /* proyectar las paginas lógicas a páginas fisicas*/

liberar-memoria(); return( O);

1

/* devolver las paginas alojadas previamente*/

void emmgresente(void) { int k char fm *m, char *emmnombre = "EMMXXXXO";

clrscr(); ~=MK~FP(peek(OxO,Ox67*4+2),10);

for(k=O;k<8,ki+){ if (emombre[k] != *-)I

puts("EMM no presente"); exit(0););

puts("EMM presente"); estado-emm(); 1

-++; 1

detecta si se encuentra presente el E"386

/* Simple indice*/ I* Apuntdor al encabezado del driver EMM*l I* Nombre esperado de E"*/

/* Apunta al encabezado de E"*/ /* donde se encuentra el vector de interrupción*/ /* Compara el nombre con el encabezado*/

I* Mensaje de EMM presente*/

void estado-emm(void) /*obtiene el estado (de error) del E"*/

union REGS regs; {

regs.h.ah = 0x40, I* Este es el número de la h c i ó n del E"*/ int86(0x67, &regs, &regs); /* Llamada de la interruption 67h*/ printf ("estado del EMM %x\n",regs.h.ah); /* Muestra el estado de E"*/ 1

void dirqag(void) I* obtiene el segmento del Page-Frame*/ {

union REGS regs; regs.h.ah = 0x41; /* La función 0x41 obtiene esta dirección*/ int86(0x67, &regs, &regs); /* Llamada a la intermpción 67h*/ PageFrame=regs.x.bx; Printf ("segmento page-frame %xh",PageFrame);

1

void contarqag(void)

union REGS regs; {

regs.h.ah = 0x42;

/* obtiene el nimero de paginas totales EMSn/

I* La funcion 0x42 obtiene el número de paginas*/

int86(0x67, &regs, &regs), /* Llamada a la interrupción 67h*I printf ("Obtiene el número de paginas EMS Yódh",regs.h.ah); printf("Númer0 de paginas libres Yódh",regs.x.bx); prinf("NÚmero total de paginas EMS %dh",regs.x.dx);

1

void aloja-memoria(void) I" aloja una determinada cantidad de páginas"/

{ union REGS regs;

regs.h.ah = 0x43;

/* (1 6 Ksytes cada una) para sus propios fines*/

/* La función 0x43 obtiene la cantidad de paginas

regs.x.bx = 0x03; /* bx aloja la cantidad de paginas logicas(3)*/ int86(0x67, &regs, &regs); /* Llamada a la interrupción 67h*/ printf ("Alojar memoria EMS O/xh",regs.h.ah); manejador = regs.x.dx; /* Manejador utilizado para el registro dx*/ printf ("handle para acceder a la memoria alojada %dh",manejador);

1

void poner-mapping(void)

f union REGS regs; regs.h.ah = 0x44; regs.h.al = O;

regs.x.bx = O; regs.x.dx = manejador; int86(Ox67, &regs, &regs); printf ("estado de error %x\n",regs.h.ah);

1

void liberar-memoria(void) f union REGS regs;

regs.h.ah = 0x45;

regs.x.dx = manejador; int86(0x67, &regs, &regs); printf ("estado de error %x\n",regs.h.ah);

I

I* Proyeccta las paginas alojadas"/ /* previamente mediante la fünción aloja-memoria

/* a una de las paginas fisicas en el Page-Frame*/

/* La función Ox44 proyecta las paginas*/ /* (al) es el número de pagina fisica (O)*/ /* bx es el número de la pagina logica(O)*/ /* dx es el Manejador*/ /* Llamada a la interrupción 6%*/

I" Devuelve al E M M las paginas pedidas*/

/* Número de lafünción que devuelve las paginas*/

/* manejador de las paginas a liberar*/ /* Llamada a la interrupción 67h*/

Programacidn del TSR

El propósito de este módulo es el de construir un "esqueleto" para el programa final, es decir, un programa residente que se active cuando ocurra un error en MS-DOS, además de poder contener a las demás partes del programa.

Los programas residentes o TSR por sus siglas en inglés se componen generalmente de 3 partes (Para más información de los programas TSR's consultar el apendice A ):

Primero tenemos la parte que se encarga de salvar las funciones originales e instalar las nuestras, además de reservar espacio en memoria para crear un ambiente para nuestro programa y por último dar la orden de terminar y permanecer residente todas estas cosas deben hacerse desde el programa principal, es decir, desde el main().

La segunda parte es una función que sirve de punto de entrada a la parte útil del programa; esta parte es la que despierta cuando ocurre el evento que nosotros hayamos elegido, en este caso es la interrupción 24h que es la interrupcidn de error critico; nosotros llamamos a esta función ManejaErrorO.

Una tercera parte es el código útil, es decir la parte que hace el trabajo que necesitamos, dentro de este procedimiento es muy importante que hagamos tres cosas: primero, salvar el ambiente de la PC y crear uno propio; segundo, realizar la tarea que deseamos; y por último restaurar el ambiente y dejar que la PC continúe haciendo su labor. De esta forma logramos que cuando se active el TSR actúe como un ladrón que entra, hace su trabajo y sale sin dejar rastro alguno. (Para más información de cómo hacer esto consultar el apéndice A). Debido a que nuestra función se encargará de maneja una tarj&a de sonido la nombramos ManejaTarjetaO.

A continuación se muestra un pseudo-código que ilustra el funcionamiento general del programa

{Este es el programa principal que se encarga de instalar nuestra función en la int 24h}

Programa main() Inicia

reserva memoria para el ambiente salva la función de la int 24h instala nuestra función en la int 24h termina y permanece residente

Termina

{función de punto de entrada al TSR} proc ManejaErrorO inicia llama a la antigua funci6n de la int 24h

si (TSR no activado) entonces llama a procedimiento útil

finSi termina

{procedimiento útil} proc ManejaTarjetaO inicia salva ambiente de PC crea un nuevo ambiente

{aquí debe ir el código para manejar } {el error y reproducir los mensajes sonoros}

restaura ambiente termina

Durante el desarrollo del proyecto se intentaron diferentes formas de interceptar a la interrupción 24h; lo primero que intentamos fue el de sustituir la función que atiende a la interrupción 24h por nuestra función de punto de entrada al TSR. Esto coincide básicamente con el pseudo código anterior; a continuación se presenta el listado del primer programa utilizado.

#include "dos.h" #include "stdi0.h #include "stdlib.h" #include "fcntlh"

#define STK-SIZE Ox2000 #define bandera 245

unsigned int permiso = 1,instalado = O,sp,ss,dl;

int fd,el ,e2,oldX,oldY; /* variables para probar reentrada */

union REGS r; struct SREGS S;

unsigned char stack[STK_SIZE]; /* reserva memoria para la pila */

void interrupt (*oid-int24)0; void interrupt maneja-mor(void); void maneja-tarJeta(void);

/*interruption de error critico*/ /* nueva int 24h */

main0 /* programa principal*/ { old-int24 = getvect(Ox24); /* obtiene la direccion de las ISR viejas*/ setvect(Ox24, maneja-mor), In redirecciona las nuevas interrupciones * I puts("W1 manejador de Errores está instalado!\n"); /* termina y queda residente*/ keep(0,4000); f

void interrupt maneja-error0

el =-dosermo; e2=errno; dl=-DL; (*old_int24)0; i f (permiso){

permiso4; maneja-tarJeta(); permiso=l;)

1

1

I* nueva interrupcion de error critico*/

/* llama a la antigua INT 24h*/ /* si no esta activa, activala*/

void maneja-tarjeta(void)

char far *old-dk, {

disable(); ss=-ss; Sp-SP; - SS=-DS; - SP=(unsigned) &stack[STK-SIZE-2]; enable(); old-dta = getdta(); setdta(MK-FP(~sp,OxSO));

oldX=wherex( ), oldY=wherey();

I* procedimiento para manejar la tarjeta *I

/* inhibe las interrupciones*/ I* salva la pila*/

I* activa interrupciones*/ /*salva el psp*/

I* aqui empieza el manejo de la tarjeta*/ /* usando funciones que provocan condiciones de*/

gotoxY( 1,1), /* reentrada*/ printf("dos-Yd err-Yód cr-Yód",-dosermo,el ,dl); gotoxy(oldX,oldY); /*termina el manejo de la tarjeta*/

setdta( old-dta); disable(); - SP=sp; - ss=ss; enable(); I Como podemos notar en este programa existen las tres partes importantes del desarrollo de un TSR además de incluir algunos procedimientos auxiliares; la función ManejaErrorO es el punto de entrada a nuestro TSR, ManejaTatjefaO es la encargada de realizar el trabajo útil, por último tenemos al programa principal main() que es la parte instaladora de los procedimientos anteriores.

Las variables globales utilizadas son para el manejo del ambiente y el control del TSR, tratamos de usar el menor número de variables globales.

Además dentro de la función ManejaTcCrjeta usamos las funciones gofoxyo y para, comprobar que no tenemos prablemas de reentrada, estas funciones utilizan llamadds a MS-DOS, estas fliHciones lo único que hacen es poneE un número en la esquina superior izquierda cuando se genera la int 2M.

Cuando probamos el programa nos dimos cuenta que esto no funcionaba bien, pues parecía como si no hubiésemos instalado ningún programa residente, es decir, no pasaba nada cuando provocábamos un error critico, especificamente, dejábamos abierta la unidad A y tratábamos de accesarla.

Entonces decidimos utilizar una interrupción diferente para despertar a nuestro TSR, usamos la interrupción h9, la interrupción del teclado, cuando realizamos esto, el programa dio el efecto esperado, al presionar cualquier tecla aparecían los números en la esquina de la pantalla. El listado de este programa es muy similar al anterior y sólo se sustituye la int 24h por la int 9h.

Una vez realizado lo anterior, nos dimos cuenta que la interrupción 24h tiene un trato especial por parte de MS-DOS, es decir, mientras el programa principal estaba en ejecución todo funcionaba perfectamente, se instalaron correctamente las funciones que necesitábamos, pero el problema se presenta cuando se le da la orden de terminar y permanecer residente MS-DOS restaura automáticamente la función original de la interrupción 24h. Esto lo pudimos corroborar con la información encontrada en el libro PC Interno, donde se desarrolla un programa no residente el cuál se hace cargo del manejo de errores usando la int 24h, mientras se ejecuta este programa permanece instalada una función que se encarga de manejar los errores, pero al terminarse el programa no restaura la interrupción 24h, pues según se explica, MS-DOS lo hace automáticamente.

Para ilustrar esta situación se usa la siguiente figura.

original

I NT 24 En algun lugar de la memorla

Tabla de interrupciones función

Antes de instalar la Int 24

original

función

k l Nueva funcidn instalada

Original

Condicidn que se presenta cuando se termina y se hace , residente

funci6n

Otra forma de corroborar lo anterior es modificando la función de ManejaError para que no haga nada cuando se genera el error, esto sería equivalente a un Cancelar cuando MS-DOS envía el mensaje de Abort, Cancel or Retry?. La función quedaría así.

proc ManejaError inicia

(No hacer nada} termina

La segunda idea que probamos fue la de hacer que la INT 24h fuera sustituida por la nuestra pero después de terminar el programa, para esto planeamos auxiliarnos de la interrupción de reloj.

La idea principal era la de dejar instalada una función en la INT 8h de manera que cuando se activara esta interrupción después de terminar el programa se encargara de instalar nuestra función. El pseudo-código de esta función es el siguiente:

proc Nuevalnt80 inicia si int 24h no instalada

fin si termina

instala int 24h

Este programa mostró el mismo comportamiento que el anterior, es decir, parecía como si no se hubiera instalado ninguna interrupción, nosotros creemos que cuando se instala esta función en la INT 24h solo queda instalada por algunos momentos que son insuficientes para mostrar algún signo de que esta funcionando.

El código completo de este programa se muestra a continuación:

#include "d0s.h" #include "stdio.h" #include "std1ib.h" #include "fcntl.h

#define STK-SIZE Ox2000 #define bandera 245

unsigned int permiso = 1, instalado = 0, sp,ss,dl;

int fd,el,eZ,oldX,oldY;

union REGS r; struct SREGS S;

unsigned char stack[STK_SIZE];

void interrupt (*old-intS)(>; void interrupt (*old_int24)();

void interrupt nueva_int8(void); void interrupt maneja-error(void);

/* variables para probar reentrada *I

/* reserva memoria para la pila*/

/*intempcion de reloj */ /*intenupcion de error critico*/

/* nueva int 8h *I /* nueva int 24h */

void maneja-tarJeta(void),

main0

old-int8 = getvect(Ox8); old-int24 = getvect(Ox24);

setvect(8, nueva-int8); puts("W1 manejador de Errores quedo instalado!\n"); keep(0,4000); 1

{

void interrupt nueva-intO(void) f

(*old_int8)();

if (!instalado){ setvect(Ox24, maneja-error); instalado= 1 ; 1

1

void interrupt maneja-error0 i el =-dosenno; e2=emo; dl=-DL; (*old_int24)0; if (permiso) f

permiso=o; maneja-taqeta(); permiso=l ; 1

1

void maneja-tarjeta(void) { char far *old-dta; disable(); ss=-ss; Sp=-SP; - SS=-DS;

&able(); old-dta = getdta(); setdta(MK_FP(qsp,Ox80));

SP==unsigned) tstack[STK-SIZE-2];

I* programa principal*/

/* salva vectores de INT antiguos*/

/* redirecciona las nuevas interrupciones */ I* termina y queda residente*/

I* activa el residente en cada INT8*I

/* llama a la antigua intmpcion 8 */

I* nueva interrupcion de error critico *I

/* activa la antigua INT 24*/ /*Si no esta activada activala*/

I* procedimiento para manejar la tarjeta*/

I*------- aqui empieza el manejo de la taqeta */

oldX=wherex(); oldY=wherey( ),

printf("dos-o/od err-Vód cr-%d",-doserrno,el ,dl); gotoxy(oldX,oldY);

gotoxy( 1 > 1);

setdta(o1d-dta); disable(); - SP=sp; ss=ss;

enable(); 1

Otro de los intentos realizados, fue uno en el que usamos una bandera de las llamadas indocumentadas de MS-DOS, nos referimos a la bandera de critical error esta es una bandera que se pone en uno cuando se está en una condición de error dentro de MS-DOS y se borra cuando este error se soluciona.

Para obtener la dirección de esta bandera es necesario saber la versión de MS-DOS que se está usando; si la versión es menor a la versión 3.0 esta bandera estará un byte antes que la bandera de dos activo, esta es otra bandera de las indocumentadas de MS-DOS, si la versión es mayor se debe utilizar la INT 5D06h la cuál nos regresará la dirección de esta bandera en dos registros del microprocesador: ds y si.

También dentro de este nuevo intento nos auxiliamos de otra de las llamadas interrupciones indocumentadas, la INT 28h, esta se activa cada vez que MS-DOS no hace nada, es decir cuando espera una respuesta del usuario. Pensamos en usar esta interrupción puesto que cuando MS-DOS manda el mensaje de Cancel, Retry , Abort? espera a que el usuario introduzca una respuesta.

#include "dos.h" #include "stdi0.h" #include "std1ib.h" #include "fcntl.h"

#define STK-SIZE Ox2000 #define bandera 245

unsigned int permiso = 1, sp,ss,dl;

int fd,el ,e2,oldX,oldY;

union REGS r; struct Sl2EGS S;

unsigned char stack[STK-SIZE];

char far *crit-erroFO; char far *dos-activo=O;

void interrupt (*old_int28)();

void interrupt nueva-int28(void);

void maneja-tarjetatvoid);

main() {

r.h.ah = 0x34; int86x(Ox21 ,&r,&r,&s); dos-activo = MK_FP(s.es,r.x.bx);

if (-osmajor<3) crit_error-dos-activo+l;

else if (-osmajor==3 && - 0 s m i n 0 ~ 0 ) crit-error=dos-activo-1;

else { r.h.ah=Ox5W6; int86x(Ox2 1 ,&r,&r,&s); crit-error=~-FP(s.ds,r.x.si); 1

/* variables para probar reentrada */

/* reserva memoria para la pila */

/*interruption de dos seguro*/

I* nueva int 28h*/

/* programa principal*/

/* obtiene la bandera de DOS-ACTNO*/

I* obtiene la bandera CRIT-ERROR */

oldiint28 = getvect(Ox28); /* obtiene la direccion de las ISR viejas*/ setvect(Ox28, nueva-int28); /* redirecciona las nuevas interrupciones*/ puts("bE1 manejador de Errores quedo instalado!\n"); /* termina y queda residente */ keep(0,4000), 1

void interrupt nueva-int28(void) { (*old_int28)0; if (*crit-error && permiso) {

permiso=o; maneja-tarJeta(); permiso=l; 1

f void maneja-tarjeta(void) f char far *old-dta;

I* nueva interrupcion de dos seguro "I

I* Si hay un error critico activa manqa-tatjeta*/

I' procedimiento para manejar la tarjeta "I

disable(), ss=-ss; sp-SP; - SS=-DS;

&able(); old-dta = getdta(); setdta(hac_FP(~sp,Ox80));

I*------ aqui empieza el manejo de la tarJeta -----------*/ oldX=wherex(); oldY=wherey(); gotow( 1 > 1 1; printf("dos-%d err-Yd cr-%d",-dosermo,emo,*crit-error); gotoxy(oldX,oldY);

SP=(unsigned) &stack[STK_SIZE-2];

setdta( old-dta); disable(); - SP=sp; - ss=ss; enable( ), 1

El comportamiento de este programa fue un poco mejor que los anteriores, pues si se activaba la función maneja tarjeta, pero no cuando estaba planeado, como se mencionó anteriormente, esta función se debe de activar cuando se genera un error en MS-DOS; esta función permanece activa siempre que MS-DOS no hace nada, esto fue un tanto sorpresivo, pues esto quiere decir que no estamos encontrando la dirección de la bandera de critical error, pues dentro de los mensajes que se mandan dentro de esta función incluye el valor de esta variable y siempre nos manda un mismo número sin importar que se este en estado de error o no.

Otro de los intentos realizados fue similar al anterior, sólo que en vez de usar la INT 28h usamos nuevamente la INT 8h (de reloj); el comportamiento de este programa fue menos eficiente, pues a pesar de que si mandaba los mensajes, hacía que la maquina se quedara dormida. El listado completo se muestra a continuación.

#include "d0s.h" #include "stdioh" #include "std1ib.h #include "fcntl.hf #defme STK-SIZE Ox2000 #define bandera 245 unsigned int permiso = 1,

int fd,el,e2,oldX,oldY; union REGS r; struct SREGS S;

unsigned char stack[STK_SIZE]; char far *dos-activo=O; char far *crit-error=O; void intermpt (*old-intS)(); void interrupt nueva_int8(void); void maneja-mewvoid);

sp,ss,dl; /* variables para probar reentrada */

/* reserva memoria para la pila*/

/* intermpcion de reloj*/ /* nueva int 8h*/

/* programa principal*/

/* obtiene la bandera de DOS-ACTIVO*/

/* obtiene la bandera Cm-ERROR*/

main0

r.h.ah = 0x34; int86x(Ox21,&r,&r,&s); dos-activo = m-FP(s.es,r.x.bx); if (-osmajor<3)

crit-error=dos-activo+l; else if (-osmajorz3 && -osminor==O)

crit-errodos-activo-l ;

r.h.ah=Ox5D06; int86x(Ox2 1 ,&r,&r,&s); crit_error=~-FP(s.ds,r.x.si); 1

{

else {

old-int8 = getvect(8); /* obtiene la direccion de las ISR viejas*/ setvect(8, nueva-int8); /* redirecciona las nuevas intmpciones*/ puts("hE1 manejador de Errores quedo instalado!W); /* termina y queda residente*/ keep(0,4000);

void interrupt nueva_int8(void) /* nueva interrupcion de reloj*/

(*old-int8)(); /* llama a la antigua intmpcion 8h*/ if (*crit-error ¿U permiso) { /*Si hay un error critico lactiva a maneja-tarjeta*/

1

permisPo; maneja-meta(); permiso=l; 1

1

void maneja-tarjeta(void) /* procedimiento para manejar la tarjeta * I

{ char far *old-dta;

disable(); ss=-ss; sp=-SP; - SS=-DS; - SP=(unsigned) &stack[STKSIZE-2]; enable(); old-dta = getdta(); setdta(MK_FP(gsp,Ox80)),

/*------- aqui empieza el manejo de la *eta

oldX=wherex(); oldY=wherey(); gotov( 1 ,I >; printf("d0s-%d err-o/od cr-0/od",_dosermo,ermo,*crit-error); gotoxy(oldX,oldY);

setdta(o1d-dta); disable(); - SP=sp; ss=ss;

&able(); 1

Además de estos intentos se realizaron otros que no se incluyen aquí por considerar que no presentan aspectos nuevos por que su funcionamiento fue inferior a los anteriormente mostrados.

Conclusiones

Prácticamente durante el desarrollo del proyecto se presentaron dos grandes problemas; el primero de ellos fue que no logramos detectar, dentro del programa residente, el momento en que se genera un error critico. Este evento sólo lo pudimos detectar dentro de programas que no eran residentes; es muy fácil sustituir la función original que atiende a la INT 24h dentro de programas normales, el procedimiento es muy parecido al primer intento hecho solo que no se le da la orden de terminar y permanecer residente, esto es muy usado cuando se desea hacer un programa que se haga cargo del manejo de errores criticos.

Como se menciona en la sección programacic5n del TSR el problema se presenta precisamente cuando se le da la orden de terminar y permanecer residente; que es cuando automaticamente se restaura la INT 24h.

Consideramos que para lograr el objetivo necesitaríamos hacer uso de funciones de MS-DOS que no conocemos (de las que todavía no están documentadas); por ejemplo una opción que nosotros pensamos que podría funcionar es sobre escribir la función que atiende a la INT 24h con una hecha por nosotros mismos, pero en este caso tendríamos que hacer una función que se hiciera cargo de prácticamente todos los errores que se puedan presentar y el punto más importante, tendríamos que saber donde se aloja esta función y cuanto espacio ocupa para asegurar que no vamos a sobre escribir la memoria que está a continuación de esta función.

Podemos mencionar que cuando modificamos el TSR para trabajar con otras interrupciones como la de teclado (INT 9h) en vez de la de error citico este funcionó perfectamente, de aquí, podemos tomar elementos para el desarrollo de proyectos relacionados con la simulación de multitarea dentro de MS-DOS.

El segundo problema fue que no logramos obtener información respecto a la programación de la tarjeta de sonido que se planeaba usar, se consultó la guia de usuarios de esta tarjeta donde encontramos las direcciones de memoria de todos los registros de esta, pero, no explicaba para que se usaba cada registro ni cuales eran los valores posibles para estos.

También consultamos el libro The Sound Blaster Book el cuál nos dió una idea de como sería la programación de esta tarjeta, la información encontrada en este libro incluye el cómo usar archivos . VOC; los programas usados requerían de un driver llamado C7-VO/C€.DRV el cuál se consiguió pero no funcionó con nuestra tarjeta a pesar de que en el manual se asegura que es compatible con la Sound Blaster, cuando intentamos cargar este driver la computadora se quedaba "dormida".

De los aspectos positivos podemos mencionar que logramos en un 100 % la construcción de las funciones para hacer uso de la memoria expandida, las funciones construidas quedaron listas para ser usadas en cualquier programa, incluyendo a los programas residentes.

Apendice A

Los programas residentes han estado presentes en MS-DOS desde su primera aparición en 1981, con el programa MODE.COM; los programas PRINT, GRAPHICS y ASSIGN fueron agregados en DOS 2.x. PRINT es la única utilidad de MS-DOS que simula la multitarea. Se puede correr una aplicación al mismo tiempo que PRINT esta imprimiendo un archivo. Sólo un programa trabaja a la vez, pero se da la ilusión de multitarea alternándose para trabajar en cada pulso de reloj de BIOS.

Técnicamente un programa residente es aquel que llama a la INT 21h Función 31 h, El propósito de esta función es el de terminar un programa y hacer que el bloque inicial de memoria sea aquel donde termina el programa que se está terminando. Esta función de MS-DOS es muy parecida a la INT 21h Función 4Ch, la cuál termina el programa pero libera la memoria que estaba siendo usada.

Así un TSR es algún programa DOS que deja una parte del mismo antes de terminar. Esto puede parecer como un error en un programa que usa memoria y nunca la libera. Existe otra función indispensable en la construcción de programas residentes, "Set Interrupt Vector", todas las computadoras basadas en la arquitectura Intel 80x86, permite a cualquier programa instalar código que sea llamado cuando se genera un interrupción de hardware o software. Esta función es usada para apuntar los vectores de interrupción hacia nuestro código y entonces llamar a una función 4Ch de la INT 21 h para dejar residente nuestro código con su respectiva pila y área de datos. De esta manera cuando se genere la interrupción que hayamos elegido, nuestro código tomara el control de la computadora.

De esta forma cuando PRINT esta instalado en memoria, esta encadenado a la interrupción del fick de reloj (INT 1 Ch), a la interrupción "DOS seguro" (INT 28h) la cual se llama cada vez que MS-DOS está sin hacer nada, pudiendo tomar el control de la computadora a intervalos regulares y desarrollar la tarea de procesar archivos (abrir, imprimir y cerrar).

Uno de los problemas que se presentan con los TSR's es que MS-DOS es un sistema "mono tarea", en otras palabras, no se le debe interrumpir a la mitad de una tarea para desarrollar otra y regresar a terminar la primer tarea. Esta característica es comúnmente llamada como "no reentrada", esto significa que si una INT 21 h se está ejecutando, no se puede ejecutar ninguna otra INT 21h . Un programa o función "reentrante" puede interrumpirse en cualquier momento permitiendo entrar a otras funciones o programas sin perder el estado de la función antes de la interrupción.

La mayoría de los programas residentes no tienen control sobre el momento en que serán llamados, puesto que generalmente están encadenados a interrupciones que no sabremos cuando se generarán, por ejemplo, un programa TSR que esté ligado a la interrupción del teclado no podrá predecir cuando el usuario presione las teclas que lo hagan despertar; el problema se presenta cuando se intenta invocar a un TSR cuando la computadora está realizando alguna tarea que no puede ser interrumpida, como por ejemplo leer algún disco o imprimir un archivo, esto generalmente dará como resultado una maquina muerta.

Para solucionar este problema existe una bandera que se enciende cuando MS-DOS es seguro de interrumpirse y se apaga cuando no puede ser interrumpido, aunque esto no es suficiente para saber cuando es posible interrumpir a MS-DOS; también se debe tener en cuenta una interrupción; la INT 28h, mencionada anteriormente.

Existe otro problema con MS-DOS y los programas residentes cuando estos implican actividad de disco. MS-DOS transfiere información de disco en la DTA (disk transfer area) reservada para cada programa. El DTA es parte del PSP (program segment prefix) que tienen todos los programas. Cuando un TSR interrumpe a otro programa, hereda el PSP de el otro programa. De esta forma, si se lleva cualquier actividad de disco se corre el riesgo de sobre escribir información que esta en el DTA del otro programa. Debido a esto es necesario que el TSR salve la DTA del programa y use la propia y al final restaure la DTA antigua.

Cuando MS-DOS es invocado usando la INT 21 h, usa una de las tres pilas internas: la pila I/O, la pila de Disco, o la pila Auxiliar. Las funciones desde la OOh hasta la OCh usan la pila 110. Las funciones restantes usan la pila de Disco. Cuando MS-DOS es llamado durante un error critico se usa la pila Auxiliar.

Apendice B

Memoria expandida y el EMS.

La memoria expandida es esencialmente un banco de memoria conmutada de almacenamiento rápido, el cual puede ser tan grande que el espacio de direcciones del CPU normal, y el cual es subdividido en pedazos pequeños (llamados paginas) que pueden ser independientemente mapeadas dentro o fuera del espacio de direcciones del CPU en demanda. Como una simple aproximación, tu puedes pensar en la memoria de banco conmutada como una cubierta de tarjetas, donde la información diferente puede ser almacenada en cada tarjeta, pero solamente la información en la tarjeta que es común en el tope de la cubierta puede ser leído o cambiado.

La memoria de banco conmutada no es exactamente un nuevo concepto. esto fue usado extensivamente en el Bus de las computadoras Apple II y S-100.para vencer las limitaciones de direcciones de 64 Kb de sus CPU's y en nuestros días la IBM PC.

Componentes de la Memoria Expandida.

Es importante no confundir la memoria expandida y la memoria extendida. Ambas están frecuentemente disponibles en la misma máquina, en realidad, muchos tableros de memoria pueden estar arriba para proporcionar otra memoria expandida o memoria extendida o una mezcla de ambas. Pero la memoria extendida puede solamente ser accesada en el modo protegido de los procesadores 80286, 80386, y 80486, puesto que la memoria expandida puede ser accesada en el modo real y por consiguiente puede ser instalada y usada en las maquinas basadas en el 8086188 como la PC original y la PC/XT.

Cuando tu instalas la memoria expandida en tu Computadora, tu estas realmente instalando un subsistema Hardware/Software integrado cerradamente(se puede ignorar el emulador EMS y los simuladores por el momento). En más casos, la parte del hardware que tapa el tablero, tiene los mismos elementos de un tablero de memoria ordinaria y algunos un adaptador para un dispositivo periférico: Esto es como chips de memoria, para estar seguros, pero también puertos de I/O, los cuales pueden ser escritos por el CPU para crear partes de memoria direccionable.

Los componentes del Software de un subsistema de Memoria Expandida es llamado el Administrador de Memoria Expandida (EMM). esto es instalado cuando el subsistema es booteable, con una directiva DEVICE en el archivo CONFIG.SYS.

En realidad, un EMM tiene diferentes de los atributos de un driver de caracter real: Esta es una cabecera del driver device, una rutina que puede encabezar un subconjunto de las peticiones que el kernel desea hacer a los drivers device y tiene un nombre de dispositivo lógico, este nombre de dispositivo es siempre EMMXXXXO, sin tomar en cuenta a los fabricantes del tablero de memoria expandida o escribir el EMM.

Los principales trabajos de los EMM's son para controlar el hardware de la memoria expandida, para administrar la memoria expandida como un sistema que puede ser usado por muchos programas diferentes, y para servir a las funciones llamadas, definidas en el EMS. La petición de los programas de esas funciones de memoria expandida desde el EMM directamente, vía una interrupción del software que MS-DOS considera "reservada", el kernel de MS-DOS no participa en la administración de la memoria expandida.

El número de la función del EMS esta siempre colocada en el registro AH, los números de las paginas lógicas tipicamente van en el registro BX, los encabezados de la memoria expandida en el registro DX. El control es transferido desde el programa de aplicación al EMM al ejecutar el software de la int 67h. Todas las funciones del EMS indican sucesos al retornar un cero en el registro AH, o una falla al retornar un código de error en el registro AH con la colocación del bit más significativo.

tabla 1 .O Resumen de las funciones del EMS más comúnmente usadas en los programas de aplicación.

Funcidn de la memoria expandida Entrada Salida Obtener el estado del EMM AH=40h AH=Estado del EMM

Averiguar dirección de AH=41 h AH=Estado del EMM

segmento del Page-Frame

Obtener el número de paginas EMS AH=42h AH=Estado del EMM

BX=Número de las paginas

libres aun no alojadas.

DX=Número total de paginas

EMS.

Alojar memoria EMS

Poner mapping

AH=43h AH=Estado del EMM

BX= Cantidad de paginas

logicas a alojar (cada una de

16 Kb)

AH= 44h AH= estado del EMM

Intempci6n 67h, Funcidn 40h (Obtener el estado del E")

Esta función averigua el estado (de error) del administrador de memoria expandida(EMM), como también se devuelve después de la llamada de todas las demás funciones EMS.

Interrupcidn 67h, Funcidn 41 h (Averiguar direccidn de segmento del Page-Frame).

La dirección de segmento del Page-Frame se averigua mediante la llamada a esta función.

lnterrupcidn 67h, Funcidn 42h (Obtener el número de paginas EMS).

Esta le indica al invocador, cuantas paginas EMS(cada una de 16 KB) hay instaladas, y cuantas quedan libres, es decir no están alojadas.

Interrupcidn 67h, Funcidn 43h (alojar memoria EMS).

Con ayuda de esta función, un programa puede alojar una determinada cantidad de paginas( 16 KB cada una) para sus propios fines.

lnterrupcidn 67h, Funcidn 44h (Poner Mapping).

Mediante la llamada a esta función realiza la proyección de las paginas alojadas previamente mediante la función 43h a una de las paginas físicas en el Page-Frame.

Interrupcidn 67h, Funcidn 45h (liberar paginas).

Las paginas alojadas previamente por la función 43h se pueden volver a devolver al EMM con ayuda de esta función, y hacerlas accesibles para otros programas.

Interrupcidn 67h, Funcidn 46h (Obtener versidn de EMS).

Con ayuda de esta función se puede obtener el número de versión del EMM (Expanded memory Manager).

AH=estado del EMM

OOh: todo 0.k. 80h: Error interno, EMM posiblemente destruido 81 h: Funcionamiento erróneo 82h: Expanded memory Manager está ocupado 83h: Handle erróneo 84h: la función llamada no es soportada 85h: No quedan Handles disponibles 86h: Error al guardar o reposicionar la proyección entre paginas

87h: Se pidieron más paginas de las que físicamente hay disponibles 88h: Se pidieron más páginas lógicas de las que quedan libres 89h: Se intentaron alojar O páginas 8Ah: Número de página lógica no válido 8Bh: Número de página física no válido 8Ch: Zona de memoria para tabla de seguridad está llena 8Dh: Zona de seguridad ya contiene una tabla de seguridad para el Handle indicado 8Eh: No existe tabla de seguridad para el Handle especificado 8Fh: Número de subfunción especificado incorrectamente errores que solo pueden aparecer a partir de la versión 4.0 90h: tipo de atributo no esta definido 91h: No se soporta característica 92h: Zona fuente y destino se solapan, una parte de la zona ha sido sobrescrita 93h: longitud indicada es mayor que la longitud real de la zona 94h: La zona convencional y la zona de la memoria EMS se solapan 95h: El offset indicado queda fuera de la página lógica 96h: La cantidad de bytes a procesar es mayor que 1 MB 97h: Zona fuente y destino tienen el mismo Handle, el intercambio no se realizo

lógicas y físicas

98h: No se definió el tipo de zona de memoria para fuente y destino 99h: Código de error sin utilizar 9Ah: No se soporta juego de registros alternativos indicado 9Bh: Todos los juego de registros alternativos están alojados 9Ch: No se soportan juegos de registro, y juegos de registro no es número cero 9Dh: Juego de registro alternativo indicado no esta definido o alojado 9Eh: No se soportan canales DMA dedicados 9Fh: Canal DMA dedicado especificado no es válido AOh: No se encontró Handle bajo el nombre indicado Alh: Ya existe un Handle con ese nombre A2h: Rebase de direcciones en 1 MB A3h: Pasado puntero invalido, o contenido del buffer indicado es incorrecto. A4h: Acceso a la función se impidió por el sistema operativo

Obteniendo acceso a la memoria expandida.

Cuando nosotros deseamos usar memoria expandida en uno de nuestros programas, el primer paso es establecer si el EMM esta presente o no. Esto se puede hacer por uno de los dos métodos que existen: El método de "abrir el archivo" y el método del "vector de interrupción". El método de "abrir el archivo" es llamado así por que se basa en la interrupción 21 h función 3dh para abrir el EMM por su nombre lógico en el

El método del "vector de interrupci6n" detecta el EMM, si este esta instalado, utilizando la interrupción 67h para capturarlo, por colocar una dirección de la función del EMS llamada como un punto de entrada del vector.

MS-DOS.

Memoria EMS

F F F F _ r Em entana EMS

Am Memoria Principal > Paginas de 16 KBytes

Figura 1. Diagrama de muestra para ver como accesa la memoria EMS

Figura l. Diagrama de muestra para ver como accesa la memoria EMS.

Bibliografia

PC Interno, Michael Tischer, editorial marcombo. Undocumented DOS, Second Edition, Andrew Schulman, Ralf Brown, David

Maxey, Raymon J. Michels, and Jim Kyle, editorial Addison-Wesley. Guía de instalación y del usuario,Media Vision. The Sound Blaster Book, Axel Stolz. editorial Abacus. PC Interrupts, Brown Kyle, Second Edition, editorial Addison-Wesley.

Speech Communication, Homan and Machine Douglas O'Shaughnessy, INRS- Telecommunications

editorial Addison-Wesley Publishing Company. Extending Dos, Ray Duncan, editorial Addison-Wesley.