Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo Funcionamiento del 8086/8088 En este capítulo se ofrece una pequeña descripción del funcionamiento de un 8086/8088. En concreto, se explica cómo está organizada la memoria, como se ejecuta un programa y cómo se manejan las interrupciones. Modos de direccionamiento En el 8086/8088, los parámetros (operadores) de una instrucción pueden ser de tres tipos: 1. registros internos de la CPU, 2. valores inmediatos, 3. direcciones de memoria, de las que hay cinco tipos diferentes de representación. En total son siete las clases de parámetros que se pueden utilizar y conjuntamente forman los llamados siete modos de direccionamiento. MODO Registro Valor Variable Indirecto mediante registro Relativo a base Directo indexado Indexado a base OPERADOR Registro Valor inmediato Offset inmediato [BX] [BP] [DI] [SI] [BX] + desp [BP] + desp [DI] + desp [SI] + desp [BX] + [SI] + desp [BX] + [DI] + desp [BP] + [SI] + desp [BP] + [DI] + desp REGISTRO BASE --DS DS SS DS DS DS SS DS DS DS DS SS SS EJEMPLO MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV AX, BX AX, 2604 AX, [1432] DX,DS:[BX] DX,SS:[BP] DX,DS:[DI] DX,DS:[SI] CX,DS:[BX+40000] CX,SS:[BP+40000] CX,DS:[DI+40000] CX,DS:[SI+40000] AX,DS:[BX][SI]+300 AX,DS:[BX][DI]+300 AX,SS:[BP][SI]+300 AX,SS:[BP][DI]+300 Figura.1. Modos de direccionamiento existentes en el 8086/8088. En la figura 1, se puede observar un esquema de todos los modos de direccionamiento, que se detallan a continuación: 1. Registros internos: el origen y destino de la operación son los registros internos de la CPU. 2. Valores inmediatos: en este modo, el origen de los datos (y sólo el origen) es un valor numérico. 1 Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo 3. Valores de memoria. Hay cinco modos de acceso a memoria: 3.1 Modo directo: Se indica la dirección de memoria a la que se quiere acceder. 3.2 Modo indirecto mediante registro: Es similar al modo anterior sólo que el valor del desplazamiento del operando no se indica directamente sino que se encuentra en un registro de la CPU. 3.3 Modo relativo a base: Es unir los dos modos anteriores. Consiste en indicar la posición del operando utilizando como desplazamiento el valor de un registro sumado con una cantidad constante. 3.4 Modo directo indexado: Idéntico al anterior pero usando como registro de desplazamiento el registro SI o el DI. 3.5 Modo indexado a base: Este es el modo más complejo, y se podría decir que es el resultado de unir los cuatro anteriores. En este modo, el desplazamiento del operando se compone a partir de un registro que hace de base, un registro índice y un valor inmediato que se les suma. La pila (stack) La pila es una característica interna del 8086/8088. Proporciona a los programas un lugar donde almacenar y seguir la pista del trabajo que se está llevando a cabo. La función más importante de la pila es la de mantener el registro de los lugares donde se llamó a una subrutina y de los parámetros que se le pasaron. La pila también puede utilizarse para el almacenamiento temporal de datos de trabajo, aunque esto es menos fundamental y no tan común. La pila obtiene su nombre por analogía con los montones de platos apilados (pilas de platos). Cuando un dato nuevo es introducido (push) en la cima de la pila, éste será el primer en ser extraído (pop). Por eso se dice que la pila siempre opera en el orden “último en entrar, primero en salir” (LIFO, Last In First Out). 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 vuelve. De esta manera, la pila mantiene ordenado el funcionamiento del programa, las subrutinas y las rutinas de tratamiento de interrupción, sin importar lo complejo de la operación. La pila se utiliza desde la parte de abajo (dirección más alta) a la parte de arriba (dirección más baja), de forma que cuando un dato es introducido (push) a la cima de la pila, se almacena en la posición de memoria justo por debajo de la cima actual. Así, la pila crece hacia abajo de forma que, a medida que se añaden datos, la posición de la cima se mueve más y más hacia direcciones más bajas, decrementando cada vez el valor de SP. 2 Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo 1008 1006 1004 1002 1000 5E00 4D00 3C00 Å Final pila Å Cima pila (SP = 1004) a) Pila antes de un PUSH 1008 1006 1004 1002 1000 5E00 4D00 3C00 2B00 Å Final pila Å Antigua cima Å Cima pila (SP = 1002) b) Pila después de un PUSH 5E00 4D00 3C00 1008 1006 1004 1002 1000 Å Final pila Å Cima pila (SP = 1004) c) Pila después de un POP Figura 2. Ejemplos del funcionamiento de una pila. Cualquier parte de un programa puede crear un nuevo espacio de pila en el momento que desee. Por lo general, cuando un programa está funcionando se crea para él una sola pila y se utiliza durante todo el funcionamiento. No hay una forma sencilla de estimar el tamaño de la pila que un programa pueda necesitar, y el diseño del 8086/8088 no proporciona ninguna manera automática de detectar cuándo el espacio de pila está agotado o casi agotado. Esto puede llevar a que los programadores estén indecisos acerca del espacio que deben reservar para la pila. Una estimación conservadora del espacio que hay que reservar da alrededor de 2 KB (2048 bytes), que es la cantidad que asignan por defecto la mayoría de los compiladores de lenguajes de alto nivel. Las interrupciones Las interrupciones1 son mecanismos utilizados en los ordenadores por medio de los cuales es posible interrumpir la ejecución de un programa para atender la llegada de un acontecimiento externo. Así, pues, son señales que se le envían a la CPU para que suspenda la ejecución de la instrucción en curso y atienda una petición determinada. Hay cuatro tipo de interrupciones: • Interrupciones hardware: Son las generadas por la circutería del ordenador en respuesta a algún evento como pulsar una tecla del teclado. Este tipo de interrupciones la maneja el controlador de interrupciones, que establece la prioridad antes de enviar la señal a la CPU. • Interrupciones internas: Son las generadas por la propia CPU cuando se produce una situación anormal, como por ejemplo, una división por cero. • Interrupciones software: Son las generadas por el propio programa para invocar a ciertas rutinas almacenadas en memoria (ROM o RAM). Es posible cambiar estas rutinas. Las interrupciones se aprovechan también en la actualidad como funciones software: no son activadas por dispositivos externos al procesador, sino que lo son por los propios programas. Las interrupciones software pueden ser activadas internamente por la propia CPU cuando se producen situaciones especiales, como, por ejemplo, cuando se intenta 1 Para más información ver [ENI01], [PA01], [PCI00] y [TE01] 3 Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo hacer una división siendo el divisor igual a cero. Esto ahorra el tiempo que, en otro caso, deberían dedicar los programas a la comprobación previa de los divisores. • Interrupciones no enmascarables: Se usan para pedir la atención inmediata de la CPU en situaciones de emergencia, como caída de voltaje o error de paridad de memoria. Cada interrupción lleva asociado un número que identifica el tipo de servicio que debe realizar. A partir del número de interrupción, calcula la dirección de la rutina que realiza el servicio requerido, la ejecuta y retorna a la instrucción siguiente a la última que ejecutó antes de que se produjera la interrupción. El mecanismo de la interrupción es simple: en un momento determinado se activa la entrada de la interrupción al procesador. El procesador suspende entonces la ejecución del programa en curso, pasando el control al programa de interrupción. Este programa tratará la causa de la interrupción, desactivará el dispositivo que la ha producido y devolverá el control al programa principal. El programa principal es transparente a este proceso y no tiene ninguna indicación de que se ha producido, salvo, por supuesto, por el tiempo de proceso transcurrido. Una función que ejecutan todas las interrupciones al activarse el programa de interrupción es salvar los registros del procesador para evitar que sean modificados y alteren el funcionamiento del programa suspendido. Estos registros se restauran justo antes de volver al programa principal. Éste tiene, sin embargo, la posibilidad de bloquear las interrupciones mediante instrucciones que activan o desactivan una bandera de interrupción (bandera IF). Tal posibilidad es necesaria cuando el programa principal accede a datos o periféricos que son también utilizados por las interrupciones, pues se pueden producir situaciones erróneas cuando los dos (proceso e interrupción) intenten utilizar los mismos recursos simultáneamente. La mayoría de los procesadores disponen de una entrada especial de interrupción que no puede ser impedida por software: se trata de la NMI (non maskable interrupt). Esta entrada es necesaria para aplicaciones de alta prioridad y urgencia (como es el caso de un fallo en la alimentación) en los que el procesador tiene escaso tiempo para detener los procesos y salvar los datos vitales de la máquina. Vectores de interrupción La familia IBM PC, como todos los ordenadores basados en la familia de microprocesadores Intel 8086/8088, se controla en gran medida a través de la utilización de interrupciones, las cuales pueden ser generadas por el hardware y el software, como ya se ha visto. Las rutinas de servicios del BIOS no son una excepción y cada una de ellas tiene asignada un número de interrupción al que se puede invocar cada vez que se quiera usar ese servicio. Cuando se produce una interrupción, el control del ordenador se transfiere a una subrutina de tratamiento de la interrupción que a menudo está almacenada en la ROM del sistema (una rutina de servicio del BIOS no es más que una rutina de tratamiento de interrupción). A esta rutina de tratamiento de la interrupción se le llama cargando su dirección 4 Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo de segmento y desplazamiento en los registros CS e IP, respectivamente. Las direcciones de segmentos que ubican las rutinas de tratamiento de la interrupción se llaman vectores de interrupción. Durante el proceso de arranque, la ROM BIOS establece los vectores de interrupción para que apunten a las rutinas de tratamiento de la interrupción en la ROM. La tabla de vectores de interrupción comienza al principio de la RAM, en la dirección 0000:0000. Cada entrada de la tabla se almacena como una pareja de palabras, con el desplazamiento en la primera parte y el segmento en la segunda. Los vectores de interrupción pueden cambiarse para que apunten a una nueva rutina de tratamiento de la interrupción simplemente ubicando el vector y cambiando su valor. Proceso de arranque Cuando el PC se pone en funcionamiento, el proceso de carga del sistema2 se inicia por medio de la ROM y después se carga el sistema operativo (en nuestro caso el DOS), ya sea desde un disco flexible o desde el disco duro. En la memoria también se cargan varias rutinas del BIOS. Una vez realizado todo el proceso de carga, se instala en la memoria el procesador de comandos COMMAND.COM. Los archivos de arranque son el IO.SYS y el MSDOS.SYS, y, junto con el COMMAND.COM, constituyen la parte principal de la arquitectura del sistema operativo MSDOS. Las rutinas contenidas en los dos primeros archivos son las encargadas de manejar todos los dispositivos y controlar las tareas de I/O asociadas con los periféricos. Además, el segundo de ellos contiene todas las rutinas de servicio del DOS. A todas estas rutinas se accede por medio de interrupciones software y hardware(vistas en el apartado anterior). La importancia de estas rutinas es tal que son utilizadas por el 99.99% de los programas desarrollados para MS-DOS. A una gran parte de esas rutinas se accede por medio de una llamada a la interrupción 21h, conocida como interrupción del sistema (en el apéndice D se encuentra una lista de todas las interrupciones y de todos los servicios que ofrece esta interrupción 21h). Es poco probable que el usuario desee modificar las rutinas de servicio ya que ellas proporcionan un marco de referencia para llevar a cabo tareas de programación muy tediosas. Ejecución de programas Este apartado pretende clarificar, sin entrar en demasiados detalles técnicos, la forma en que se ejecutan las instrucciones y cómo funciona la CPU. 2 En el capítulo 3 de [Nor01] hay información muy detallada sobre este proceso. También hay información en [Ray00], [PCI00] y [Terr00] 5 Grupo de Arquitectura de Computadores y Diseño Lógico. UEX, 1997. http://atc.unex.es/gacdl Funcionamiento del 8086/8088 Germán Galeano Gil. Juan A. Gómez Puildo 1. Lo primero que ocurre es que el oscilador (reloj) envía un pulso a la circutería. 2. Entonces la CPU envía por el bus de direcciones la posición (dirección de memoria) de la instrucción siguiente a la última ejecutada. Este paso se denomina también fase de búsqueda, y en ella la CPU ordena la transferencia del contenido del contador de programa al registro de selección de memoria y envía a la memoria la orden de lectura. 3. Una vez enviada la petición, el sistema lee el contenido de los bytes de la posición que contiene la instrucción y sus parámetros, si es que posee, para enviarlos a la CPU a través del bus de datos. 4. Cuando llega la instrucción a la CPU, ésta la decodifica, tras lo cual se inicia la fase de búsqueda de operandos, en la que la CPU transfiere la dirección del operando, en el caso de que éste se encuentre en memoria. Posteriormente se realiza el mismo proceso con el otro operando. 5. Una vez obtenidos los operandos, la instrucción es ejecutada. Para ejecutarse, cada instrucción necesita un número diferente de ciclos o señales de oscilador. 6