Black Hole organizacion
CostaRica  
  Bienvenida
  Hackers
  Foro ingresa
  Noticias
  Contacto
  Imagenes
  Programas
  Visitantes
  Chat
  Libros
  => hacker
  => Virus
  => Cracker
  => Lecciones hackin
  => Programacion
  => Diseños web
  => Guia de hackin
  => Privasidad
  => Guia → 1
  => Guia → 2
  => Guia → 3
  => Guia → 4
  => Guia → 5
  => Guia → 6
  => Guia → 7
  => Guia → 8
  => Guia → 9
  => Guia → 10
  => Guia → 11
  => Como intrudusirse aun sistema
  => shellcodes_linux-1
  => shellcodes_linux -2
  => UN-scodes.
  => Guia version Deluxe
  => Ser Hacker dentro de Términos Legales
  => Como hackear una paginaweb
  => Comoprogramar un Virus
  => Como Crear un Virus
  => Cuantos tipos de Virus existen
  => Programaciones de un virus
  => Estructura de computadores
  => Fundamentos de SSOO
  => Sistemas de numeración
  => Ensamblador I: Conceptos básicos
  => Ensamblador II
  => Utilidades para la programación
  => Infección bajo Windows
  => Infección bajo Linux
  => Técnicas avanzadas
  => Apéndices
  => CONOCIENDO LA MAQUINA
  => DIRECCIONAMIENTO DE MEMORIA EN EL 8086
  => CHIPS DE APOYO (Ampliación de la lección 1)
  => LA PILA DEL 8086
  => CODIFICACIÓN DE LAS INSTRUCCIONES EN EL 8086
  => Manual HTML
  => Ataques basados en Desbordamiento de Buffer (Buffer Overflow)
  => Privasidad
  => Escaneo
  => anti Escaneo y Escaneo
  => Malianom
  Triang
  Tersirve esta paguina?
  -
  juegos
  Vagos
  mapa
  Mapa del sitio
  546
LA PILA DEL 8086

Atras


Hola a todos. En esta lección vamos a tratar aspectos muy interesantes de la programación del PC, interrupciones, puertos, etc. Espero que tengáis claro lo del error que os comentaba en la lección 1, acerca de los buses. Si no es as¡, a qué esperáis para preguntar...

Bueno, seguimos con lo nuevo:  

ENTRADA/SALIDA (COMUNICACIÓN CON EL HARDWARE I)

La comunicación entre un programa y el hardware, es decir los chips de apoyo y las tarjetas de ampliación, se efectúa mediante los llamados Ports (puertos, en castellano). Estos puertos son zonas de memoria de 1 o 2 bytes de tamaño, en las cuales se depositan los datos que van a ser utilizados por los chips o tarjetas, y también se depositan los datos que devuelven estos chips o tarjetas al procesador. En el PC, existe una zona de memoria de 64 Ks, ajena a la memoria principal, dedicada a los puertos. Es decir, estos 64 Ks de memoria no tienen nada que ver con la memoria disponible para los programas. Para realizar los movimientos de datos entre puertos y procesador existen instrucciones especiales: IN y OUT. Tanto IN como OUT tienen dos formas de uso, las cuales utilizan el registro AL o AX para almacenar los datos a leer o escribir. La forma difiere en función de que se quiera acceder a un puerto menor de 256 o mayor.

Más todo directo o estético: corresponde cuando se quiere acceder a un puerto menor de 256.

IN AL,10H-------------> lee un byte del puerto 10h

IN AX,10H-------------> lee una palabra del puerto 10h

OUT 0FFH,AL--------- > escribe el valor de AL en el puerto 0FFH

 

Método indirecto o dinámico: corresponde al caso de querer acceder a un puerto mayor de 256, para lo cual se utiliza el registro DX indicando el número de puerto.

IN AL,DX--------------> lee un byte del puerto indicado por DX. (Antes hemos tenido que introducir en DX la dirección del puerto).

OUT DX,AX-----------> escribe la palabra contenida en AX en el puerto DX.

Algunos ejemplos de puerto son:

60H ------------------> acepta entradas de teclado.

61h-------------------> controla el altavoz.

3F0HA3F7H----------> Opera sobre la controladora de discos.

En el PC cualquier subsistema, exceptuando la memoria, está controlado por el procesador a través de los puertos.

INTERRUPCIONES (COMUNICACIÓN CON EL HARDWARE II)

