miércoles, 27 de noviembre de 2019
miércoles, 20 de noviembre de 2019
4.4 Administrador de memoria
4.4 Administrador de memoria
La administración de la memoria es un proceso hoy en día muy importante, de tal modo que su mal o buen uso tiene una acción directa sobre el desempeño de memoria. En general un ensamblador tiene un administrador de memoria más limitado que un compilador; en la mayoría de los lenguajes de programación el uso de punteros no estaba vigilado por lo que se tienen muchos problemas con el uso de memoria. Los lenguajes más recientes controlan el uso de punteros y tienen un programa denominado recolector de basura que se encarga de limpiar la memoria no utilizada mejorando el desempeño.
La memoria principal puede ser considerada como un arreglo lineal de localidades de almacenamiento de un byte de tamaño. Cada localidad de almacenamiento tiene asignada una dirección que la identifica
Se distinguen los siguientes propósitos del sistema de administración de memoria:
Protección.
Si varios programas comparten la memoria principal, se debería asegurar que el programa no sea capaz de cambiar las ubicaciones no pertenecientica él. Aunque una acción de escritura puede tener efectos más graves que una de lectura, esta última tampoco debería estar permitida, para proporcionar algo de privacidad al programa.
Compartimiento.
Este objetivo parece contradecir al anterior, sin embargo a veces es necesario para los usuarios poder compartir y actualizar información (por ejemplo, en una base de datos) y, si se organiza la tarea de entrada a la misma, se puede evitar el tener varias copias de la rutina.
Reubicación.
La técnica de multiprogramación requiere que varios programas ocupen la memoria al mismo tiempo. Sin embargo no se sabe con anticipación donde será cargado cada programa por lo que no es práctico usar direccionamiento absoluto de memoria.
Organización física.
Debido al costo de una memoria principal rápida, éste se usa en conjunto con una memoria secundaria mucho más lenta (y por consiguiente, barata) a fines de extender su capacidad.
Organización lógica.
Aunque la mayor parte de las memorias son organizadas linealmente con un direccionamiento secuencial, esto difícilmente concuerde con el camino seguido por el programa, debido al uso de procedimientos, funciones, subrutinas, arreglos, etc.
4.3 Lenguaje Máquina
4.3 Lenguaje Máquina
Es el que proporciona poca o ninguna abstracción del microprocesador de un ordenador. El lenguaje máquina solo es entendible por las computadoras. Se basa en una lógica binaria de 0 y 1, generalmente implementada por mecanismos eléctricos. En general el lenguaje maquina es difícil de entender para los humanos por este motivo hacemos uso de lenguajes más parecidos a los lenguajes naturales.
Se denomina lenguaje máquina a la serie de datos que la parte física de la computadora o hardware, es capaz de interpretar. El lenguaje máquina fue el primero que empleo el hombre para la programación de las primeras computadoras. Una instrucción en lenguaje máquina puede representarse de la siguiente forma: 011011001010010011110110. Esta secuencia es fácilmente ejecutada por la computadora, pero es de difícil interpretación, siendo aún más difícil la interpretación de un programa (conjunto de instrucciones) escrito de esta forma.
Esta dificultad hace que los errores sean frecuentes y la corrección de los mismos costosa, cuando no imposible, al igual que la verificación y modificación de los programas.
Características:
El lenguaje máquina realiza un conjunto de operaciones predeterminadas llamadas micro operaciones. Las micro operaciones sólo realizan operaciones del tipo aritmética (+,- ,*,/), lógicas (AND, OR, NOT) y de control (secuencial, de control y repetitiva). El lenguaje maquina es dependiente del tipo de arquitectura. Así un programa máquina para una arquitectura Intel x86 no sé ejecutara en una arquitectura Power PC de IBM (al menos de manera nativa).
Algunos microprocesadores implementan mas funcionalidades llamado CISC, pero son más lentos que los RISC ya que estos tienen registros más grandes.
Ventajas
- Mayor adaptación al equipo.
- Máxima velocidad con mínimo uso de memoria.
Desventajas
- Imposibilidad de escribir código independiente de la máquina.
- Mayor dificultad en la programación y en la comprensión de los programas.
- El programador debe conocer más de un centenar de instrucciones.
- Es necesario conocer en detalle la arquitectura de la máquina.
4.1 Registros
¿Qué son?
Los registros son la memoria principal de la computadora. Existen diversos registros de propósito general y otros de uso exclusivo. Algunos registros de propósito general son utilizados para cierto tipo de funciones. Existen registros acumuladores, puntero de instrucción, de pila, etc.
Los registros son espacios físicos dentro del microprocesador con capacidad de 4 bits hasta 64 bits dependiendo del microprocesador que se emplee.
¿Quiénes lo utilizan?
Antes de nada, para el desarrollo de esta parte hablaremos indistintamente de registros de activación o de marcos de pila. Esto se debe a que en la documentación encontrada sobre el manejo de los registros ebp y esp se hace mención a dicho concepto de marco de pila. Puesto que el lenguaje permite recursividad, los registros de activación se asignan dinámica mente.
Distribución
La UCP o CPU tiene 14 registros internos, cada uno de ellos de 16 bits (una palabra). Los bits están enumerados de derecha a izquierda, de tal modo que el bit menos significativo es el bit 0.
Los registros se pueden clasificar de la siguiente forma:
Registros de datos:
AX: Registro acumulador. Es el principal empleado en las operaciones aritméticas.
BX: Registro base. Se usa para indicar un desplazamiento.
CX: Registro contador. Se usa como contador en los bucles.
DX: Registro de datos.
Estos registros son de uso general y también pueden ser utilizados como registros de 8 bits, para utilizarlos como tales es necesario referirse a ellos como por ejemplo: AH y AL, que son los bytes alto (high) y bajo (low) del registro AX. Esta nomenclatura es aplicable también a los registros BX, CX y DX.
Registros de segmentos:
CS: Registro de segmento de código. Contiene la dirección de las instrucciones del programa.
DS: Registro segmento de datos. Contiene la dirección del área de memoria donde se encuentran los datos del programa.
SS: Registro segmento de pila. Contiene la dirección del segmento de pila. La pila es un espacio de memoria temporal que se usa para almacenar valores de 16 bits (palabras).
ES: Registro segmento extra. Contiene la dirección del segmento extra. Se trata de un segmento de datos adicional que se utiliza para superar la limitación de los 64Kb del segmento de datos y para hacer transferencias de datos entre segmentos.
Registros punteros de pila:
SP: Puntero de la pila. Contiene la dirección relativa al segmento de la pila.
BP: Puntero base. Se utiliza para fijar el puntero de pila y así poder acceder a los elementos de la pila.
Registros índices:
SI: Índice fuente.
DI: Índice destino.
La distribución es el proceso en el que el programa generado puede ejecutarse en otras máquinas.
Con respecto al ensamblador, la mayoría del direccionamiento se hace relativo para que el programa sea relocalizable por un programa llamado cargador.
En el caso de programas compilados se necesitan de las librerías, si son estáticas se incluyen en el ejecutable por lo que el programa se hace gráfico, si son dinámicas no pero el programa es más pequeño.
Debido a la complejidad del software actual se necesitan de asistentes para poder instalar y ejecutar un programa.
Operar sobre registros es más rápido y eficiente que operar sobre memoria. Por ello, la adjudicación eficiente de registros tiene un gran impacto en la performance. El uso de registros puede dividirse en dos subproblemas:
- Durante la reserva de registros (allocation), se seleccionan el conjunto de variables que vivirá en registros en un punto del programa.
- Durante la (posterior) asignación de registros (assignation), se elige el registro específico para cada variable.
¿Cuales su aplicación en la generación de códigos?
1. usar el registro de y si está en un registro que no tiene otra variable, y además y no
está viva ni tiene uso posterior. Si no:
2. usar un registro vacío si hay. Si no:
3. usar un registro ocupado si op requiere que x esté en un registro o si x tiene uso
Posterior. Actualizar el descriptor de registro. Si no:
4. usar la posición de memoria de x
4 - Generación de Código Objeto
4 - Generación de Código Objeto La fase final de un compilador es la generación de código objeto, que por lo general consiste en código de máquina relocalizable o código ensamblador. Las posiciones de memoria se seleccionan para cada una de las variables usadas por el programa. Después, cada una de las instrucciones intermedias se traduce a una secuencia de instrucciones de máquina que ejecuta la misma tarea. Un aspecto decisivo es la asignación de variables a registros. El generador de código objeto puede considerarse como la penúltima fase de un compilador, la cual se encarga de tomar como entrada el código intermedio generado por el front-end, y producir código objeto de la arquitectura target para luego entrar en la fase de optimización de código. Toma como entrada de representación intermedia el programa fuente y produce como salida un programa objeto equivalente. |
Aspectos generales Administración de memoria: la correspondencia entre los nombres del programa fuente con direcciones de objetos de datos en la memoria durante la ejecución la realiza la etapa inicial en cooperación con el generador de código. Las entradas en la Tabla de Símbolos se van creando conforme se examina las declaraciones de un procedimiento. El tipo en una declaración determina la cantidad de memoria necesaria para el nombre declarado. Según la información de la Tabla de Símbolos se pueden determinar una dirección relativa para el nombre de un área de datos para el procedimiento. Selección de instrucciones: es importante que el conjunto de instrucciones sea uniforme y completo. Las velocidades de las instrucciones es un factor importante. Si no se tiene en cuenta la eficiencia del programa objeto, la selección de instrucciones es sencilla. Para cada tipo de proposición de tres direcciones, se puede diseñar un esqueleto de código. Ejemplo: código de tres direcciones de: x := y + z MOV y, R0 /* cargar y en el registro R0 */ ADD z, R0 /* suma z a R0 */ MOV R0, x /* almacenar R0 en x */ Asignación de registros: Las instrucciones que implican operandos en registros son generalmente más rápidas que las de los operandos en memoria. Por lo tanto, utilizar eficientemente los registros es fundamental para generar un buen código. El uso de registros se divide en dos subproblemas:
Elegir un orden mejor es un problema difícil, NP-completo. |
Suscribirse a:
Entradas (Atom)
-
Las pilas y colas son estructuras de datos que se utilizan generalmente para simplificar ciertas operaciones de programación. Estas estruct...
-
3.2.1 Costo de ejecución (Memoria, registros, pilas) Costo de ejecución (Memoria, registros, pilas) Los costos de ejecución son a...
-
Criterios para mejorar el código La mejor manera de optimizar el código es hacer ver a los programadores que optimicen su códig...