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






I am nerdier than 93% of all people. Are you nerdier? Click here to find out!


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

Desterrado de la mente perversa de MotaGirl.
11/03/2009 20:55 # id #. Tema: Frikadas.

Comentarios » Ir a formulario

gravatar.comDesterrado por la mente de: krone

Yo también pongo las llaves igual ^_^

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



Desterrado en: 11/03/2009 22:36.


gravatar.comDesterrado por la mente de: motagirl2

bieeen!!
Hacemos un grupo de facebook? XD



Desterrado en: 11/03/2009 22:39.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 12/03/2009 00:42.


gravatar.comDesterrado por la mente de: 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?



Desterrado en: 12/03/2009 13:10.


gravatar.comDesterrado por la mente de: motagirl2

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



Desterrado en: 12/03/2009 16:29.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 14/03/2009 09:51.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 30/04/2009 12:04.


gravatar.comDesterrado por la mente de: 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.



Desterrado en: 30/04/2009 12:08.


gravatar.comDesterrado por la mente de: 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;
}



Desterrado en: 13/05/2009 11:46.


gravatar.comDesterrado por la mente de: 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 ;)



Desterrado en: 15/05/2009 04:19.


gravatar.comDesterrado por la mente de: 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!!



Desterrado en: 17/05/2009 18:52.


gravatar.comDesterrado por la mente de: 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 :/



Desterrado en: 17/05/2009 19:15.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 18/05/2009 10:39.


gravatar.comDesterrado por la mente de: 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)



Desterrado en: 18/05/2009 12:20.


gravatar.comDesterrado por la mente de: 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;



Desterrado en: 18/05/2009 18:07.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 19/05/2009 12:20.


gravatar.comDesterrado por la mente de: miguel

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



Desterrado en: 19/05/2009 12:23.


gravatar.comDesterrado por la mente de: 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!



Desterrado en: 19/05/2009 12:25.


gravatar.comDesterrado por la mente de: 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



Desterrado en: 06/08/2009 22:35.


Añadir un comentario

*

*
No será mostrado.


*

* Datos requeridos.

Artículos anteriores

Free counter and web stats