Hola,
esto es algo que vengo buscando hace varios meses, y es algo muy importante de como trabaja la cpu y si tenes pensado hacer un sistema operativo, te recomiendo que lo leas. es todo un honor haber posteado esto en mi blog (y en CM) 
aclaro que lo que digo a continuacion nunca lo puse en practica al 100%, y que saco parte de la info de wikipedia y de http://www.acm.uiuc.edu/sigops/roll_your_own/i386/idt.html
hay una seccion de la memoria donde esta la informacion de las interrupciones, osea, es donde el cpu busca cuando alguien hace
int 30h
o cuando se ejecuta una interrupcion de cpu o de hardware
las interrupciones son funciones que se ejecutan cuando pasa algo, por ejemplo, cuando escribimos en el teclado, o cuando un programa intenta ejecutar una instruccion invalida, o error de violacion de memoria, o cosas por el estilo, pero tambien por ejemplo la BIOS carga funciones basicas, por ejemplo la int 21h, o como por ejemplo en UNIX donde las llamadas al sistema se hacen a travez de la int 80h, osea, en este caso es el programa el que llama a una interrupcion.
las primeras 32 interrupciones son reservadas para interrupciones del procesador. y hay un total de 256 interrupciones (desde la int 0 a la int 255)
lo que hace la cpu es, por ejemplo si hacemos int 30h, buscar la posicion de esa tabla destinada a la interrupcion 30h y obtener la direccion y hacer una llamada a esta direccion
modo real:
esta tabla esta dividida de a 32 bits (osea, 4 bytes) para cada interrupcion, osea, ocupa 256 * 4 bytes, osea, 1024bytes, osea, 1kb, esos 32 bytes se dividen en 2, 16 bits para el segmento y 16 bits para el offset (en la memoria en la posicion mas baja aparece el offset y en la mas alta el segmento). teniendo la direccion base de la tabla (base) para saber la posicion de la interrupcion X se hace
base + (X * 4)
y se obtiene la posicion donde esta el offset y el segmento de la interrupcion a ejecutar.
modo protegido:
esta dividida de a 64 bits (osea, 8 bytes) para cada interrupcion:
http://www.acm.uiuc.edu/sigops/roll_your_own/i386/gate.jpg
es un quilombo, nose si es que yo lo leo mal, si esta mal dibujado, o si los de intel son monos, pero esta todo mezclado
el dibujo ese se lee de derecha a izquierda y de abajo hacia arriba, los numeritos de arriba son los bits, empieza por el 0 a la derecha y el 31 a la izquierda, y a la derecha los numeros +0 y +4 corresponden a los bytes a partir de la base
y estas son las referencias:
* P - Present. Se coloca en 1 para interrupciones en funcionamiento
* DPL - tiene que ser 0 para exceciones e interrupciones de hardware, 3 para interrupciones de software llamadas desde la aplicacion
* Type - Trap Gate, Interrupt Gate, o Task Gate on the System Descriptor List
* DWord-Count - tiene que ser 0 para elementos en la IDT
* Offset in Target Segment - direccion de la interrupcion
* Target Segment Selector - segmento en el que correra la interrupcion (ver esto)
muy bien, si modificamos esta tabla de las direcciones de las interrupciones podemos hacer que cuando alguien hace int 46h se ejecute un codigo nuestro
cuando uno crea un S.O. no te vienen todas las interrupciones regaladas... jejejeje
bueno, falta el detalle final, donde esta esta esta famosa tabla? hay un registro del cpu donde esta la direccion inicial y el tamaño, pero este registro solo esta accesible a travez de las funciones sidt y lidt
se les pasa una direccion de la memoria donde van a leer (lidt) o escribir (sidt) la base y el tamaño, en el caso de trabajar en modo real, ocupa 32 bits, teniendo en los primeros 16 bits el tamaño, y en los segundos 16 bits (osea,la posicion mas alta) la base, que suele ser 0000h. y en el caso de modo protegido tenemos 16 bits para el tamaño y 32 para la base.
sidt escribe en la direccion de memoria el tamaño y la base, y lidt lee la posicion de memoria y lo guarda en el registro.
osea, uno podria crear otra tabla en otra posicion de meoria (osea, cargar las nuevas interrupciones en algun lugar de la memoria y colocar en, por ejemplo, 0100h una nueva tabla que apunta a las nuevas interrupciones, para eso tendriamos que hacer algo asi:
;16 bits...
_idtt dw 0
_idtb dw 0
;copiamos las nuevas interrupciones
;
;creamos la nueva tabla con las posiciones que apuntan a nuestras interrupciones
cli ;por las dudas...
mov _idtt,tamaniotabla
mov _idtb,basetabla
lidt _idtt ;como lidt va a leer 32 bits, "agarra" _idtt y _idtb
sli
;ya tenemos las nuevsa interrupciones
aunque creo que seria mejor atualizar la tabla actual
;16 bits...
_idtt dw 0
_idtb dw 0
cli ;por las dudas..
sidt _idtt
;vamos a cambiar la interrupcion 80h :P
mov bx, _idtb
mov [bx + 4 * 80h],nuevooffset
add bx,2
mov [bx + 4 * 80h],nuevosegmento
sli
;ya tenemos el nuevo procedimiento para cuando alguien haga int 0x80
perdonen pero mi asm es muuy malo xDD
bueno, espero que se haya entendido y que sea de utilidad
LINKS:
http://www.acm.uiuc.edu/sigops/roll_your_own/i386/idt.html
http://www.acm.uiuc.edu/sigops/roll_your_own/i386/idt.html#ProcExcept
salu2!


0 comentarios:
Publicar un comentario en la entrada