LENGUAJES Y AUTOMATAS II
MAYO 2014
INTRODUCCION
El desarrollo de software se puede dividir en 2 grandes categoras. El
software comercial y el software cientfico. La presente materia proporciona las
bases para crear software cientfico. Es comn pensar que el estudiante normal
nunca tendr acceso a desarrollar software cientfico, sin embargo, esto es un
error ya que cada da las necesidades se van ampliando y todo va siendo ms
accesible. Tenemos el clsico ejemplo de la robtica. Actualmente ya hay tiendas
donde venden accesorios para hacer un pequeo robot de juguete. Eso antes no
se vea y ahora ya es comn.
Por lo mismo, es importante proporcionarle al alumno las bases para que l se
introduzca con profundidad en el mundo de los compiladores. Esta materia abre
horizontes impresionantes ya que se conoce a fondo las etapas por las que
atraviesa la creacin de un lenguaje de computacin. Desde la etapa lxica hasta
la etapa de generacin de cdigo, el estudiante debe profundizar en
conocimientos que colindan con la parte electrnica de la computadora, el
lenguaje ensamblador, el lenguaje mquina.
Esta materia es una aventura racional. Algunos pensarn que es un tormento
cerebral, pero los inteligentes sabrn apreciar todas las competencias que se
desarrollan en esta materia.
Cabe mencionar que esta materia es la 2. Parte de la materia Lenguajes y
autmatas, por lo tanto se debe dedicar cierto tiempo a dar un repaso prctico a la
1. Parte de la materia que consisti en las 2 primeras fases de los compiladores:
fase lxica y fase sintctica.
Si no se da este repaso se corre el peligro de que el alumno no entienda sta
segunda parte ya que van muy ligadas.
Es muy recomendable utilizar un compilador didctico.
Se recomienda
ampliamente el compilador desarrollado por Kenneth Louden. En la bibliografa al
final de este documento se encuentra con la referencia nmero 3 y nmero 12.
Esto debido a que el alumno debe conocer un compilador ya hecho para as
entender al 100% todos los conceptos.
PROPOSITO
CONTENIDO
OBJETIVO
Desarrollar software de base: traductor, intrprete o compilador.
CONTENIDO
Arboles de expresiones.
1.2.
UNIDAD 3 Optimizacin
CONTENIDO TEMATICO
En este captulo analizamos la fase del compilador que calcula la informacin
ad~cional necesaria para la compilacin una vez que se conoce la estructura
sintctica de un programa. Esta fase se conoce como anlisis semntico debido a que
involucra el clculo de informacin que rebasa las capacidades de las gramticas
Un smbolo inicial N.
La tarea del analizador sintctico (parser) es determinar si una cadena de entrada puede
derivarse a partir del smbolo inicial, y si es as, cmo puede hacerse. Hay dos maneras
bsicas de hacer esto:
Analizadores LL vs. LR
transicin a otro estado. Esto hace que los analizadores LR sean ms resistentes a
las ambigedades que los LL, pero pueden resultar en analizadores que requieren
ms recursos (en trminos de tiempo de procesamiento y espacio de memoria).
Los analizadores LALR (Look Ahead LR) son una especializacin de los
analizadores LR. Pueden manejar ms GLC que el LR bsico. Es un tipo de
analizador muy popular porque logra un buen balance entre el nmero de
gramticas que puede manejar y su consumo computacional (en trminos de
procesador y memoria). Las herramientas Yacc y Bison generan analizadores
sintcticos de este tipo.
1. E1 E2 + T
E1.val := suma(E2.val, T.val)
2. E1 E2 - T
E1.val := diferencia(E2.val, T.val)
3. E T
E.val := T.val
4. T1 T2 * F
T1.val := producto(T2.val, F.val)
5. T1 T2 / F
T1.val := cociente(T2.val, F.val)
6. T F
T.val := F.val
7. F1 -F2
F1.val := inverso(F2.val)
8. F ( E )
F.val := E.val
9. F constante
F.val := constante.val
Como vemos, en estas reglas de la gramtica de atributos, asignar significados a las
sentencias del lenguaje equivale a asignar una funcin que recibe como parmetros los
componentes de la sentencia y regresa un valor que se asigna a esa expresin.
Resumen
Hemos visto hasta ahora que el anlisis sintctico y el anlisis semntico utilizan algunas
herramientas matemticas para realizar sus funciones: rboles sintcticos y gramticas de
atributos. Estas herramientas nos permiten definir la sintaxis y semntica de un lenguaje y
nos preparan para la generacin de cdigo intermedio.
UNIDAD 2 Generacin
cdigo intermedio.
de
CONTENIDO TEMATICO
Cdigo mquina
La aparicin de los lenguajes de alto nivel mejor la productividad de los programadores al
liberarlos de los detalles de bajo nivel de la computadora que estaban programando. El
compilador es quien se encarga de realizar la conversin del cdigo fuente en lenguaje de alto
nivel al cdigo mquina de la computadora que ejecutar el programa. Es, por tanto, el
compilador quien ahora maneja los detalles de bajo nivel de la arquitectura a programar. Esto
implica que el desarrollo del compilador requiere del conocimiento de los detalles de la
arquitectura de la mquina destino. En este apartado conoceremos la computadora abstracta para
la que Tiny traduce sus programas.
De cdigo
De datos
De direcciones de retorno
Los lmites de cada tipo de memoria estn indicados por una serie de registros. La siguiente
figura ilustra estas memorias y sus registros lmite:
El cdigo mquina para este programa se muestra abajo. Obviamente, los comentarios no
son generados por el generador de cdigo.
LIT 0 # Espacio para Count
LIT 1 # Asigna 1
SGV 0 # Count := 1
L2 LGV 0 # Carga Count
LIT 10 # Carga 10
BOP BLE # POP, Compara. Push resultado T/F
COND L3 L4 # Pop stack, si V, ve a L3, sino, ve a L4.
L3 SOS INPUT # Llamada al SO. Lee y coloca en la pila
SOS OUTPUT # Llamada al SO. Saca de la pila y despliega
SOS OUTPUTL # Despliega un avance de lnea
LGV 0 # Carga Count
LIT 1 # Carga 1
BOP BPLUS # Smalos y guarda resultado en la pila
SGV 0 # Saca de la pila y almacena en Count
GOTO L2 # Regresa a L2
L4 HALT # Salta aqu cuando termines. Detnte.
Ejemplo 2
Con el fin de ayudar al entendimiento de esta mquina estudiaremos otro programa
ejemplo, escrito en el lenguaje Medium, que es el lenguaje intermedio para Tiny:
program fact:
var m: integer;
function fact(n: integer) : integer
begin
If n > 0 then
fact := n * fact( n 1 );
else
fact := 1;
m := m + 1;
end;
begin
m := 0;
output( fact( read ), m );
end fact.
El cdigo para la mquina abstracta es el siguiente:
LIT 0
GOTO L1
L2 LLV 1
LIT 0
BOP BGT
COND L3 L4
L3 LLV 1
LIT 0
LLV 1
LIT 1
BOP BMINUS
CODE L2
CALL 3
BOP BMULT
SLV 0
GOTO L5
L4 LIT 1
SLV 0
NOP
L5 LGV 0
LIT 1
BOP BPLUS
SGV 0
LLV 0
RTN 1
L1 LIT 0
SGV 0
LIT 0
SOS INPUT
CODE L2
CALL 1
SOS OUTPUT
LGV 0
SOS OUTPUT
SOS OUTPUTL
HALT
Es muy recomendable que traces con papel y lpiz la ejecucin de estos dos programas de
ejemplo para que entiendas mejor la programacin en bajo nivel de la mquina abstracta.
UNIDAD 3 Optimizacin.
Competencia especfica de la unidad:
Conocer e Identificar los diferentes tipos de optimizacin que permita eficientar el
cdigo intermedio.
CONTENIDO TEMATICO
Estrategias de optimizacin
La optimizacin del cdigo es el proceso de "puesta a punto" (tuning) de la salida de un
compilador con el fin de minimizar o maximizar algn atributo del programa objeto. Es
comn que la meta de la optimizacin sea minimizar el espacio en memoria que ocupa del
cdigo o maximizar la velocidad de ejecucin.
Una forma de clasificar las estrategias de optimizacin del cdigo se basa en el alcance de
la optimizacin: desde una sola instruccin (optimizacin local), hasta un programa entero
(optimizacin global).
Tcnicamente hablando es ms sencillo implementar estrategias locales que globales,
aunque normalmente el beneficio es menor que el obtenido con estrategias globales.
Algunos ejemplos de estrategias de optimizacin clasificadas por su alcance son:
Para evitar complicar mucho al compilador de Tiny, la herramienta TWS no maneja ningn
tipo de optimizacin; sin embargo, muchos compiladores s lo hacen, ya que la posibilidad
de obtener cdigo optimizado siempre es un atractivo ms para cualquier compilador,
independientemente del lenguaje a traducir.
Deteccin de errores
Los errores de programacin pueden clasificarse en tres categoras:
Errores de compilacin
Errores de ejecucin
Errores lgicos
Errores de compilacin
Son errores que aparecen cuando se est compilando el programa y eventualmente
ocasionan que se detenga el proceso de traduccin.
Muchos de estos errores son causados por equivocaciones de captura, por ejemplo, un mal
deletreo de alguna palabra clave, mezcla incorrecta de maysculas y minsculas en los
nombres de variables, o la falta de un signo de puntuacin, entre otros.
Son los errores ms fciles de corregir porque contamos con la ayuda del compilador.
Cuando el compilador detecta un error durante el analizador sintctico o no puede asignar
significado a una expresin durante el anlisis semntico, genera un mensaje de error
mostrando una breve descripcin del error y la lnea del cdigo fuente donde lo encontr.
Normalmente el compilador intenta seguir el proceso de traduccin con el fin de detectar la
mayor cantidad posible de errores e informarlos al programador para que proceda a
corregirlos.
Cuando aparecen varios errores de compilacin, por lo general slo el primer error es real,
los dems pueden no serlo.
Errores de ejecucin
Son errores que aparecen mientras el programa est en ejecucin.
Un ejemplo tpico es la divisin entre cero; por ejemplo, supn que tienes la siguiente
expresin:
velocidad = kilmetros / horas
Si la variable horas = 0 cuando se intente ejecutar la instruccin, la divisin no puede
calcularse y se genera un error de ejecucin.
Errores lgicos
Causan que el programa no funcione correctamente y que arroje resultados equivocados.
En este tipo de errores la compilacin termina sin errores y el programa se ejecuta sin
errores de ejecucin, pero arroja resultados no esperados, stos son los ms difciles de
encontrar y corregir.
returnrule(yytext[0]);
A continuacin reproducimos la parte del analizador sintctico que define las operaciones
aritmticas:
Expression ->Term
->Term LTE Term => "<=";
Term ->Primary
->Primary '+' Term => "+";
Primary -> '-' Primary => "-"
-> READ => "read"
->Name
->INTEGER_NUM => "<integer>"
-> '(' Expression ')';
Name -> IDENTIFIER => "<identifier>";
Para introducir el operador de la multiplicacin, se debe agregar un nuevo productor de
factor:
Expression ->Term
->Term LTE Term => "<=";
Term ->Primary
->Primary '+' Term => "+";
Factor ->Primary
->Primary '*' Factor => "*";
Primary -> '-' Primary => "-"
-> READ => "read"
->Name
->INTEGER_NUM => "<integer>"
-> '(' Expression ')';
Name -> IDENTIFIER => "<identifier>";
Modificaciones al constrainer
El constrainer consiste de la clase tws::constrainer y del archivo de cabecera nodes.h, que
definen los nodos del rbol que el constrainer y el generador de cdigo deben recorrer para
realizar su trabajo. El archivo nodes.h contiene las siguientes lneas:
addnode(ProgramNode,"program");
addnode(TypesNode, "types");
addnode(TypeNode, "type");
addnode(DclnsNode ,"dclns");
addnode(DclnNode, "dcln");
addnode(IntegerTNode,"integer");
addnode(BooleanTNode, "boolean");
addnode(BlockNode,"block");
addnode(AssignNode, "assign");
addnode(OutputNode, "output");
addnode(IfNode ,"if");
addnode(WhileNode ,"while");
addnode(NullNode , "null");
addnode(LENode ,"<=");
addnode(PlusNode ,"+");
addnode(MinusNode,"-");
addnode(ReadNode,"read");
addnode(IntegerNode,"<integer>");
addnode(IdentifierNode,"<identifier>");
Se debe agregar la siguiente lnea para el nodo de la multiplicacin:
addnode(MultNode ,"*");
El archivo de la clase tws::constrainer tiene el mtodo expression(), que analiza las
expresiones en el AST y determina si estn bien formadas. A continuacin mostramos el
fragmento de este mtodo que verifica los nodos "+" y "-":
if ((nodename == PlusNode) or (nodename == MinusNode)){
Type1 = expression(T->get_child(0));
if(T->get_degree()==2){
Type2 = expression(T->get_child(1));
}else{
Type2 = TypeInteger;
}
if( (Type1 != TypeInteger) or (Type2 != TypeInteger)){
error(T);
cout<< "ARGUMENTS OF '+', '-' etc. MUST BE OF TYPE\
INTEGER" <<endl;
}
returnTypeInteger;
}
Para manejar el nuevo nodo de multiplicacin "*", se debe agregar el siguiente cdigo al
mtodo:
if (nodename == MultNode){
Type1 = expression(T->get_child(0));
Type2 = expression(T->get_child(1));
if( (Type1 != TypeInteger) or (Type2 != TypeInteger)){
error(T);
cout<< "ARGUMENTS OF '*', MUST BE OF TYPE\
INTEGER" <<endl;
}
returnTypeInteger;
}
Modificaciones al generador de cdigo
El cdigo para las expresiones aritmticas es generado en la clase tws::codegenerator, en el
mtodo expression(). A continuacin mostramos el fragmento de este mtodo que genera el
cdigo para el nodo "-":
if (name == MinusNode){
expression(T->get_child(0),CurrLabel);
if (T->get_degree() == 2){
expression(T->get_child(1),NoLabel);
codegen(NoLabel,BOPOP,BMINUS);
dec_framesize();
}else{
codegen(NoLabel,UOPOP,UNEG);
}
}
El cdigo para el nodo "*" debe generarse de la siguiente manera:
if (name == MultNode){
expression(T->get_child(0),CurrLabel);
expression(T->get_child(1),NoLabel);
codegen(NoLabel,BOPOP,BMULT);
dec_framesize();
}
Donde BMULT es la instruccin en ensamblador para la multiplicacin.
Recompilando el traductor
Una vez realizados todos los cambios anteriores en sus respectivos archivos fuente, es
necesario recompilar nuestro traductor. Esto lo hacemos por medio de la utilera make, es
decir, estando ubicados en el directorio tws simplemente tecleamos:
make
Probando la multiplicacin
El ltimo paso es capturar y compilar un programa que utilice la nueva instruccin, por
ejemplo:
{Archivo: mult.tiny }
programmulti:
var factor1,factor2, producto : integer;
begin
factor1 := read;
factor2 := read;
producto = factor1 * factor2;
output(producto)
endmulti.
Recuerda que compilas el programa con la instruccin:
tc mult.tiny
UNIDAD 4 Generacin
cdigo objeto.
del
NOP
HALT : Detenerse (halt)
Hacer
nada
De transferencia de datos
LIT v : Cargar (Push) la Literal v en Local frame (Lf) de la memoria
LLV
i
:
Cargar
valor
local
(Load
Local
Value)
i
LGV
i
:
Cargar
valor
global
(Load
Local
Value)
i
SLV i : Almacena valor local i (Store Local Value i)
SGV
i
:
Almacena
valor
global
LLA i : Cargar Direccin Local i (Load Local Address i)
LGA i : Cargar Direccin Global i (Load Global Address i)
POP
n
:
Extrae
n
valores
(Pop
n
DUP
:
DUPlica
el
tope
de
la
SWAP : Intercambia los 2 valores superiores de la pila.
de datos.
en
Lf.
en
Lf.
en Lf.
i.
en Lf.
en Lf.
values).
pila.
Aritmticas y lgicas
UOP i : Operacin unitaria i (Unary Operation i): const X = Pop Lf.
Push
(Unop(i,X))
en
Lf
BOP i : Operacin binaria i: const Xr,Xl = Pop Lf, Pop Lf
Push (Binop(i,Xl,Xr)) en Lf
De control de flujo
CALL
n
:
Llamada
a
una
subrutina.
RTN
n
:
Retorno
de
rutina.
GOTO
L
:
I
<L
Salto
incondicional
a
L
COND L M : I <- if Pop Lf = True # Pop Stack. Si el valor es:
then
L
#
Verdadero,
salta
a
L
else
M
#
Falso,
salta
a
M.
fi
CODE
F
:
Push
F
on
Lf
#
Carga
el
punto
de
entrada.
SOS i : Llamada a la funcin i del sistema operativo
Para las operaciones aritmticas y lgicas tenemos que:
Unop(i,X)
case
UNOT
UNEG
USUCC
UPRED : X-1
i
:
:
:
significa:
of
not(X)
-(X)
X+1
Binop(i,Xl,Xr)
case
BAND
BOR
BPLUS
BMINUS
BMULT
BDIV
BMOD
BEQ
BNE
BLE
BGE
BLT
BGT : Xl > Xr
:
:
:
:
:
:
:
:
:
:
:
:
i
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
and
or
+
*
div
mod
=
<>
<=
>=
<
significa:
of
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Llamadas al sistema
Para simplificar el manejo de los dispositivos de Entrada/Salida suponemos que tenemos
disponibles algunas llamadas al sistema operativo, a las cuales se accede por medio de la
instruccin SOS:
SOS i significa:
case
i
TRACEX
:
Trace_Execution
DUMPMEM:
INPUT
:
Push
i
INPUTC
:
Push
Ord(ch)
OUTPUT
:
write
OUTPUTC:
write
OUTPUTL:
EOF
:
then
Push
True
else Push False on Lf
<-
not
on
on
(Pop
if
on
of
TraceExecution
Dump_Memory
readln(i)
Lf
readln(ch)
Lf
Lf)
(Chr(Pop(Lf)))
writeln
eof(input)
Lf
Cuando compilamos un programa de Tiny se generan varios archivos a partir del programa
fuente; estos archivos son:
Es importante anotar que estos archivos se sobrescriben cada vez que compilo un programa
en Tiny. Esto es til porque me permite analizar el cdigo generado por el compilador de
Tiny para el ltimo programa traducido, y se evita el uso inmoderado del espacio en disco.
A manera de ejemplo, vamos a ver el cdigo generado por el compilador de Tiny para el
programa de prueba p7, que se muestra a continuacin:
program
begin
output(3)
end x.
x:
Recuerda que para compilar este programa debes ejecutar el programa Cygwin. El
comando para compilar este archivo, esta ubicado en el directorio tiny, es:
./tc tests/p7
En la siguiente figura se muestra el resultado de la compilacin y ejecucin de p7.
Tambin se pueden observar los comandos "cd" para posicionarme en el directorio de tiny:
A continuacin te muestro el contenido del archivo _CGEN creador por el compilador de
Tiny:
<<< CODE
<<< CODE
<<< CODE
<<< CODE
<<< CODE
LIT
Incrementing
SOS
Decrementing
SOS
HALT
to
Framesize
to
Label
Label
Label
Label
Label
is
is
is
is
is
3
1
OUTPUT
0
OUTPUTL
Recuerda que el generador de cdigo recorre el rbol sintctivo generado por el analizador
sintctico y revisado por el analizador semntico, para ir generando el cdigo objeto.
Observa que el primer nodo analizado es el nodo program, despus el nombre del
programa, que es un nodo decln, posteriormente un nodo block (bloque), cuyo inicio es
indicado por el begin, despus una instruccin de salida (ouput), que recibe como
parmetro un nodo entero (3, en este caso). Esta instruccin output(3) se traduce por las
instrucciones lit 3, sos output y sos outputl. Posteriormente, la instruccin end x.que se
traduce por halt.
El contenido del archivo _CODE es el siguiente:
LIT
SOS
SOS
HALT
3
OUTPUT
OUTPUTL
Fcilmente puede verse que es el mismo cdigo objeto que aparece en el archivo _CGEN,
pero sin comentario alguno. Este archivo nos muestra el contenido del archivo ejecutable
que se "cargar" al intrprete de la mquina abstracta para su ejecucin.
Ejemplo del cdigo generado por el compilador de Tiny para una estructura
selectiva
Para ilustrar el cdigo generado por el compilador de Tiny para una estructura selectiva,
vamos a analizar brevemente el cdigo generado por el siguiente programa:
program
begin
if(
1
end ejemplo2.
ejemplo2:
<=
then
output(1)
else
output(2)
Label
Label
Label
,
Label
,
Label
, Label
,
,
is
is
is
is
is
is
1
1
>>>
Processing
Node
Framesize
Framesize
L1
Framesize
>>> Processing Node
>>> Processing Node
LIT
Framesize
Framesize
<integer>
Label
is
2
to
2
BLE
to
1
L2
to
0
output , Label is L1
<integer> , Label is L1
1
to
1
OUTPUT
to
0
OUTPUTL
L3
output , Label is L2
<integer> , Label is L2
2
to
1
OUTPUT
to
0
OUTPUTL
L1
LIT
1
2
BLE
L2
1
OUTPUT
OUTPUTL
L3
L2
SOS
SOS
NOP
L3 HALT
LIT
2
OUTPUT
OUTPUTL
Ejemplo del cdigo generado por el compilador de Tiny para una estructura
repetitiva
Para analizar brevemente el cdigo generado por el compilador de Tiny para una estructura
repetitiva, vamos a revisar brevemente el cdigo generado para el siguiente programa:
program
var
begin
while
begin
output(i);
i
end;
end mientras.
mientras:
i:integer;
i
:=
<=
do
1;
LGV
L2
0
0
5
BLE
L3
L2
SOS
SOS
LGV
LIT
BOP
SGV
GOTO
L3 HALT
LGV
0
OUTPUT
OUTPUTL
0
1
BPLUS
0
L1
Donde:
1. LIT 0 es la instruccin que utiliza el compilador de Tiny para definir una variable
(en este caso la variable entera i).
2. LGV 0 (que en este ejemplo est etiquetada con L1), es la instruccin para referirse
a esa primera variable y cargarla en el tope de la pila.
3. Posteriormente carga el nmero 5 en el tope de la pila (LIT 5) y compara con la
operacin BOP BLE (Salta si menor o igual). Si el contenido de la variable i es
menor o igual a 5, entonces salta a L2, si no salta a L3 (COND L2 L3).
4. L2: Carga i en el tope de la pila (LGV 0), llama a output para que se despliegue en
pantalla (SOS OUTPUT) y despliega un "avance de lnea" llamando a outputl (SOS
OUTPUTL).
5. Carga i en el tope de la pila (LGV 0) y el 1 en el tope de la pila (LIT 1).
6. Realiza la operacin suma con los dos datos en el tope de la pila y guarda el
resultado en la variable i (BOP BPLUS).
7. Salta incondicionalmente a L1 (GOTO L1), que es la verificacin de la condicin
del while().
8. L3: Termina (halt).
Tomando como base estos ejemplos, realiza ahora la actividad correspondiente a esta
seccin del Mdulo 4: Disear el cdigo que deben generar cada una de las instrucciones
que agregars al compilador de Tiny:
Operacin mdulo.
Operacin autoincremento.
Operacin autodecremento.
Estructura for().
Estructura repeat ... until().
Mdulo
Autoincremento
Autodecremento
Estructura for ()
Estructura repeat ... until
2.
3.
4.
5.
f.
BIBLIOGRAFIA
Associates.
19. The Lex & Yacc Page, 3-mar-04, 12:45, http://dinosaur.compilertools.net
20. A compact guide to lex & Yacc, Thomas Niemann, 3-Mar-04, 12:50,
http://epaperpress.com/lexandyacc
21. Lex & Yacc HOWTO, Bert Hubert (PowerDNS.COM.BV), 3-Mar-04, 12:55,
http://ds9a.nl/lex_yacc
22. Flex, 3-mar-04, 13:02, http://www.gnu.org/software/flex/flex.html
23. Compiler construction using flex and Bison, Anthony Aaby, 3-mar-04, 13:05,
http://cs.wwc.edu/aabyan/464/BooK/
24. Flex, version 2.5 A fast scanner generator, Edition 2.5, March 1995, Vern
Paxson, 3-mar-04, 13:10,
http://www.cs.princelon.edu/appel/modern/c/software/flex/flex_toc.html
25. Bison. The Yacc-compatible Parser Generator, November 1995, Bison
Version 1.5, Charles Donnelly and Richard Stallman, 3-mar-04, 13:10,
http://www.cs.princelon.edu/appel/modern/c/software/bison/bison_toc
.html, 13/dic/2009
26. Bison. http://3d2f.com/programs/30-170-microprocessor-emulator-andassemblerdownload.shtml, 13/dic/2009
27. 2/Ago/2005 ,Microprocessor Emulator and Assembler 3.10-k,
http://software.intel.com/en-us/articles/all/1/, 24/feb/2010
28. Intel, 31/dic/2009, Intel Software Development EmulatorBottom of Form,
http://software.intel.com/enus/articles/intelsoftwaredevelopmentemulator/,
24/feb/2010