Sei sulla pagina 1di 30

GENERACION DE

CODIGO OBJETO
INTRODUCCIÓN
• Una vez terminado el análisis sintáctico, comienza la generación de código.
Esta fase suele dividirse en dos partes:
• Generación de código intermedio.
• Generación de código de maquina.
• El código intermedio se genera para una máquina virtual. Estas máquinas se
definen con dos objetivos:
• Ser lo suficientemente simples como para poder generar código para ellas de manera
sencilla, pero con la suficiente riqueza para poder expresar las construcciones del
lenguaje fuente.
• Estar lo suficientemente próximas a los procesadores reales para que el paso del código
intermedio al código de máquina sea prácticamente directo.
• Aunque en principio estas dos fases bastan para la generación del código
final, en la práctica están mezcladas con fases de optimización.
• La generación de código tiene como objetivo generar el ejecutable que después empleará el
usuario. Sin embargo, es habitual que el producto del compilador no sea directamente un
fichero ejecutable. Es bastante más común que sea un fichero en lenguaje ensamblador. De
esta manera, se evitan problemas como tener que medir el tamaño exacto de las
instrucciones o llevar la cuenta de sus direcciones. Además, es muy probable que el código
generado tenga referencias a objetos externos como funciones de biblioteca.
REGISTROS
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.
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.
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:
Durante la asignación de los registros: se selecciona el conjunto
de variables que residirá en los registros en un momento del
programa.
Durante la fase posterior de asignación a los registros, se
escoge el registro específico en el que residirá una variable.
LENGUAJE
ENSAMBLADOR
El lenguaje ensamblador es un lenguaje de
programación de bajo nivel. Consiste en un conjunto
de mnemónicos que representan instrucciones básicas para
los computadores, microprocesadores, microcontroladores y
otros circuitos integrados programables. Implementa una
representación simbólica de los códigos máquina binarios y
otras constantes necesarias para programar una arquitectura
de procesador y constituye la representación más directa
del código máquina específico para cada arquitectura legible
por un programador.
CARACTERÍSTICAS
El código escrito en lenguaje ensamblador posee una cierta dificultad

de ser entendido ya que su estructura se acerca al lenguaje máquina,


es decir, es un lenguaje de bajo nivel.

El lenguaje ensamblador es difícilmente portable, es decir, un código


escrito para un microprocesador, puede necesitar ser modificado, para


poder ser usado en otra máquina distinta. Al cambiar a una máquina
con arquitectura diferente, generalmente es necesario reescribirlo
completamente.

Los programas hechos por un programador experto en lenguaje


ensamblador son generalmente mucho más rápidos y consumen


menos recursos del sistema (memoria RAM y ROM) que el programa
equivalente compilado desde un lenguaje de alto nivel. Al programar
cuidadosamente en lenguaje ensamblador se pueden crear
programas que se ejecutan más rápidamente y ocupan menos
espacio que con lenguajes de alto nivel.
EJEMPLO
Un programa escrito en lenguaje ensamblador consiste en una serie
de instrucciones que corresponden al flujo de órdenes ejecutables
por un microprocesador.
Por ejemplo, en el lenguaje ensamblador para un procesador x86:
La sentencia:
MOV AL, 61h
Asigna el valor HEXADECIMAL 61 (97 DECIMAL) al registro "AL". El
programa ensamblador lee la sentencia de arriba y produce su
equivalente BINARIO en LENGUAJE DE MÁQUINA.
Binario: 10110000 01100001 (hexadecimal: B61)
El código de máquina generado por el ensamblador consiste de 2 bytes.
El primer byte contiene empaquetado la instrucción MOV y el código del
registro hacia donde se va a mover el dato:

En el segundo byte se especifica el número 61h, escrito en binario


