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