Las interrupciones constituyen la forma en que la circuitería externa informa al microprocesador de que algo ha sucedido (como que se ha pulsado una tecla, por ejemplo) y solicita que se emprenda alguna acción. Pero no acaba ah¡ su utilidad, ya que las interrupciones además son el medio principal de comunicación entre las funciones de la BIOS y el DOS. En este segundo caso, son mal llamadas interrupciones. Más bien habría que decir funciones, ya que nos sirven para hacer una llamada a una función BIOS o DOS, como por ejemplo la acción de cambiar de modo de video, para la cual se utiliza la interrupción 10h (Driver o controlador de v¡deo), con el número adecuado de función. Más adelante veremos como llamar a una función.

Al primer tipo de interrupciones se les denomina interrupciones de hardware, y son las interrupciones reales. Esto es, que estando un programa en ejecución, se interrumpe éste para ejecutar un trozo de código necesario para atender a la petición de un dispositivo, como puede ser el teclado. Acto seguido, se reanuda la ejecución del programa en cuestión. Son las interrupciones que vimos en la lección 3, al hablar del PIC.

Al segundo tipo de interrupciones se les denomina interrupciones de software, y son las 'ficticias', ya que no hay ningún dispositivo pidiendo atención del procesador, sino que es el programa del usuario el que ejecuta una función BIOS o DOS, mediante una interrupción. En este caso, no se interrumpe el programa de forma súbita, sino que es dicho programa el que lanza una interrupción, la cual tiene su rutina de atención a la interrupción (como vimos en la lección 3) 'conectada' a un grupo de funciones o rutinas.

Veamos las interrupciones con más detalle:

La tabla de vectores:

Toda interrupción aceptada conduce a la ejecución de un subprograma específico, como hemos visto. Pero como sabe el procesador donde empieza este subprograma, una vez que atiende a la interrupción... La respuesta nos la da la tabla de vectores.

Esta tabla de vectores contiene las direcciones de comienzo o punteros al subprograma de atención a la interrupción. La tabla está compuesta de 256 entradas. Es decir, son posibles 256 interrupciones diferentes en el PC. 

Cada una de estas entradas, contiene la dirección de inicio del código de atención a una interrupción, en la siguiente forma: 2 primeros bytes (una palabra) que contienen la dirección base del segmento, y los 2 últimos bytes que contienen el desplazamiento. En total 4 bytes para indicar el comienzo de una interrupción, en la forma segmento: desplazamiento.

Ya vimos en la segunda lección como transformar una dirección segmentada (segmento: desplazamiento) en una dirección física o real.

Durante la aceptación de una interrupción, el 8086 carga la dirección base del segmento en el registro CS y el desplazamiento en el contador de programa IP. De esta forma, la siguiente instrucción a ejecutar, que viene dada por los registros CS:IP, ser la primera del subprograma de atención a la interrupción.

Pines (líneas de bus) para demandar interrupción desde el exterior

Existen 3 líneas externas jerarquizadas que son, por orden de prioridades decrecientes: RESET, NMI e INTR. Sólo INTR es enmascarable (cuando un pin de demanda de interrupción está enmascarado e inhabilitado la activación del pin, no produce ninguna interrupción). Es decir, que si se activan los pines RESET o NMI, siempre van a conducir a la ejecución de una interrupción. Pero si se activa el pin INTR, tenemos dos opciones (dependiendo de si está  enmascarado o no), que son hacer caso omiso de la petición de interrupción, o atender dicha interrupción, respectivamente.

Pin INTR:

Una petición de interrupción sobre este pin es enmascarable mediante el bit IF (bandera de interrupción) del registro FLAGS o registro de estado. Este bit IF, es la máscara de INTR. Para saber si está enmascarada o no la línea INTR, se mira este flag. El cual puede tener (obviamente) dos valores: 0 y 1. Enmascarado es 0.

Para manipular este bit, disponemos de dos instrucciones en ensamblador:

CLI (Clear IF, o borrar flag IF) que lo pone con valor 0.

STI (Set IF, o activar flag IF) que lo pone con valor 1.

La petición de interrupción se realiza activando el pin INTR con nivel alto (1) y debe mantenerse as¡ hasta que por el pin INTA (pin asociado al pin INTR. Es activo a nivel bajo (0), indicando que se ha aceptado la interrupción solicitada por medio del pin INTR) el 8086 indique que ha sido aceptada.

Entonces... Contamos con el pin INTR para pedir al procesador atención a una interrupción, y con el pin asociado INTA que estará con valor (0) cuando la interrupción haya sido aceptada.

INTR----> Interrupt Request (petición de interrupción).

