(Solución alternativa práctica guiada I)

Anuncio
Disseny de Sistemes Operatius
Enginyeria en Informàtica
Curs 2008/2009
Soluciones alternativas a las tres primeras
prácticas guiadas
Solución alternativa práctica guiada I
#include <stdio.h>
#include <dos.h>
void interrupt beep(...)
{
/*
1.- BP debe apuntar a la base de la nueva pila
asm push bp
asm mov bp, sp
Ya lo hace el compilador. Si lo hiciésemos nosotros,
no retornaríamos bien a la funcion llamante
2.- Se deben guardar todos los registros susceptibles de cambiar
asm push di
asm push si
…
asm push ax
Esto ya lo hace el compilador porque hemos declarado beep
utilizando la palabra clave “interrupt”
*/
/*
Retardo del bucle */
unsigned long int i = 0;
unsigned long int j = 0;
/*
CTRL de temporizador para programar
contador 2 a modo 3. B6hex = 1011 0110
*/
outportb(0x43, 0xB6);
/*
Configuramos frecuencia onda cuadrada
que generara contador 2
*/
outportb(0x42, 0x27);
outportb(0x42, 0x10);
/*
Ponemos a 1 los dos ultimos bits buffer B del 8255*/
outportb(0x61, inportb(0x61) | 0x03);
/*
Bucles de espera*/
i=0;
while(i < 10000)
{
j=0;
while(j < 65535)
{
j++;
}
}
i++;
/*
Desactivamos contador y altavoz*/
outportb(0x61, inportb(0x61) & 0xFC);
/*
1.- Sacamos en orden inverso todos los registros que se introdujeron en la pila
asm pop ax
…
asm pop si
asm pop di
asm push bp
asm mov bp, sp
Esto ya lo hace el compilador porque hemos declarado beep
utilizando la palabra clave “interrupt”. Si lo hiciésemos nosotros,
no retornaríamos bien a la funcion llamante
2.- Restauramos el bp de la pila
asm mov sp, bp
asm pop bp
asm IRET
*/
En realidad, no hace falta hacer esto, porque
el compilador ya pone este codigo por nosotros.
Si lo hiciéramos, no pasaría nada; porque ejecutaríamos
IRET antes de que se ejecutase el codigo de retorno
que pone el compilador (lo haríamos antes que el).
}
void main()
{
void interrupt (* viejaRutina)(...);
asm cli
viejaRutina = getvect(0x7F);
setvect(0x7F, beep); // Enganchamos nuestra ISR
asm sti
geninterrupt(0x7F);
}
setvect(0x7F, viejaRutina); // Restablecemos la antigua ISR
Solución alternativa práctica guiada II
#include <stdio.h>
#include <dos.h>
void far beep(unsigned p, unsigned long d)
{
/*
1.- BP debe apuntar a la base de la nueva pila
asm push bp
asm mov bp, sp
*/
Ya lo hace el compilador. Si lo hacemos nosotros,
no retornaremos bien a la funcion llamante
/* Guardamos los registros que vamos a cambiar */
push ax
push cx
/*
CTRL de temporizador para programar
contador 2 a modo 3, onda cuadrada
*/
outportb(0x43, 0xB6);
/*
Configuramos frecuencia onda cuadrada
que generara contador 2
*/
asm mov ax, word ptr [bp + 6] /* Obtenemos el periodo de la señal */
asm out 0x42, al
/* Hacemos output del periodo*/
asm mov cl, 8
asm shr ax, cl
asm out 0x42, al
/*
Ponemos a 1 los dos ultimos bits buffer B del 8255
*/
outportb(0x61, inportb(0x61) | 0x03); /* Empieza cuenta*/
/* Obtenemos la duracion de la señal */
asm mov ax, [bp + 10]
asm mov cx, [bp + 8]
/*
Bucle de espera*/
bucle:
asm loop bucle
asm dec ax
asm mov cx 0FFFFh
asm JNE bucle
/* Desactivamos contador y altavoz*/
outportb(0x61, inportb(0x61) & 0xFC);
/* Recuperamos los registros que hemos cambiado */
asm pop cx
asm pop ax
/*
1.- Restauramos el bp de la pila
asm mov sp, bp
asm pop bp
asm RETF
}
main()
{
}
*/
En realidad, no hace falta hacer esto, porque
el compilador ya pone este codigo por nosotros.
Pero si lo hiciésemos, no pasaría nada; porque ejecutaríamos
RETF antes de que se ejecutase el codigo de retorno
que pone el compilador (lo haríamos antes que el).
unsigned long i = 0;
for (i=1; i < 65535; i+=1000)
{
beep((unsigned) i, 1000);
}
Solución alternativa práctica guiada III
#include <stdio.h>
#include <dos.h>
#define MAX_BUFF_SIZE 32769
char
unsigned int
unsigned int
char far *
unsigned int
// Tamaño maximo del buffer
buffFile[MAX_BUFF_SIZE];
buffIndex;
numCharsBuff;
buffIni;
salir;
// Buffer de caracteres
// Indice para recorrer buffer
// Numero de caracteres almacenados
// Direccion del buffer
// Flag para salir del programa
void far interrupt imprimirCaracter(...)
{
// Guardamos los registros a utilizar en la pila
// (ya lo hace el compilador con "interrupt")
// Comprobamos que no hayamos imprimido ya todo el buffer
asm mov bx, word ptr numCharsBuff
asm mov ax, word ptr buffIndex
asm mov cx, ax
asm sub ax, bx
asm jnz imprimir
// Cargamos tamaño buffer
// Cargamos indice buffer
// Guardamos indice buffer
asm mov word ptr salir, 1
asm jmp fin
// Indicamos salida bucle expera main
// Si aun hay caracteres por impr
// saltar a "imprimir"
imprimir:
// Obtenemos direccion caracter a imprimir
asm lds bx, dword ptr buffIni
asm add bx, cx
// Cargamos segment y offset buffer
// Obtenemos offset caracter a imprimir
// Incrementamos indice buffer
asm inc cx
asm mov word ptr buffIndex, cx
// Especificamos parametro para funcion
// de impresion DOS
asm mov dl, byte ptr ds:[bx]
//asm mov dl, 0x7E
// Invocamos a la funcion de impresion DOS
asm xor ax, ax
asm mov ah, 0x02
asm sti
asm int 0x21
fin:
;
}
// El compilador ya recupera los registros de la pila,
// debido a que hemos declarado la funcion como “interrupt”
int leerFichero (const char * nomficSrc)
{
FILE *
handleSrc;
// Puntero a fichero
char
readChar;
// Caracter leido
unsigned int
buffAuxIndex;
// Indice para rellenar buffer
// Abrimos el fichero de origen
printf("\nEl fichero a abrir es: %s\n", nomficSrc);
handleSrc=fopen(nomficSrc, "r");
if (handleSrc==NULL)
{
printf("Error al abrir el fichero de origen: %s \n", nomficSrc);
return -1;
}
// Leemos el fichero en el buffer
buffAuxIndex = 0;
readChar= (char) fgetc(handleSrc);
while (readChar != EOF && buffAuxIndex < (MAX_BUFF_SIZE - 1))
{
// Si el caracter es retorno de carro,
// lo sustituimos por un retorno de carro
// (ASCII code = 13) y añadimos nueva linea
// (ASCII code = 10)
if (readChar == '\n')
{
buffFile [buffAuxIndex] = (char) 13;
buffAuxIndex += 1;
}
else
{
}
if (buffAuxIndex < (MAX_BUFF_SIZE - 1))
{
buffFile [buffAuxIndex] = (char) 10;
buffAuxIndex += 1;
}
buffFile [buffAuxIndex] = readChar;
buffAuxIndex += 1;
readChar= (char) fgetc(handleSrc);
}
buffFile[buffAuxIndex] = '\0';
numCharsBuff = buffAuxIndex;
fclose(handleSrc);
return 0;
}
void main(int argc, char* argv[])
{
void far interrupt (* viejaRutina)(...);
int lectura;
char c;
lectura = leerFichero (argv[1]);
if(lectura == -1)
{
printf("Error al abrir el fichero\n");
}
else
{
// Inicializamos vars acceso a buffer
// y flag salida de programa
buffIndex = 0;
buffIni = (char far *) buffFile;
salir = 0;
// Instalamos nuestra ISR
asm cli
viejaRutina = getvect(0x1C);
setvect(0x1C, imprimirCaracter);
asm sti
// Bucle de espera
while (salir != 1);
// Desinstalamos nuestra ISR
}
}
asm cli
setvect(0x1C, viejaRutina);
asm sti
Descargar