|
|
Who the Hell...?!motagirl2, la culpable de todo esto¿De qué va esto?Temas
¿Más cosas interesantes?Elementos compartidos de motagirl2Quiero estar al dia!- Subscribirme usando mi agregador de noticias ^^- No, gracias, prefiero recibir un mail cuando haya nuevos artículos ;) ¿Dónde está mota?En Anime-Planet En Anobii En Bloglines En Blogspot En DailyMotion En DeviantArt En DinoParc En El Bruto En Facebook En Flickr En Fotolog En GoEar En Hammerfest En Jisko En LastFM En MySpace En Naturalquimia En Orkut En Technorati En Tuenti En Twitter En Wordpress En YouTube Reglas y consejos para apostar a las tragaperras en tu web de casinos de internet
|
Otro bonito capítulo sobre mis prácticas de periféricos, de esos que nadie comenta pero luego cuando nos cruzamos por el campus me rascais la cabeza y me dais las gracias :P Esta no pensaba hacerla todavía, pero por lo visto esta mañana a las 7.00 mis vecinos han considerado divertido poner música a todo volumen (nunca antes odié a Bach) y pasear con tacones (o equivalente). Así que como no podía dormir, y no tenía nada mejor que hacer (en realidad sí, pero no importa), le he dedicado un rato a esta práctica que es muy sencilla. La tabla de vectores de interrupción es un cacho de memoria (concretamente, desde el 0000:0000) en el que se almacenan las direcciones de las funciones o rutinas que atenderán a cada interrupción. Es decir, que cuando se produce una interrupción, se transfiere el control del sistema a la rutina situada en la dirección indicada en la posición de memoria especificada en la posición correspondiente de este vector. Hay 256 interrupciones (la lista está aquí).Cada una, usa 4bytes de este vector: 2bytes para el offset y otros 2bytes para el segmento en que se encuentra la función (no, no me he equivocado: guarda primero el offset y después el segmento). Por tanto, en total la tabla ocupa 1KB. Además, cada interrupción está en la posición indicada por su número: La dirección de la interrupción 0 se encuentra en los 4 primeros bytes, la de la interrupción 1 en los 4 siguientes, etc. En definitiva: el offset de la dirección de la interrupción i se encuentra en el byte tvi+4*i y su segmento en el tvi+4*i+2 (suponiendo tvi el inicio de la tabla de vectores de interrupción, o sea, 0000:0000) Supongamos que no nos gusta la rutina normal de teclado, y queremos una propia que por ejemplo, en vez de escribir el carácter por pantalla, imprima el valor del código de teclado (es decir, el código de la tecla pulsada, que no depende del carácter sino de la posición de la tecla y de si se pulsa o se suelta. Por ejemplo, el ESC genera el scancode 1, el 1 genera el código 2, el 2 el 3, etc etc. La tabla completa está aquí -la Tabla90-). Podría ser algo tal que así: void interrupt rutina_teclado(){ char codigo; } Inciso: Sí, pongo las llaves así, mucha gente lo ve raro pero ... a mi me parece más amigable que ambas en nueva línea. :P La palabra interrupt le indica al compilador que lo que está haciendo no es una función normal, sino una interrupción. O sea, que le está pidiendo al compilador que genere código para salvar y restaurar el estado de la CPU cada vez que se ejecute ese código (esa es la gracia de las interrupciones) Con inport(0x60) lo que hace es leer el scancode de la tecla pulsada/soltada, y el outport(0x20, 0x20) simplemente es el EOI (End Of Interruption), que hace que se salga correctamente de una interrupción. ¡Debemos usarlo siempre para terminar una interrupción! Bueno, obviamente, esto así solito, en el limbo de los códigos, no tiene mucho sentido, así que tendríamos que modificar la TVI para que cada vez que pulsemos una tecla, vaya a nuestra maravillosa rutina en vez de a la normalita. Como ya sabemos, la interrupción de teclado es la 9, así que lo que nos interesa está en esa posición (O sea, necesitamos un punterete hacia MK_FP (0 , 9*4)). Lo primero, antes de romper nada, es guardarnos la dirección de la rutina original. (Aunque si se rompe algo, que no panda el cúnico: basta con cerrar y abrir nuestro maravilloso emulador de DOS). Para ello, guardamos en un par de variables el offset y el segmento, que como dije antes, están respectivamente en los dos primeros y dos siguientes bytes de 0 , 9*4. Lo siguiente es modificar la posición de la tabla que nos interesa y decirle que ahora tiene que apuntar a nuestra rutina. El identificador de una función es en realidad un puntero a la misma, así que se convierte en algo tan simple como lo que sigue: asm cli; Es importante desactivar la llegada de interrupciones antes de cambiar nada. ¿Os imaginais la super catástrofe que sería que se produjera una interrupción de teclado después de haber cambiado el offset pero antes de haber modificado el segmento? ¡Eso sí que sería una fieshta! Podemos hacerlo con instrucciones en ensamblador: asm cli (desactivarlas) y asm sti (activarlas), una vez que se han modificado. Cuenta la leyenda que también se puede usar disable() y enable(), que están incluidas en dos.h . . . pero yo no las he usado así que no prometo nada. Y una vez cambiado esto... ya podríamos casi decir que está todo hecho. Eso sí: En el tremendamente abierto "hacer cosas" de la rutina es bastante interesante configurar un caracter "de escape", para que cuando se detecte una determinada tecla pulsada, se salga de la interrupción restaurando la rutina original (y así además te ahorras tener que cerrar el DOS para poder usar el teclado normalmente xD). Pero eso lo haceis vosotros: no os lo voy a dar todo mascadito :P Fail típico 1: poner un while(salir==false) dentro de la rutina. Esto es absurdo, porque la rutina se invocará SIEMPRE que pulse o suelte una tecla, así que el bucle no me hace falta. Fail típico 2: llamar explícitamente a la función. ¡No hace falta! Vendrá ella solita cada vez que pulses una tecla. Ale, espero que os haya servido de algo, y si no es así... al menos a mi me ha servido para "afianzar conocimientos". Acepto comentarios, mails y tabletas de chocolate :P Os dejo con la típica captura de rigor: En ella pulso las teclas M O T A en ese orden. Si pinchais en la imagen y la veis en flickr, le he puesto notitas explicativas ^^ Por cierto, fe de erratas del artículo sobre Modificación de los patrones de bits de los caracteres: Comprobé una vez más el ejecutable sobre cmd, y resulta que no funcionaba por la simple razón de que no lo tenía configurado en el modo 80x25 y en pantalla completa. En cuanto lo cambié, comenzó a tirar. Cosas que pasan XD |