INTA----> Interrupt Accepted (interrupción aceptada).

Veamos cómo actúa la CPU desde que se activa el pin INTR hasta que se retorna del subprograma de atención a la interrupción:

Debido a que la interrupción interrumpir  al programa en ejecución en cualquiera de sus instrucciones, es necesario resguardar el contenido del registro de estado (FLAGS), para que al volver de la interrupción, tengan las banderas el mismo valor. Y sobre todo, hay que guardar la dirección de la siguiente instrucción a ejecutar en el programa actual.

Pero dónde se guardan todos estos datos... En una zona de memoria denominada PILA, la pila del procesador. (Explicación en el último apartado de esta lección).

Al acto de introducir un dato en la pila se le denomina apilar, y a sacarlo de la misma se le denomina desapilar.

Pues bien, el procesador hará lo siguiente:

Apila el contenido del registro de estado (flags)  

Apila la dirección de retorno (contenido de los registros CS e IP).

Inhibe las interrupciones (IF=0 y TF=0, m s adelante se comenta la utilidad del flag TF o TRACE)

Esto se hace para que no se produzca otra interrupción durante la secuencia de aceptación de la interrupción. Esto es muy importante. Activa el pin INTA (lo pone a nivel bajo). El dispositivo que ha solicitado la interrupción, al notar el cambio en el pin INTA, queda enterado de la aceptación de la interrupción. Lee el número del vector de interrupción del bus de datos. Previamente, el dispositivo lo ha depositado en respuesta a la activación del pin INTA. Obtiene la dirección del subprograma de atención a la interrupción. Dicha dirección se encuentra (como hemos visto antes) almacenada en la tabla de vectores.

El 8086 ejecuta la subrutina que finaliza con la instrucción IRET, o Retorno de Interrupción, cuya ejecución restituye en CS e IP la dirección de retorno salvada en la pila, y en el registro de estado el valor de los flags. Al restaurar los flags, se anula la inhibición anterior de IF y TF, con lo cual, otra vez se aceptan interrupciones. Pudiendo as¡ tener interrupciones en cascada. Repasar el ejemplo de la pulsación de tecla de la lección 3, a ver si ahora se ve con más claridad.

Pin NMI:

Este pin está reservado a acontecimientos graves, como puede ser un corte de corriente, un error de memoria, del bus, etc. La activación de NMI no conlleva ninguna lectura en el bus de datos del vector de interrupción, sino que la CPU directamente busca el vector de interrupción número 2.

Pin RESET:

Inicializa el sistema. En la petición de RESET no se almacena nada en la pila ni se accede a la tabla de vectores para conseguir la dirección de comienzo. Al activar el pin RESET, el registro de estado queda borrado (0).

CS = 0FFFFh.

IP = 00000h.

De esta manera, la siguiente instrucción a ejecutar por el procesador es la contenida a partir de FFFF:0, código de reinicialización y carga del sistema operativo. Son los últimos bytes de la ROM.

El resto de registro de segmentos quedan con valor 0.

            DS = 0000

            ES = 0000

            SS = 0000

Interrupciones internas o desvíos.

El microprocesador 8086 tiene 2 interrupciones internas: División imposible' y 'funcionamiento paso a paso (TRACE)'.

División imposible:

Se produce cuando se divide por 0, o cuando el cociente resultante de la división no cabe en el registro preparado para contenerlo. En ambos casos, se ejecuta la interrupción 0.

Funcionamiento paso a paso:

Si el programador coloca a (1) el bit TF (TRACE) del registro de estado, al final de cada instrucción, la CPU bifurcar a la posición de memoria indicada por el vector de interrupción n£mero 1. Esto es lo que utilizan los debuggers o depuradores de c¢digo para hacer un seguimiento del programa, instrucción por instrucción.

Más adelante, cuando hablemos acerca de la programación de utilidades residentes, entraremos en la programación práctica de las interrupciones. Valga lo dicho hasta ahora como base teórica.

La pila del procesador: 

La pila es una característica interna del 8086. Es una estructura de datos situada en la RAM. Proporciona a los programas un lugar donde almacenar datos de forma segura, pudiendo compartirlos con otros procedimientos o programas de forma cómoda y práctica.

La función más importante de la pila es la de mantener las direcciones de retorno en las llamadas a procedimientos e interrupciones, as¡ como guardar los par metros pasados a estos procedimientos. La pila también se utiliza para almacenamiento temporal de datos dentro de un programa, y para muchas cosas más que se aprenden con la práctica.

