Facebook Twitter Google +1     Admin





Who the Hell...?!

motagirl2, la culpable de todo esto

¿De qué va esto?

Temas



¿Más cosas interesantes?

Elementos compartidos de motagirl2


Google



Quiero 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 Anobii
En DeviantArt
En Facebook
En Flickr
En Instagram
En LastFM
En Lomography
En Tumblr
En Twitter
En YouTube


Acceso a la tabla de vectores de interrupción

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;
codigo = inport(0x60);

/*Blablablabla hacer cosas blablabla*/
outport (0x20, 0x20);

}

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
Encuesta: ¿Cómo  las pones tú? xD

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;
*(tvi+9*4)=FP_OFF(rutina_teclado);
*(tvi+9*4+2)=FP_SEG(rutina_teclado);
asm sti;  

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 ^^

sesion6 de perifericos

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

Perpetrado por MotaGirl
11/03/2009 20:55 # id #. Tech/Geek/Craft

Comentarios » Ir a formulario

motagirl

gravatar.comPerpetrado por krone

Yo también pongo las llaves igual ^_^

Los que lo ponen al revés son unos raros :P



¿Cuándo? 11/03/2009 22:36.


gravatar.comPerpetrado por motagirl2

bieeen!!
Hacemos un grupo de facebook? XD



¿Cuándo? 11/03/2009 22:39.


gravatar.comPerpetrado por Scipion

muy bien mota, las llaves las pones así pq las llaves se ponen así.
krone, siempre hay un raro/siervo de satan/amigo de microsoft que las pone mal pero que le vamos a hacer, el mundo es injusto.
P.D.: hagamos un grupo en facebook de llaves bien puestas y otro de fans de los lenguajes que llevan llaves (no me mola nada el if_then_fi etc.) XD



¿Cuándo? 12/03/2009 00:42.


gravatar.comPerpetrado por haruma

Sobre las llaves. Tú las pones al estilo de las "Java Code Conventions". Lo común en C es poner la llave de abrir en una nueva línea.

De todas formas esto es tema para un debate largo e irresoluble, del estilo de cómo hacer un bucle infinito. Todavía recuerdo un libro que decía que el método estándar para hacer un bucle infinito en C era for(;;), aunque "había una fiel minoría de programadores" que usaban while(1) (soy de esa minoría).

Contra-encuesta: ¿cómo hacéis un bucle infinito?



¿Cuándo? 12/03/2009 13:10.


gravatar.comPerpetrado por motagirl2

Yo también soy del while(1). De hecho lo del for(;;) ni se me había ocurrido xD



¿Cuándo? 12/03/2009 16:29.


gravatar.comPerpetrado por Chuky

Mhuhahaha yo también uso las llaves asi, para abrir y cerrar puertas O.o

Respecto a lo del bucle infinito while(true) xDD



¿Cuándo? 14/03/2009 09:51.


gravatar.comPerpetrado por mgisbert

Ey, me parece que la forma elegante de poner las llaves es como las pone motagirl... pero a lo que iba... jeje, con respecto a la fe de erratas del artículo sobre Modificación de los patrones de bits de los caracteres, lo tengo en 80x25 y lo pongo en pantalla completa pero sigue sin pirular en cmd... ¿alguien sabe algo más?...
Esque el dosbox y yo no nos llevamos muy bien...

See u



¿Cuándo? 30/04/2009 12:04.


gravatar.comPerpetrado por motagirl2

mmmm ni idea, pero a mí el profesor me recomendó hacerlo en dosbox porque es una emulación completa de Dos, no como cmd,... en el que puede no funcionar algo.



¿Cuándo? 30/04/2009 12:08.


gravatar.comPerpetrado por mgisbert

Ey, ya me he hecho amigo del DosBox, jeje, pero sigue sin pirulaaar!! jejeje, el rollo es asín, no?:

int main(){
char *q;
struct REGPACK rp;
rp.r_ax=0x1130;
rp.r_bx=0x0600;
intr(0x10,&rp);

q=(char *)MK_FP(rp.r_es,rp.r_bp);

*(q+65*16)=255;

asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push es;
asm push bp;
asm mov ax, 1110h;
asm mov bx, 1000h;
asm mov cx, 0100h;
asm mov dx, 0;
asm les bp, q;
asm int 10h;
asm pop bp;
asm pop es;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}



¿Cuándo? 13/05/2009 11:46.


gravatar.comPerpetrado por Carlos

Muy buenos tus post sobre perifericos.

Con tu explicación creo que me has ahorrado 5 horas, por lo que...te debo 5 horas ;)



¿Cuándo? 15/05/2009 04:19.


gravatar.comPerpetrado por miguel