como 01100001, que se asignará al registro AL, quedando la sentencia
ejecutable como:
10110000 01100001
La cual puede ser entendida y ejecutada directamente por el procesador.
LENGUAJE MÁQUINA
EL LENGUAJE MÁQUINA ES EL ÚNICO QUE ENTIENDE
LA COMPUTADORA DIGITAL, ES SU "LENGUAJE
NATURAL". EN ÉL SÓLO SE PUEDEN UTILIZAR DOS
SÍMBOLOS: EL CERO (0) Y EL UNO (1). POR ELLO, AL
LENGUAJE MÁQUINA TAMBIÉN SE LE
DENOMINA LENGUAJE BINARIO.
El lenguaje máquina es el
Fue el primer lenguaje
único lenguaje que puede
utilizado en la Los bits 0 y 1; físicamente,
ejecutar una
programación para las se materializan con
computadora, es
primeras computadoras, tensiones comprendidas Todo código fuente en
específico en cada
pero dejó de utilizarse por entre 0 y 4.0 voltios y última instancia debe
arquitectura, es un código
su dificultad y entre 4 y 5 voltios, llevarse a un lenguaje
que es interpretado
complicación, siendo respectivamente. Para máquina mediante el
directamente por el
sustituido por otros representar datos que proceso de compilación o
microprocesador, está
lenguajes más fáciles de contengan una interpretación para que la
compuesto por un
aprender y utilizar, y que información se utilizan computadora pueda
conjunto de instrucciones
además reducen la una serie de unos y ceros ejecutarlo.
ejecutadas en secuencia
posibilidad de cometer cuyo conjunto indica dicha
que representan acciones
errores. información.
que la máquina podrá
tomar.
El código máquina, o lenguaje de máquina, está formado por instrucciones sencillas,
que dependiendo de la estructura del procesador pueden especificar:

Registros específicos para operaciones aritméticas, direccionamiento o control de


funciones.

Posiciones de memoria específicas (offset).

Modos de direccionamiento usados para interpretar operando.

Las instrucciones de máquina o instrucciones del computador son las que determinan el funcionamiento de la
CPU que las ejecuta, la CPU puede realizar una diversidad de funciones que son el reflejo de la variedad de las
instrucciones definidas para dicha CPU, el programador tiene un repertorio de instrucciones como medio para
controlar la CPU.

Las operaciones más complejas se realizan combinando estas instrucciones sencillas, que
pueden ser ejecutadas secuencialmente o mediante instrucciones de control de flujo.
• El lenguaje máquina realiza un conjunto de operaciones
predeterminadas llamadas microoperaciones.
1

• Las microoperaciones sólo realizan operaciones del tipo


aritmética (+,-,*, /), lógicas (AND, OR, NOT) y de control
2 (secuencial, decisión, repetitiva).

• El lenguaje máquina es dependiente del tipo de


arquitectura.
3
Direccionamiento Es la forma en cómo se accede a la memoria. Recordar
que un programa no puede ejecutarse sino se encuentra en memoria
principal. La forma de acceder a la memoria depende del microprocesador,
pero en general existen dos tipos de direccionamiento: directo e indirecto.

El direccionamiento directo también recibe el nombre de


direccionamiento absoluto y el acceso a las direcciones se hace de
manera directa.

El direccionamiento indirecto también recibe el nombre de


direccionamiento relativo y se basa a partir de una dirección genérica,
generalmente el inicio del programa. Para acceder a una dirección
relativa se suma a la dirección base el número de espacios de
memorias necesarias.
VENTAJAS DEL LENGUAJE MÁQUINA

• Posibilidad de cargar (transferir un programa a la memoria) sin


necesidad de traducción posterior, lo que supone una
velocidad de ejecución superior a cualquier otro lenguaje de
programación.
DESVENTAJAS DEL LENGUAJE MÁQUINA

• Dificultad y lentitud en la codificación.


• Poca fiabilidad.
• Gran dificultad para verificar y poner a punto los programas.
• Los programas solo son ejecutables en el mismo procesador
(CPU).
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 li
nealmente con un direccionamiento secuencial, esto difícilmente
concuerde con el camino seguido por el programa, debido al uso de
procedimientos, funciones, subrutinas, arreglos, etc.
EJEMPLO
GENERACIÓN DE CÓDIGO OBJETO
• El enfoque más simple de la etapa de generación del código
objeto es:
• Para cada instrucción (del código intermedio) se tiene una
plantilla con la correspondiente secuencia de instrucciones
en lenguaje simbólico del procesador objetivo.
La secuencia de instrucciones
LD AX,B
LD BX,C
en lenguaje simbólico que
A:=B+C corresponde a esa instrucción
ADD AX,BX
ST AX,A depende de la arquitectura
del procesador para el cual el
GENERACIÓN DE CÓDIGO GENERACIÓN DE CÓDIGO programa es generado
INTERMEDIO OBJETO

Potrebbero piacerti anche