La pila tiene su nombre por analogía con los montones de platos apilados (pilas de platos). Cuando un dato nuevo es introducido en la pila, se dice que es apilado (push) debido a que se sitúa por encima de los demás, es decir se sitúa en la CIMA de la pila.

Una pila opera en el orden último en entrar, primero en salir:

LIFO (LAST IN FIRST OUT) o lo que es lo mismo, el último en entrar es el primero en salir. Esto significa que cuando la pila se utiliza para seguir la pista de los retornos de las subrutinas, la primera llamada a subrutina que se hizo, es la última que se devuelve. De esta manera, la pila mantiene ordenado el funcionamiento del programa, las subrutinas y rutinas de tratamiento de interrupción, sin importar la complejidad de la operación. La pila crece en orden inverso. Es decir, a medida que se añaden nuevos datos, la cima de la pila se acerca más a posiciones más bajas de memoria.

Existen 3 registros destinados a gestionar la pila.

Registro de segmento de pila (SS): que indica la dirección base del segmento de pila

Puntero de pila (SP): que apunta a la cima de la pila.

Puntero base de pila (BP): que se usa para moverse a través de la pila sin cambiar la cima. Se suele utilizar para acceder a los distintos par metros al llamar a una función.

Los elementos que se almacenan en la pila son del tipo palabra (2 bytes). Esto quiere decir, entre otras cosas, que el puntero de pila (SP), as¡ como el puntero base de pila (BP), incrementan/decrementan en 2 su valor para apuntar a un nuevo elemento dentro de la pila, fruto de apilar o desapilar un elemento.

También conlleva el que si queremos almacenar un byte en la pila, primero lo debemos convertir en palabra (2 bytes), y luego almacenar esa palabra. Esto es muy sencillo, s¢lo hay que meter ese byte o registro de 8 bits en un registro de 16 bits y almacenar este registro.

Las instrucciones para manejar la pila son:

PUSH---------> Guarda un dato en la pila. Decrementando SP en 2 unidades, para que    apunte al nuevo elemento a introducir. Ejemplo: PUSH AX--> Apila el contenido de AX en la cima de la pila.

 

POP----------> Obtiene un dato de la pila. Incrementando SP en 2 unidades, para que apunte al nuevo elemento a introducir. Ejemplo: POP AX --> Desapila el    contenido de la cima de la pila en el registro AX. Es decir, AX contenía  el valor que había en la cima de la pila, y el puntero de pila se actualiza incrementándolo en 2.

 

PUSHF--------->Guarda el contenido del registro de estado (FLAGS) en la pila. Decrementando SP en 2 unidades, para que apunte al nuevo elemento a introducir. No es necesario indicar sobre qué actúa esta instrucción, lo lleva implícito en su nombre PUSHF (PUSH FLAGS).

 

POPF----------> Introduce en el registro FLAGS el contenido de la cima de la pila.    Incrementando SP en 2 unidades, para que apunte al nuevo elemento a introducir. Al igual que con la instrucción anterior, no es necesario indicar sobre qué actúa esta instrucción POPF (POP FLAGS).

Conviene recordar el hecho de que la pila crece en orden inverso al normal, es decir de direcciones de memoria altas a direcciones bajas. Por lo tanto es necesario tener en cuenta el uso que se va a hacer de la pila en el programa, debido a que si reservamos espacio en nuestro programa para una pila peque¤a, en caso de sobrepasarla haciendo muchos push seguidos, machacaría nuestro programa. Hay que tener en cuenta que no sólo es nuestro programa el que utiliza la pila mediante la instrucción PUSH y mediante llamadas a procedimientos, interrupciones, etc. Sino que mientras nuestro programa corre se están sucediendo numerosas interrupciones que conllevan muchos PUSH. Por ejemplo, 18'2 veces por segundo se produce la interrupción de reloj, con lo cual, todas estas veces se está apilando y posteriormente quitando información de la pila.

Por regla general, basta con tener una pila de unos 2 KS, es decir, espacio para almacenar 1024 elementos. Es muy difícil que se sobrepase este tamaño.

 

Bueno... Aquí¡ seguro que hay dudas.

Venga, decidme qué queréis que explique más detenidamente, que dentro de un par de lecciones empezamos a programar, y hay que tenerlo todo claro.

Un saludo.

AESOFT....
Black Hole  
   
Facebook botón-like  
 
 
Hoy hay 20 visitantes¡Aqui en esta página!
Este sitio web fue creado de forma gratuita con PaginaWebGratis.es. ¿Quieres también tu sitio web propio?
Registrarse gratis