Creo que mi fallo está en el bucle que hago para que no salga el programa... ¿dónde hay que poner ese bulce exactamente? Yo lo ponía después de asm int 10h; que es cuando se supone que la interrupción se ejecuta, no? y antes de todo lo demás que hace que vuelva estar todo como antes, no? Tb lo he probado poner al final pero nada... ¿Alguien sabe algo?

Gracias!!



¿Cuándo? 17/05/2009 18:52.


gravatar.comPerpetrado por motagirl2

Disculpa la tardanza, es que justo me he puesto a mirarlo y me han enviado la orla y me he emocionado xD

Bueno, yo tengo el bucle justo despues del

asm cli;
*(tvi+9*4)=FP_OFF(rutina_teclado);
*(tvi+9*4+2)=FP_SEG(rutina_teclado);
asm sti;

o sea, antes de volver a restaurarlo todo. Quizá falles en otra cosa :/



¿Cuándo? 17/05/2009 19:15.


gravatar.comPerpetrado por miguel

Pero eso que me dices es de la sesión 6, no?, en realidad yo estaba hablando de la segunda parte de la 4, jeje, lo de ponerle una rayita a la A. Sé que este artículo es de acceso a la TVI pero como salió el tema de lo anterior... pues pregunté.

Ah! y no te tienes que disculpar, jejeje, que encima de todo lo que haces... yo intentaré colgar tb todo lo que tenga... cuando lo tenga... jeje

See u



¿Cuándo? 18/05/2009 10:39.


gravatar.comPerpetrado por motagirl2

Uhm...en la 4 no hace falta bucle, al ejecutar ya se cambian los patrones y durará hasta que hagas un CLS.

Sobre la practica 4 escribí también un par de posts: http://motagirl.blogia.com/2009/022701-acceso-a-rom-para-obtener-los-patrones-de-bits-de-los-caracteres.php y http://motagirl.blogia.com/2009/030402-modificacion-de-los-patrones-de-bits-de-los-caracteres.php

(Ya me avisas cuando cuelgues lo tuyo jaja)



¿Cuándo? 18/05/2009 12:20.


gravatar.comPerpetrado por miguel

Vale, voy pillando... jeje, le mandé una tutoría al profesor y me ha dicho lo mismo, entonces creo que lo que hacía mal es que declaraba un puntero que apuntaba a la memoria de vídeo e intentaba modificarla desde ahí, en lugar de copiarla. Pero lo he modificado y ahora me saca basura por pantalla... sería tal que así, no?:

[por cierto, ya había visto los otros dos posts tuyos... :P]


char *p,*q,c;
struct REGPACK rp;
rp.r_ax=0x1130;
rp.r_bx=0x0600;
intr(0x10,&rp);

q=(char *)MK_FP(rp.r_es,rp.r_bp);
p=malloc(sizeof(char)*4096);
*p=*q;
*(p+65*16)=255;



¿Cuándo? 18/05/2009 18:07.


gravatar.comPerpetrado por miguel

Por fiiiiin!!! he visto la luz!! jejeje, bueno más bien me la ha mostrado el profesor por email diciéndome que soy un melón por lo de *p=*q, eso sólo copiaría el primer byte, hay que poner for(j=0;j



¿Cuándo? 19/05/2009 12:20.


gravatar.comPerpetrado por miguel

Ey, no sé por qué no se ha copiado mi mensaje entero, el bucle es for(j=0;j



¿Cuándo? 19/05/2009 12:23.


gravatar.comPerpetrado por miguel

Jope! altra volta!! jeje, bueno que hay que hacer un blucle recorriendo los 4k de la tabla y asignando los contenidos de los punteros uno a uno, y que a ver si salen las prácticas gordas que serán las más importantes de cara al examen y, por cierto, a alguien le va bien la 5? comentad en el foro: http://penyainformatica.mforos.com/821675-perifericos/

Salut!



¿Cuándo? 19/05/2009 12:25.


gravatar.comPerpetrado por Orlando

Disculpen por la pregunta pero, como que daria una funcion hecha en C. Para que al ejecutar el programa se abra en pantalla completa

utilizando windows xp y copilandolo en Turbo C



¿Cuándo? 06/08/2009 22:35.


gravatar.comPerpetrado por GatoVolador

Debo agradecerte y te agradezco tu iluminación en la oscura ciencia de los Periféricos :P



¿Cuándo? 16/03/2010 17:11.


gravatar.comPerpetrado por motagirl2

Jaja gracias :)



¿Cuándo? 16/03/2010 17:18.


Añadir un comentario



No será mostrado.





Artículos anteriores

Blog creado con Blogia. Esta web utiliza cookies para adaptarse a tus preferencias y analítica web.
Blogia apoya a la Fundación Josep Carreras.

Contrato Coloriuris