Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Facultad de Ingeniería
Escuela de Ingeniería en Ciencias y Sistemas
Organización de Lenguajes y Compiladores 2
Segundo semestre 2019
Catedráticos: Ing. Bayron López, Ing. Erick Navarro e Ing. Edgar Saban
Tutores académicos: Luis Lizama, Rainman Sián, Julio Arango.
DOSLang
Contenido
1 Objetivos .................................................................................................................. 7
1.1 Objetivo general ............................................................................................ 7
1.2 Objetivos específicos .................................................................................... 7
2 Descripción .............................................................................................................. 7
2.1 Descripción de la aplicación .......................................................................... 7
2.1.1 DosLang ...................................................................................................... 7
2.1.2 DosIDE ........................................................................................................ 7
2.1.3 Consola ....................................................................................................... 8
2.1.4 Debugger ..................................................................................................... 8
2.1.5 Optimizador ................................................................................................. 8
2.1.6 Reportes ...................................................................................................... 9
2.2 Flujo del Proyecto ....................................................................................... 11
2.2.1 Flujo general de la aplicación .................................................................... 11
2.2.2 Flujo específico de la aplicación ................................................................ 12
3 Generalidades del lenguaje DOSLang ................................................................... 13
3.1 Tipos de dato .............................................................................................. 13
3.1.1 Tipos primitivos.......................................................................................... 13
3.1.2 Tipos definidos por el usuario .................................................................... 14
3.1.3 Tipos de dato enumerados ........................................................................ 14
3.1.4 Tipos de subrango ..................................................................................... 15
3.2 Arreglos ....................................................................................................... 15
1
3.2.1 Arreglos Multidimensionales y Arreglos de arreglos .................................. 17
3.2.2 Acceso a los arreglos ................................................................................ 17
3.3 Registros ..................................................................................................... 18
3.4 Memoria Virtual ........................................................................................... 19
3.4.1 Sizeof......................................................................................................... 19
3.4.2 malloc ........................................................................................................ 19
3.4.3 free ............................................................................................................ 20
4 Definición léxica ..................................................................................................... 21
4.1 Finalización de línea ................................................................................... 21
4.2 Espacios en blanco ..................................................................................... 21
4.3 Comentarios ................................................................................................ 21
4.4 Sensibilidad a mayúsculas y minúsculas .................................................... 22
4.5 Identificadores ............................................................................................. 22
4.6 Palabras reservadas ................................................................................... 22
4.7 Literales ...................................................................................................... 23
4.8 Secuencias de escape ................................................................................ 23
5 Estructura del Lenguaje ......................................................................................... 25
5.1 Nombre del programa ................................................................................. 26
5.2 Sentencia uses............................................................................................ 26
5.3 Declaración de variables ............................................................................. 26
5.4 Declaración de constantes .......................................................................... 27
5.5 Expresiones ................................................................................................ 28
5.5.1 Operaciones Aritméticas............................................................................ 28
5.5.2 Operadores relacionales............................................................................ 32
5.5.3 Operaciones lógicas .................................................................................. 32
5.6 Funciones y Procedimientos ....................................................................... 34
5.6.1 Funciones .................................................................................................. 34
5.6.2 Procedimientos .......................................................................................... 36
5.6.3 Paso de Parámetros .................................................................................. 36
5.6.4 Procedimientos y Funciones anidadas ...................................................... 39
5.6.5 Funciones Propias del lenguaje ................................................................. 39
2
6 Sentencias ............................................................................................................. 42
6.1 Bloques ....................................................................................................... 42
6.2 Sentencia With ............................................................................................ 43
6.3 Asignación de variables .............................................................................. 44
6.4 Sentencias de transferencia ........................................................................ 45
6.4.1 Break ......................................................................................................... 45
6.4.2 Continue .................................................................................................... 46
6.4.3 Exit ............................................................................................................ 47
6.5 Sentencias de selección ............................................................................. 47
6.5.1 Sentencia If................................................................................................ 47
6.5.2 Switch ........................................................................................................ 47
6.6 Ciclos .......................................................................................................... 49
6.6.1 While.......................................................................................................... 49
6.7 Sentencias de entrada/salida ...................................................................... 51
6.8 Sentencia Write ........................................................................................... 51
7 Generación de código intermedio .......................................................................... 53
7.1 Temporales ................................................................................................. 54
7.2 Etiquetas ..................................................................................................... 54
7.3 Identificadores ............................................................................................. 54
7.4 Comentarios ................................................................................................ 55
7.5 Operadores aritméticos ............................................................................... 55
7.6 Saltos .......................................................................................................... 56
7.6.1 Saltos condicionales .................................................................................. 56
7.6.2 Salto incondicional ..................................................................................... 57
7.7 Asignación a temporales ............................................................................. 57
7.8 Declaración de métodos ............................................................................. 58
7.9 Llamadas a métodos ................................................................................... 58
7.10 Print ............................................................................................................. 59
7.11 Entrada o lectura de dato ............................................................................ 59
7.12 Entorno de ejecución .................................................................................. 60
7.12.1 Estructuras del entorno de ejecución ..................................................... 60
3
7.12.2 Acceso a estructuras del entorno de ejecución ...................................... 62
8 Optimización de código intermedio ........................................................................ 63
8.1 Eliminación de instrucciones redundantes de carga y almacenamiento. .... 63
8.2 Eliminación de código inalcanzable ............................................................ 64
8.3 Simplificación algebraica y reducción por fuerza ........................................ 65
9 Generación de código ensamblador ...................................................................... 68
9.1 Entrada de ASM .......................................................................................... 68
9.2 Salida de ASM ............................................................................................ 68
9.3 Registros de la CPU.................................................................................... 68
9.3.1 Registros de uso general ........................................................................... 68
9.3.2 Registros de segmento .............................................................................. 69
9.3.3 Registros punteros .................................................................................... 69
9.3.4 Registros especiales ................................................................................. 69
9.3.5 Bits del registro de banderas ..................................................................... 69
9.4 Estructura stack assembler ......................................................................... 70
9.5 Instrucciones de transferencia de datos ...................................................... 71
9.5.1 MOV .......................................................................................................... 71
9.5.2 PUSH......................................................................................................... 71
9.5.3 POP ........................................................................................................... 72
9.5.4 XCHG ........................................................................................................ 72
9.5.5 XLAT.......................................................................................................... 72
9.5.6 LEA ............................................................................................................ 72
9.5.7 LDS ........................................................................................................... 73
9.5.8 LES ............................................................................................................ 73
9.5.9 LAHF ......................................................................................................... 73
9.5.10 SAHF...................................................................................................... 73
9.5.11 PUSHF ................................................................................................... 74
9.5.12 POPF ..................................................................................................... 74
9.6 Instrucciones aritméticas ............................................................................. 74
9.6.1 ADD ........................................................................................................... 74
9.6.2 ADC ........................................................................................................... 74
9.6.3 SUB ........................................................................................................... 75
4
9.6.4 SBB ........................................................................................................... 75
9.6.5 CMP........................................................................................................... 75
9.6.6 INC ............................................................................................................ 75
9.6.7 DEC ........................................................................................................... 76
9.6.8 NEG ........................................................................................................... 76
9.6.9 DAA ........................................................................................................... 76
9.6.10 DAS ........................................................................................................ 76
9.6.11 MUL ........................................................................................................ 77
9.6.12 IMUL ....................................................................................................... 77
9.6.13 CBW ....................................................................................................... 77
9.7 Instrucciones lógicas ................................................................................... 77
9.7.1 AND ........................................................................................................... 77
9.7.2 TEST dest,src ............................................................................................ 78
9.7.3 OR ............................................................................................................. 78
9.7.4 XOR ........................................................................................................... 78
9.7.5 NOT ........................................................................................................... 79
9.8 Instrucciones de desplazamiento ................................................................ 79
9.8.1 SHL/SAL .................................................................................................... 79
9.8.2 SHR ........................................................................................................... 80
9.8.3 SAR ........................................................................................................... 80
9.8.4 ROL ........................................................................................................... 81
9.8.5 ROR........................................................................................................... 81
9.8.6 RCL ........................................................................................................... 82
9.8.7 RCR ........................................................................................................... 82
9.9 Instrucciones de transferencia de control .................................................... 83
9.9.1 JMP etiqueta.............................................................................................. 83
9.9.2 CALL id ...................................................................................................... 83
9.9.3 RET ........................................................................................................... 83
9.10 Saltos condicionales aritméticos ................................................................. 83
9.10.1 Aritmética signada (con números positivos, negativos y cero) ............... 83
9.10.2 Aritmética sin signo (con números positivos y cero)............................... 84
9.11 Saltos condicionales según el valor de los indicadores: ............................. 84
5
9.12 Saltos condicionales CX ............................................................................. 84
9.13 Interrupciones: ............................................................................................ 84
9.14 Operadores analíticos ................................................................................. 85
9.14.1 SEG........................................................................................................ 85
9.14.2 OFFSET ................................................................................................. 85
9.14.3 TYPE ...................................................................................................... 86
9.14.4 Definición de procedimientos ................................................................. 86
9.14.5 Definición de macros .............................................................................. 87
9.15 Operadores de macros ............................................................................... 88
9.16 Instrucciones para el ensamblador (Directivas) .......................................... 88
9.16.1 Definición de símbolos ........................................................................... 88
9.16.2 Definición de datos ................................................................................. 88
9.16.3 Definición de segmentos ........................................................................ 89
9.16.4 Segmentos simplificados ........................................................................ 90
10 Manejo de errores ............................................................................................... 92
10.1 Tipos de errores .......................................................................................... 92
10.2 Contenido mínimo de tabla de errores ........................................................ 92
10.3 Método de recuperación ............................................................................. 92
11 Apéndice A: Precedencia y asociatividad de operadores .................................... 93
12 Entregables y Restricciones ................................................................................ 94
12.1 Entregables ................................................................................................. 94
12.2 Restricciones............................................................................................... 94
12.3 Consideraciones ......................................................................................... 94
12.4 Requisitos mínimos ..................................................................................... 95
12.5 Entrega del proyecto ................................................................................... 97
6
1 Objetivos
1.1 Objetivo general
Comprender la fase de síntesis durante el proceso de compilación mediante un
lenguaje de programación estructurado
.
2 Descripción
DOSLang es un lenguaje de programación procedural e imperativo. La característica
principal de este lenguaje es la capacidad de combinar código ensamblador con
DOSLang. Está característica existe ya que el código ensamblador se ejecuta mucho
más rápido. Es bien sabido que programar enteramente en ensamblador no suele ser
una buena idea, pero tener la posibilidad ayuda a ir experimentando con el lenguaje
ensamblador y a la vez poder aumentar la velocidad de ejecución de un programa si
fuera necesario.
2.1.1 DosLang
DOSLang es un lenguaje de programación estructurado, procedural e imperativo. Esto
significa que todos los programas deben tener una estructura y orden definido.
2.1.2 DosIDE
DosIDE es un entorno de desarrollo. Este provee las herramientas para la escritura de
programas en DosLang así como también las herramientas para solicitar la
transformación del código fuente a código intermedio.
7
2.1.3 Consola
Este componente permitirá observar el resultado de ejecución de las aplicaciones
desarrolladas en el IDE
2.1.4 Debugger
Este componente permitirá validar la ejecución del código intermedio, permitirá la
ejecución paso a paso, así como también permitirá visualizar el manejo de las estructuras
para el manejo de memoria como el Heap y Stack en tiempo de ejecución para poder
validar su correcta implementación.
2.1.5 Optimizador
Este componente permitirá optimizar el código intermedio generado, utilizando
optimización de mirilla. Al ejecutar esta versión de código podrá ser ejecutado o
transformado a código ensamblador produciendo la misma salida lógica de la aplicación.
8
2.1.6 Reportes
DOSIDE permite generar reportes sobre el proceso de compilación del archivo de
entrada. Estos reportes nos permiten tener una idea más detallada sobre el
funcionamiento de nuestro compilador ya que nos presenta los errores, la tabla de
símbolos utilizada y las optimizaciones que generamos.
9
2.1.6.2 Reporte de Tabla de Símbolos
Este reporte mostrará la tabla de símbolos después del proceso de compilación. Se
deberán demostrar todas las variables, funciones y procedimientos que fueron
declarados, así como su tipo y toda la información que el estudiante considere necesaria.
Se calificará la presentación del reporte
10
2.2 Flujo del Proyecto
A continuación, se describe el flujo general y especifico del proyecto, desde su petición
al cliente hasta la ejecución del código intermedio o la generación de código
ensamblador.
Para el desarrollo del entorno de desarrollo en línea se hará uso del lenguaje javascript
y para el procesamiento del lenguaje intermedio se hará uso de Nodejs y JISON. El
servidor se desarrollará utilizando java y se hará uso de Jlex y CUP para la
transformación del programa fuente a código de cuádruplos.
Nota: La comunicación entre el cliente y el servidor se hará a través de sockets.
11
2.2.2 Flujo específico de la aplicación
A continuación, se detalla el flujo principal de la aplicación a través de la cual el usuario
puede desarrollar sus aplicaciones
1. El programador crea su programa a través del entorno de desarrollo.
2. El programador solicita la compilación de su programa fuente.
3. La aplicación procesará el programa fuente y generará la representación en
código intermedio (cuádruplos) del programa fuente.
4. La aplicación proporcionará al programador el código intermedio generado o
notificará de posibles errores en el programa fuente
5. A partir del código intermedio el programador puede:
a. Ejecutar el código intermedio en el entorno de desarrollo en línea
b. Sintetizar el código intermedio en código ensamblador para
posteriormente evaluar su ejecución en un emulador
c. Debuggear el código intermedio para poder visualizar el manejo de
estructuras de memoria en tiempo de ejecución.
d. Optimizar el código intermedio utilizando el método de mirilla para luego
continuar con el flujo de síntesis (5)
12
3 Generalidades del lenguaje DOSLang
DOSLang es un lenguaje derivado de pascal, por lo tanto, está conformado por un
subconjunto de sus instrucciones que pretenden facilitar el aprendizaje
de programación a las personas, utilizando la programación estructurada y
estructuración de datos.
13
3.1.2 Tipos definidos por el usuario
Un tipo puede ser definid por un nombre, esto sirve para definir variaciones de un tipo.
La sintaxis de la declaración de un tipo es:
type
days, age = integer;
yes, true = boolean;
name, city = string;
fees, expenses = double;
14
type
SUMMER = (April, May, June, July, September);
COLORS = (Red, Green, Blue, Yellow, Magenta, Cyan, Black, White);
TRANSPORT = (Bus, Train, Airplane, Ship);
const
P = 18;
Q = 90;
type
Number = 1 ... 100;
Value = P ... Q;
Consideraciones:
• Únicamente aplica para tipos numéricos y caracteres
3.2 Arreglos
DOSLang proporciona una estructura de datos llamada arreglo que puede almacenar
una colección secuencial de tamaño fijo de elementos del mismo tipo.
En lugar de declarar variables individuales, como número1, número2, ... y número100,
declara una variable de matriz como números y usa números [1], números [2] y ...,
15
números [100] para representar variables individuales Se accede a un elemento
específico en una matriz mediante un índice.
Todas las matrices consisten en ubicaciones de memoria contiguas. La dirección más
baja corresponde al primer elemento y la dirección más alta al último elemento. Si se
desea una matriz de estilo C que comience desde el índice 0, solo necesita iniciar el
índice desde 0, en lugar de 1
Sintaxis
Ejemplo
type
temperature = array [-10 .. 50] of real;
var
day_temp, night_temp: temperature;
type
ch_array = array[char] of 1..26;
var
alphabet: ch_array;
c: char;
begin
...
for c:= 'A' to 'Z' do
alphabet[c] := ord[m];
(* the ord() function returns the ordinal values *)
16
3.2.1 Arreglos Multidimensionales y Arreglos de arreglos
var
a: array [0..3, 0..3] of integer;
i, j : integer;
{ Es equivalente a… }
var
a: array [0..3] of array [0..3] of integer;
i, j : integer;
begin
for i:= 0 to 3 do
for j:= 0 to 3 do
a[i,j]:= i * j;
...
end;
Sintaxis
<Variable> ::= id
| <Variable> '.' id
| <Variable> '^'
| <Variable> '[' <ExpressionList> ']'
Ejemplo
program exArrays;
var
n: array [1..10] of integer; (* n is an array of 10 integers *)
17
i, j: integer;
begin
(* initialize elements of array n to 0 *)
for i := 1 to 10 do
n[ i ] := i + 100; (* set element at location i to i + 100 *)
(* output each array element's value *)
for j:= 1 to 10 do
writeln('Element[', j, '] = ', n[j] );
end.
Consideraciones:
• Para un arreglo de n dimensiones, si se hace un acceso sobre una dimensión m
donde m<n, al acceso retornara un arreglo de n-m dimensiones.
3.3 Registros
La principal limitación de un array es que todos los datos que contiene deben ser del
mismo tipo. Pero a veces nos interesa agrupar datos de distinta naturaleza, como pueden
ser el nombre y la edad de una persona, que serían del tipo string e integer,
respectivamente. En ese caso, podemos emplear los records o registros, que se definen
indicando el nombre y el tipo de cada dato individual (cada campo), y se accede a estos
campos indicando el nombre de la variable y el nombre del campo, separados por un
punto:
program Record2;
var
dato: record
nombre: string;
edad: integer;
end;
begin
dato1 : dato = malloc(sizeof(dato));
with dato1 do
begin
nombre := “Ignacio”;
edad := 23;
write(“El nombre es “, nombre );
write(“ y la edad “, edad);
end;
end.
18
En este caso tenemos un nuevo bloque en el cuerpo del programa, delimitado por el
"begin" y el "end" situados más a la derecha, y equivale a decir "en toda esta parte del
programa me estoy refiriendo a la variable dato". Así, podemos nombrar los campos que
queremos modificar o escribir, sin necesidad de repetir a qué variable pertenecen.
3.4.1 Sizeof
Este método retornara un entero que indicara el tamaño de un registro. El tamaño de un
registro se calcula como la suma de cada uno de sus atributos. Si el registro tuviera como
atributos otro registro o un arreglo, también contaría como un espacio ya que únicamente
se almacenaría su apuntador.
Sintaxis
sizeof(registro : record)
Ejemplo
Estudiante: record
nombre: string;
edad: integer;
end;
----------------------------------------------------------------------------
Automovil: record
marca: string;
modelo: integer;
dueno: Estudiante;
3.4.2 malloc
Este método recibirá como parámetro un entero, reservará en el “heap” dicha cantidad
de memoria y retornará un puntero hacia la posicion que se reservó. Esta operación
deberá de realizarse cada vez que se quiera instanciar un registro, en caso de no
19
reservarse memoria, el registro apuntará a nil y si se intenta utilizar se producirá un error
en tiempo de ejecución.
Sintaxis
malloc(cantidad : int)
Ejemplo
Type
Direccion
calle: String;
avenida: String;
zona: Integer
end;
Estudiante
nombre : String;
edad : Integer;
direccion : Direccion;
end;
Var
est1, est2 : Estudiante;
begin;
3.4.3 free
Este método recibirá como parámetro una variable de tipo registro y limpiará la memoria
en la que se alojaba dicha variable. El apuntador que se limpió nuevamente apuntará a
nil y si se quiere volver a utilizar se deberá emplear la sentencia malloc nuevamente. Si
se intenta limpiar un registro que ya apunta a nil, deberá de reportarse un error en tiempo
de ejecución.
Sintaxis
free(variable : registro)
Ejemplo
20
est1 = malloc(sizeof(Estudiante)); (* Se reserve memoria para est1 *)
4 Definición léxica
4.1 Finalización de línea
El compilador de DOSLang dividirá la entrada en líneas, estas líneas estarán divididas
mediante componentes léxicos que determinen la finalización de las mismas y son los
siguientes:
● Carácter salto de línea (LF ASCII)
● Carácter retorno de carro (CR ASCII)
● Carácter retorno de carro (CR ASCII) seguido de carácter salto de línea (LF ASCII)
4.3 Comentarios
Un comentario está destinado a incrustar anotaciones legibles al programador en el
código fuente de un Programa
Existirán dos tipos de comentarios:
• Los comentarios de una línea que serán delimitados al inicio con el símbolo “(*” y
al final con el símbolo “*)”
• Los comentarios con múltiples líneas que empezarán con los símbolos “{” y
terminarán con los símbolos “}”.
21
}
4.5 Identificadores
Los identificadores son símbolos léxicos que nombran entidades. Estas entidades
pueden ser variables, métodos o módulos. Un identificador es una secuencia de
caracteres alfabéticos [A-Z a-z] incluyendo el guion bajo [_] o dígitos [0-9] que
comienzan con un carácter alfabético o guion bajo.
Identificador_valido_1
identificador1
sale_Compi
Ejemplo 2: identificadores validos
Fuente: Elaboración propia.
Valor.1
54var
Ejemplo 3: identificadores no válidos
Fuente: Elaboración propia.
22
and array begin case const
4.7 Literales
Representan el valor de un tipo primitivo
● Enteros: [0-9]+
● Real: [0-9]+(“.” [0-9]+)
● Caracter: “’” <Carácter ASCII> “’”
● Cadena/Word: “”” <Caracteres ASCII> “’”
○ Será el único literal que, si no se inicializa, su valor será nil.
● Booleanos: [true, false]
● Nulo: nil
○ Los literales de tipo char, int y real no podrán ser de tipo nil.
Secuencia Significado
de escape
\? Signo de interrogación
\\ Barra invertida
23
\0 Carácter nulo
\a Pitido
\b Retorno
\f Nueva página
\n Nueva línea
\r Retorno de carro
\t Tabulación horizontal
\v Tabulación vertical
24
5 Estructura del Lenguaje
25
5.1 Nombre del programa
Cada programa debe ser nombrado, y deben ser único dentro de un mismo directorio de
ejecución.
Program <Identificador>;
Consideraciones:
• Debe existir el programa, de lo contrario lanzar una excepción.
• Si existieran elementos repetidos, debe lanzar una excepción.
26
var
age, weekdays : integer = 0;
choice, isready: boolean;
initials, grade: char;
name, surname : string;
Consideraciones:
● No puede declararse una variable con el mismo identificador de una variable
existente en el ámbito actual, de suceder debe reportarse un error.
● La inicialización es opcional y el tipo de la expresión debe ser el mismo que el
declarado, de lo contrario debe reportarse un error.
● Si existe un valor de inicialización este es el mismo para todas las variables en la
lista
● No pueden definirse nombre de variables con el mismo nombre que una función
o procedimiento
const
PI : real = 3.1416;
Consideraciones:
● No puede declararse más de una constante con el mismo identificador.
27
● La inicialización es requerida y el tipo de la expresión debe ser el mismo que el
declarado, de lo contrario debe reportarse un error.
● La expresión de valor inicial afecta a todas las constantes en la lista
● No pueden definirse nombre de constantes con el mismo nombre que una función
o procedimiento
5.5 Expresiones
DOSLang tendrá soporte a diferentes operaciones, todas estas serán descritas en
conjunto como operaciones, las expresiones son:
5.5.1.1Suma
Consiste en la adición de dos o más elementos para llegar a un resultado final donde
todo se incluye. El símbolo de la suma es el símbolo más (+) y se intercala entre los
elementos que se quiere sumar
5.5.1.2Resta
La resta es una operación aritmética básica a través de la cual se le disminuye al
minuendo la cantidad indicada en el sustraendo. El símbolo de la resta es el símbolo
menos (-) y se intercala entre los elementos que se quiere restar.
Consideraciones:
● Cualquier otra combinación que no esté listada en la tabla deberá reportarse como
un error semántico.
5.5.1.3Multiplicación
Consiste en calcular el resultado (producto) de sumar un mismo número (multiplicando)
tantas veces como indica otro número (multiplicador). La multiplicación se representa por
el símbolo (*) y se intercala entre los elementos que se quiere multiplicar.
29
Operandos Tipo Ejemplos
resultante
int * real 10.25 * 12.3 = 1550.72
real * int 20.1 * 5 = 80.4
real * char real 2.5 * ‘b’ = 240.0
char * real 3.5 * 8.5 = 29.75
real * real
5.5.1.4 Potencia
La potenciación es una operación matemática entre dos términos denominados: base y
exponente. Se escribe y se lee normalmente como «a elevado a la n» . La potencia se
representa por el símbolo (^).
5.5.1.5 Modulo
Operación aritmética que retorna como resultado el residuo de una división. El módulo
se representa por el símbolo (%) y se intercala entre los elementos entre los que se
quiera obtener el módulo.
30
Operandos Tipo resultante Ejemplos
int % real 16 % 3.5 = 2.0
real % int ‘a’ % 94.5 = 2.5
real % char real 10.5 % 3.4 = 0.3
char % real
real % real
int % char 10 % 3 = 1
char % int int ‘b’ % 100 = 98
int % int
char % char
Consideraciones:
● Cualquier otra combinación que no esté listada en la tabla deberá reportarse como
un error semántico.
5.5.1.6 División
La división es una operación matemática o aritmética que consiste en averiguar cuántas
veces un número (el divisor) está contenido en otro número (el dividendo). La división se
representa con el símbolo (/) y se intercala entre los elementos entre los que se quiera
obtener el resultado.
int / char 3 / 2 = 1
int
char / int ‘a’ / 8 = 12
(se descartan los
int / int
decimales)
char / char
Consideraciones:
● Cualquier otra combinación que no esté listada en la tabla deberá reportarse como
un error semántico.
● Si el divisor es 0, se tendrá que reportar un error en tiempo de ejecución, es decir,
no cuando se esté generando el formato de código intermedio.
31
5.5.2 Operadores relacionales
Una operación relacional es una operación que compara la igualdad, diferencia o
comportamiento entre dos valores. Este tipo de comparaciones siempre devuelve un
valor lógico según el resultado de la comparación (true | false). Una operación relacional
siempre tiene dos operandos y un único operador.
int [=,<>]real
real [=,<>] int
real [=,<>] char
char [=,<>]real
50 = 50.0 = true
int [=,<>] char
5.5 <> 30 = true
char [=,<>] int
‘a’ = ‘a’ = true
real [=,<>]real
=,<> 1.2 <> 0.2 = false
int [=,<>] int
“123A” = “123a” = false
char [=,<>] char
true = true = true
String [=,<>] String
true <> true = false
String [=,<>] word
word [=,<>] String
word [=,<>] word
boolean [=,<>] boolean
Consideraciones:
● Cualquier otra combinación que no esté listada en la tabla deberá reportarse como
un error semántico.
AND
Multiplicación lógica o conjunción
Operando A Operando B AAND B
FALSE FALSE FALSE
FALSE TRUE FALSE
TRUE FALSE FALSE
TRUE TRUE TRUE
OR
Suma lógica o disyunción
Operando A Operando B A OR B
FALSE FALSE FALSE
FALSE TRUE TRUE
TRUE FALSE TRUE
TRUE TRUE TRUE
NAND
Compuerta Not And
Operando A Operando B A NAND B
FALSE FALSE TRUE
FALSE TRUE TRUE
TRUE FALSE TRUE
TRUE TRUE FALSE
NOR
Compuerta Not Or
Operando A Operando B A NOR B
FALSE FALSE TRUE
FALSE TRUE FALSE
TRUE FALSE FALSE
TRUE TRUE FALSE
NOT
Negación
Operando A NOT A
FALSE TRUE
TRUE FALSE
Consideraciones:
● Ambos operadores deberán ser de tipo booleano.
33
5.6 Funciones y Procedimientos
En DOSLang es una función es un subprograma que retorna siempre un valor, mientras
que un procedimiento es un subprograma que realiza un conjunto de acciones sin ningún
retorno.
5.6.1 Funciones
Una función es un grupo de declaraciones que juntas realizan una tarea. Cada programa
tiene al menos una función, que es el programa en sí, y todos los programas más triviales
pueden definir funciones adicionales. Una declaración de una función le dice al
compilador sobre el nombre, el tipo de retorno y los parámetros de una función. Una
definición de función proporciona el cuerpo real de la función.
En DOSLang, una función se define usando la palabra clave “function”. La forma general
de una definición de función es la siguiente
Sintaxis
Ejemplo
program recursiveFibonacci;
var
i: integer;
34
begin
if n=1 then
fibonacci := 0;
else
fibonacci := fibonacci(n-1) + fibonacci(n-2);
end;
begin
for i:= 1 to 10 do
Consideraciones
• Si el tipo de retorno y el valor retornado no coinciden, se deberá de reportar un
error.
• Los parámetros pueden ser de cualquier tipo.
• Las funciones soportan todo tipo de llamadas recursivas
• Las funciones soportan sobrecarga de parámetros
• Si la función no define no define ningún argumento los paréntesis no son
requeridos
5.6.1.1Return
En DosLang no existe una palabra reservada para la sentencia return para la devolución
de resultados en una función. Para identificar el valor de retorno de una función se hace
una asignación a una variable predefinida con el mismo nombre de la función
35
Consideraciones:
• Debe verificarse que el valor de la expresión sea del mismo tipo del que fue
declarado en dicha función.
• No puede declarase una variable local del mismo nombre que la función
5.6.2 Procedimientos
En DOSLang, un procedimiento se define utilizando la palabra clave de procedure. La
forma general de una definición de procedimiento es la siguiente:
Sintaxis
Ejemplo
begin
if x < y then
m := x
else
m := y;
if z <m then
m := z;
end; { end of procedure findMin }
Consideraciones
• Los parámetros pueden ser de cualquier tipo.
36
5.6.3.1Paso Por Valor
Este método copia el valor real de un argumento en el parámetro formal del subprograma.
En este caso, los cambios realizados en el parámetro dentro del subprograma no tienen
efecto en el argumento.
Por defecto, DOSLang utiliza el método de llamada por valor para pasar argumentos. En
general, esto significa que el código dentro de un subprograma no puede alterar los
argumentos utilizados para llamar al subprograma.
program exCallbyValue;
var
a, b : integer;
(*procedure definition *)
procedure swap(x, y: integer);
var
temp: integer;
begin
temp := x;
x:= y;
y := temp;
end;
begin
a := 100;
b := 200;
writeln('Before swap, value of a : ', a );
writeln('Before swap, value of b : ', b );
{*
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :100
After swap, value of b :200
*}
37
5.6.3.2 Paso Por Referencia
Este método copia la dirección de un argumento en el parámetro formal. Dentro del
subprograma, la dirección se utiliza para acceder al argumento real utilizado en la
llamada. Esto significa que los cambios realizados en el parámetro afectan el argumento.
Para pasar los argumentos por referencia, DOSLang permite definir parámetros
variables. Esto se hace precediendo los parámetros formales por la palabra clave var.
program exCallbyRef;
var
a, b : integer;
(*procedure definition *)
procedure swap(var x, y: integer);
var
temp: integer;
begin
temp := x;
x:= y;
y := temp;
end;
begin
a := 100;
b := 200;
writeln('Before swap, value of a : ', a );
writeln('Before swap, value of b : ', b );
{*
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100
*}
38
5.6.4 Procedimientos y Funciones anidadas
Una función anidada (o procedimiento) que se encuentra definida dentro de otra función.
Las funciones contenidas dentro de otra función no son visibles desde afuera de la
función contenedora. Pueden definirse cualquier nivel de funciones anidada
Las funciones (y procedimientos) anidados tienen acceso a las variables locales
definidas en la función que los contiene.
Ejemplo de función anidada
BEGIN {CallingProcedure }
CallBack;
NestedCallBack;
END;
Sintaxis
Ejemplo
5.6.5.2 Length
Recibe como parámetro una cadena y devuelve un entero con la longitud de la cadena.
Sintaxis
length(cadena : string)
Ejemplo
5.6.5.3 Replace
Recibe como parámetro dos cadenas. La primera indica la cadena que se quiere
modificar y la segunda indica que caracteres se quieren remplazar. Devuelve otra cadena
removiendo lo indicado en el segundo parámetro
Sintaxis
Ejemplo
5.6.5.4 ToCharArray
Recibe como parámetro una cadena y devuelve un vector de tipo char con cada una de
las letras de la cadena.
Sintaxis
40
toCharArray(cadena: string)
Ejemplo
5.6.5.5 ToLowerCase
Recibe como parámetro una cadena y devuelve una segunda cadena que contiene la
palabra indicada en el parámetro con todas sus letras minúsculas.
Sintaxis
toLowerCase(cadena: string)
Ejemplo
5.6.5.6 ToUpperCase
Recibe como parámetro una cadena y devuelve una segunda cadena que contiene la
palabra indicada en el parámetro con todas sus letras mayúsculas.
Sintaxis
toUpperCase(cadena: string)
Ejemplo
5.6.5.7 Equals
Recibe como parámetro dos cadenas y devuelve un booleano que indica si las cadenas
son iguales o no
Sintaxis
Ejemplo
41
5.6.5.8 Trunk
Recibe como parámetro un valor con punto flotante (real) y devuelve un entero sin los
valores decimales.
Sintaxis
trunk(val : real)
Ejemplo
5.6.5.9 Round
Recibe como parámetro un valor con punto flotante (real) y devuelve un entero
redondeando el valor decimal según las siguientes reglas:
• Si el decimal es mayor o igual que 0.5, se aproxima al número superior
• Si el decimal es menor que 0.5, se aproxima al número inferior
Sintaxis
round(val : real)
Ejemplo
6 Sentencias
Son los elementos básicos en los que se divide el código en un lenguaje de
programación. En DOSLang el signo que las separa es el punto y coma.
6.1 Bloques
Un bloque es un conjunto de sentencias que será delimitado por las palabras begin (o el
nombre de la sentencia) y end
Consideraciones
● Si un bloque contiene únicamente una sentencia pueden omitirse las palabras
reservadas begin y end.
42
● La palabra reservada “end.” (con punto al final) es exclusivo para el bloque
principal
● La palabra reservada “end;” (con punto y coma al final) sirva para delimitar un
bloque de otro totalmente independiente.
● La palabra reservada “end” (sin ningún símbolo de puntuación) sirve para
delimitar un subloque de una sentencia compuesta. Por ejemplo, el bloque de un
IF que contiene sentencias Else.
Program withexample;
Type
Estudiante = Record
Edad : integer;
Nombre: Word;
End;
Var estudiante1, estudiante2 : Estudiante;
43
Begin
(* Ejemplo de asignación y lectura sin With *)
estudiante1.nombre := “Rainman”;
estudiante1.edad := 26;
Writeln(estudiante1.nombre, “ ”, estudiante1.edad);
End.
> Rainman 26
> Luis 23
> Luis 23
Consideraciones
• Si existe una propiedad del registro y una variable (local o global) con el mismo
nombre, la propiedad del registro tiene mayor precedencia.
44
<AssignmentStatement> ::= <Variable> ':=' <Expression> ';'
<Variable> ::= id
| <Variable> '.' id
| <Variable> '(' <ExpressionList> ‘)’
| <Variable> '[' <ExpressionList> ']'
Sintaxis 5: asignación de variables
Fuente: Elaboración propia.
Nombre := “Luis”;
Cantidad := getCantidad();
Consideraciones:
● Si se intenta asignar un valor a una variable que no ha sido definida se debería de
reportar el error.
● Se debe verificar que el tipo que se está asignado sea el mismo con el que fue
definida la variable
6.4.1 Break
La sentencia break sirve para terminar la ejecución de un ciclo.
<break_def> := break ;
45
END;
Writeln(cuenta);
END;
> 1
> 2
6.4.2 Continue
La sentencia continue se utilizará para transferir el control al principio del ciclo, es decir,
continuar con la siguiente iteración.
6.4.3 Exit
La sentencia exit termina la ejecución del programa o subprograma actual y retorna
la ejecución al bloque que hizo la llamada. Si la palabra reservada exit se encuentra
en el programa principal el programa termina su ejecución.
Consideraciones:
• Solo aplica para el bloque principal y para el bloque principal de funciones y
procedures.
Sintaxis 8: sentencia if
Fuente: Elaboración propia.
else
47
<CaseStatement> ::= CASE <Expression> OF <CaseList> [DEFAULT <statement>]?
END
Ejemplo
program checkCase;
var
grade: char;
begin
grade := 'A';
case (grade) of
'A' : writeln(“Excellent!” );
end;
end.
6.6 Ciclos
6.6.1 While
La sentencia cíclica mientras se utilizará para crear repeticiones de sentencias en el flujo
del programa.
El bloque de sentencias se ejecutará mientras la condición sea verdadera (0 𝑎 𝑛 𝑣𝑒𝑐𝑒𝑠),
de lo contrario el programa continuará con su flujo de ejecución normal.
program whileLoop;
var
a: integer;
begin
a := 10;
while a < 20 do
begin
writeln(“value of a: “, a);
a := a + 1;
end;
end.
49
El bloque de sentencias se ejecutará una vez y se seguirá ejecutando mientras la
condición sea verdadera (1 𝑎 𝑛 𝑣𝑒𝑐𝑒𝑠), de lo contrario el programa continuará con su flujo
de ejecución normal.
program repeatUntilLoop;
var
a: integer;
begin
a := 10;
(* repeat until loop execution *)
repeat
writeln(“value of a: “, a);
a := a + 1
until a = 20;
end.
Consideraciones:
• Este bloque no hace uso de las palabras reservadas begin y end
6.6.1.2 For
La sentencia cíclica para permitirá inicializar o establecer una variable como variable de
control, el ciclo tendrá una condición que se verificará en cada iteración, luego se deberá
definir una operación que actualice la variable de control cada vez que se ejecuta un ciclo
para luego verificar si la condición se cumple.
50
Sintaxis 12: sentencia for
Fuente: Elaboración propia.
program forLoop;
var
a: integer;
begin
for a := 10 to 20 do
begin
writeln(“value of a: “, a);
end;
end.
Consideraciones:
• La variable de control se auto-incremente en uno al alcanzar el final del ciclo antes
de la siguiente iteración
write(“Hola ”);
writeln(“mundo”); //Agrega un salto de linea
write(69);
51
(*contatenación*)
Write(“hola”, “ “, “mundo”);
Consideraciones:
• Si se utiliza la sentencia writeln se incluirá un salto de línea al final, de lo
contrario, si es una sentencia write no se incluirá un salto de línea al final
• Si existe más de un valor de expresión debe concatenar los valores
• Debe imprimirse la representación a String del valor que se esté pasando.
• En caso de que la expresión sea nil, deberá imprimirse la palabra nil.
<read_console_statement> ::=
“read” “(” id “)”
int Id_1;
String Id_2;
char Id_3;
boolean Id_4;
double Id_5;
read (Id_1);
read (Id_2);
read (Id_3);
read (Id_4);
read (Id_5);
52
Ejemplo 16: sentencia read
Sintaxis
Operador, argumento_1, argumento_2, resultado
Consideraciones
• Cada campo debe estar delimitado por comas
• El campo operador como el del resultado no pueden venir vacíos.
53
• El campo de argumento 1 y 2 pueden venir vacíos dependiendo de la operación
que se realizará.
Ejemplo
+, 0, 5, t1
*, t1, t2, t3
=, 5, , t1
7.1 Temporales
Los temporales serán creados por el compilador en el proceso de generación de código
intermedio. Estos serán instanciados en el primer encuentro del interprete y deberán
empezar con la letra “t” seguida de un número.
t[0-9]+
7.2 Etiquetas
Etiquetas Las etiquetas serán creadas por el compilador en el proceso de generación de
código intermedio. Las etiquetas deberán empezar con la letra “L” seguida de un número.
L[0-9]+
7.3 Identificadores
Un identificador será utilizado para dar un nombre a variables, métodos o estructuras.
54
Un identificador es una secuencia de caracteres alfabéticos [A-Z a-z] incluyendo el guion
bajo [_] o dígitos [0-9] que comienzan con un carácter alfabético o guion bajo.
Ejemplos
este_es_un_identificador_valido_09
_este_tambien_09
Y_este_2018
7.4 Comentarios
Un comentario es un componente léxico del lenguaje que no es tomado en cuenta para
el análisis sintáctico de la entrada.
Existirán dos tipos de comentarios:
• Los comentarios de una línea que serán delimitados al inicio con los símbolos “//”
y al final con un carácter de finalización de línea
• Los comentarios con múltiples líneas que empezarán con los símbolos “/*” y
terminarán con los símbolos “*/”.
Ejemplo
//este es un ejemplo de un lenguaje de una sola línea
/*
este es un ejemplo de un lenguaje de múltiples líneas.
*/
55
7.6 Saltos
Para definir el flujo que seguirá el intérprete se contará con bloques de código, estos
bloques están definidos por etiquetas y saltos, los saltos son aquellos que, definiéndole
una etiqueta y una posible condición, el flujo del código se desplaza hasta el bloque
contenido en luego de dicha etiqueta.
Cuádruplos contará con 2 tipos de saltos, los cuales son:
• Salto condicional: Contará con una condición para decidir si se realiza el salto o
no.
• Salto incondicional: Se realizará el salto siempre.
Ejemplo:
L1:
T1 = 5 * 2;
Jmp L2: // salto incondicional a L2
T2 = 5 + 1; // debido al salto esta instrucción no se ejecuta
L2: // luego de Jmp L2, el flujo continuo desde esta etiqueta
56
Ejemplo
L1:
*, t1, t2, t3
=, 5, , t1
jl, t1, t2, L2 // si T1 < T2 salta a L2
*, t1, t2, t3 // si no se cumple, continua el flujo
=, 5, , t1
L2: // si cumple, el flujo salta a esta etiqueta
Ejemplo
L1:
*, t1, t2, t3
Jmp, , , L2 // Salto a etiqueta L2
+, t1, 5, t3
L2: // El flujo continuo aquí
57
=, valor, , temporal
Ejemplo
=, 5, , t1 // Equivalente t1 = 5
+, 0, 5, t3
=, t3, , t1 // Equivalente t1 = t3
Sintaxis
Begin, , , idMetodo
// Serie de instrucciones cuádruplos
End, , idMetodo
Ejemplo
begin, , , metodo1
+, 0, 5, t1
*, t1, t2, t3
=, 5, , t1
end, , metodo1
58
Ejemplo
begin, , , metodo1
+, 0, 5, t1
=, 5, , t1
end, , metodo1
call, , , metodo1
7.10 Print
Esta instrucción será una función nativa de cuádruplos, su función principal es imprimir
en consola un valor definido según el formato del parámetro que se le asigne, la sintaxis
y parámetros permitidos son los siguientes:
Sintaxis
print( parámetro, valor );
Parámetro Acción
%c Imprime el valor carácter del identificador,
se basa según el código ascii.
%e Imprime únicamente el valor entero del
valor.
%d Imprime con punto decimal el valor.
Ejemplo
Print(%c, 65); >A
Print(%e, 65.4); > 65
Print(%d, 65.4); > 65.4
59
Sintaxis
call, , , $_in_value
Cada llamada a método o función que se realiza en el código de alto nivel cuenta con un
espacio propio en memoria para comunicarse con otros métodos y administrar sus
variables locales. Esto se logra modificando el puntero del Stack, que en el proyecto se
identifica con la letra P, para ir moviendo el puntero de un ámbito a otro, cuidando de no
corromper ámbitos ajenos al que se está ejecutando. A continuación, se ilustra su
funcionamiento con un ejemplo.
El puntero se identifica con la letra “P” y este contendrá la dirección de memoria donde
comenzará el ámbito actual, su asignación se realizará exactamente igual que a como
los terminales.
Ejemplos
=, t1, , P // Equivalente a asignar P = t1
=, P, , t1 // Equivalente a asignar t1 = P
+, P, 5, P // Equivalente a asignar P = P + 5
Como se mencionó anteriormente con el puntero del stack se debe manejar el concepto
de ámbitos en cuádruplos, por lo cual la simulación de cambio de ámbito se debe realizar
por medio de operaciones sobre este puntero.
Ejemplo
+, P, 5, P
Call, , , metodo1
-, P, 5, P
61
7.12.1.2 El Heap y su puntero
El Heap (o en español, montículo) es la estructura de control del entorno de ejecución
encargada de guardar las referencias a variables globales o valores de cadenas y
arreglos.
Ejemplos
+, H, 1, H // Equivalente a asignar H = H + 1
=, H, , t1 // Equivalente a t1 = H
Sintaxis de asignación
= , dirección, valor, estructura
Ejemplo
=, t1, 5, Stack // Equivalente a asignar 5 en la dirección t1 al Stack (Stack[t1] = 5)
=, H, 5, Heap // Equivalente a asignar 5 en la dirección del puntero H al Heap
(Stack[t1] = 5)
Sintaxis de obtención
62
= , estructura, dirección, campo de memoria a guardar
Ejemplo
= , Stack, t1, t2 // Equivalente a asignar en t2 la posición t1 del Stack ( t2 = Stack[t1] )
= , Heap, t1, t2 // Equivalente a asignar en t2 la posición t1 del Heap ( t2 = Heap[t1] )
Ejemplo Optimización
=,t2, , b
=,t2, ,b
= b, , t2
63
8.2 Eliminación de código inalcanzable
Consistirá en eliminar las instrucciones que nunca serán utilizadas. Por ejemplo,
instrucciones que estén luego de un salto incondicional, el cual direcciona el flujo de
ejecución a otra parte y nunca llegue a ejecutar las instrucciones posteriores al salto
incondicional. Las reglas aplicables son las siguientes:
Regla 2
Si existe un salto condicional de la forma Lx y exista una etiqueta Lx:, todo código
contenido entre el goto Lx y la etiqueta Lx, podrá ser eliminado siempre y cuando no
exista una etiqueta en dicho código.
Ejemplo Optimización
jmp L1
Jmp L1
<instrucciones>
L1:
L1:
Regla 3
Si existe un alto condicional inmediatamente después de sus etiquetas Lv:
<instrucciones> Lf: se podrá reducir el número de saltos negando la condición,
cambiando el salto condicional hacia la etiqueta falsa Lf: y eliminando el salto condicional
innecesario a goto Lf y quitando la etiqueta Lv:.
Ejemplo Optimización
Regla 4
Si se utilizan valores constantes dentro de las condiciones y el resultado de la condición
es una constante verdadera, se podrá transformar en un salto incondicional y eliminarse
el salto hacia la etiqueta falsa Lf.
Ejemplo Optimización
64
Je, 1, 1, L1
jmp L1;
jmp L2;
Regla 5
Si se utilizan valores constantes dentro de las condiciones y el resultado de la condición
es una constante falsa, se podrá transformar en un salto incondicional y eliminarse el
salto hacia la etiqueta verdadera Lv.
Ejemplo Optimización
Je, 1, 0, L1
jmp L2;
jmp L2;
Regla 6
Eliminación de las instrucciones que tenga la siguiente forma:
Ejemplo Optimización
+, x, 0, x
Regla 7
Eliminación de las instrucciones que tenga la siguiente forma:
Tabla 3: regla 9 de optimización
Fuente: Elaboración propia.
Ejemplo Optimización
-, x, 0, x
Regla 8
Eliminación de las instrucciones que tenga la siguiente forma:
Tabla 4: regla 10 de optimización
Fuente: Elaboración propia.
65
Ejemplo Optimización
*, x, 1, x
Regla 9
Eliminación de las instrucciones que tenga la siguiente forma:
Ejemplo Optimización
/, x, 1, x
Para las reglas 12, 13, 14, 15 es aplicable la eliminación de instrucciones con
operaciones de variable distinta a la variable de asignación y una constante, sin
modificación de la variable involucrada en la operación, por lo que la operación se
descartará y se convertirá en una asignación.
Regla 10
Ejemplo Optimización
+, y, 0, x =, y, , x
Regla 11
Ejemplo Optimización
-, y, 0, x =, y, , x
Regla 12
Ejemplo Optimización
*, y, 1, x =, y, , x
Regla 13
Ejemplo Optimización
/, y, 1, x =, y, , x
66
Se deberá realizar la eliminación de reducción por fuerza para sustituir por operaciones
de alto costo por expresiones equivalentes de menor costo.
Regla 14
Ejemplo Optimización
*, y, 2, x +, y, y, x
Regla 15
Ejemplo Optimización
*, 0, y, x =, 0, , x
Regla 16
.
Ejemplo Optimización
/, 0, y, x =, 0, , x
67
9 Generación de código ensamblador
La herramienta DOSLang contendrá un módulo externo que será una aplicación que
tendrá como tarea la traducción del código cuádruplos a código ensamblador.
Como el lenguaje ensamblador es un lenguaje de bajo nivel, se podrá evaluar el código
intermedio por medio de un emulador y garantizar que la salida de cuádruplos es
correcta.
DOSLang
68
• AX, Registro Acumulador: Conformado por 2 registros internos (AL:AH), los
cuales tambien se podrán utilizar pero son de menor tamaño (8 bits c/u).
• BX, Registro base Conformado por 2 registros internos (BL:BH), los cuales
tambien se podrán utilizar, pero son de menor tamaño (8 bits c/u).
• CX, Registro contador Conformado por 2 registros internos (CL:CH), los cuales
tambien se podrán utilizar, pero son de menor tamaño (8 bits c/u).
• DX, Registro de datos Conformado por 2 registros internos (DL:DH), los cuales
tambien se podrán utilizar, pero son de menor tamaño (8 bits c/u).
69
Estado que
Bit de apagado Bit de encendido
representa
OverFlow
NV OV
(Desbordamiento)
DN UP
Direction
(Hacia atrás) (Hacia adelante)
Interrupts DI EI
PL NG
Sign
(Positivo, no signo) (Negativo, con signo)
Zero NZ ZR
Auxilary carry NA AC
PO PE
Parity
(Impar) (Paridad par)
Carry NC CY
70
9.5 Instrucciones de transferencia de datos
En assembler se le llama transferencia de datos a la asignación de datos a una dirección
de memoria, ya sea una posición definida de una estructura o un registro de uso común,
esta transferencia de datos no afecta ni se puede aplicar a registros de banderas. Las
trasferencias de datos que proporciona assembler son las siguientes.
9.5.1 MOV
Es la transferencia de datos básica donde copia el valor del operando fuente (src) a la
dirección de memoria o registro destino (dest).
Sintaxis
MOV src , dest
Aplicaciones
• MOV reg, {reg | mem | inmed}
• MOV mem,{reg | inmed}
• MOV {reg16 | mem16},{CS | DS | ES | SS}
• MOV {DS | ES | SS},{reg16 |mem16}
Consideraciones
• No se puede transferir de una posición de memoria a otra posición de memoria,
si fuente es una posición de memoria el destino deberá ser un registro.
• Se recomienda transferir datos de un registro a otro únicamente si estos tienen la
misma cantidad de memoria asignada, (16 bits con 16bits, 8 bits con 8 bits, etc.).
9.5.2 PUSH
Esta es una transferencia de datos que involucra la estructura stack de assembler, esta
instrucción recibe un valor o dirección fuente (src) de 16 bits y lo coloca en el tope del
stack.
Sintaxis
Push src
Aplicaciones
Push {reg16 | mem16 | CS | DS | ES | SS}
71
9.5.3 POP
Esta es una transferencia de datos que involucra la estructura stack de assembler, en
esta instrucción se retira y se obtiene el valor de 16 bits que contiene el tope del stack y
lo coloca en una dirección destino definida (dest).
Sintaxis
Pop dest
Aplicaciones
Pop {reg16 | mem16 | DS | ES | SS}
9.5.4 XCHG
Es una transferencia de datos doble, donde se intercambia el registro fuente con el
destino y el registro destino con el de fuente, siendo realmente un intercambio de valores.
Sintaxis
XCHG src, dest
Aplicaciones
XCHG reg, {reg | mem}
9.5.5 XLAT
Realiza una transferencia de datos de una tabla específica, donde recibe la referencia
de la tabla y hace la transferencia a AL la posición AL de la tabla.
Sintaxis
XLAT tabla // Equivalencia a mov AL, [tabla + AL]
9.5.6 LEA
Realiza una transferencia de datos donde recibiendo un destino (dest), se le coloca la
dirección del dato fuente(src), siendo esta dirección relativa al segmento de datos.
72
Sintaxis
LEA dest, src // reg contiene el puntero de src
9.5.7 LDS
Realiza una doble transferencia de datos, donde la primera es recibiendo un destino
(dest), se le coloca la dirección del dato fuente(src), siendo esta dirección relativa al
segmento de datos y la segunda es que se coloca el valor del dato fuente en el registro
DS.
Sintaxis
LDS dest, src // reg contiene el puntero de src
// DS contiene el valor de src
9.5.8 LES
Realiza una doble transferencia de datos, donde la primera es recibiendo un destino
(dest), se le coloca la dirección del dato fuente(src), siendo esta dirección relativa al
segmento de datos y la segunda es que se coloca el valor del dato fuente en el registro
ES.
Sintaxis
LES dest, src // reg contiene el puntero de src
// ES contiene el valor de src
9.5.9 LAHF
Realiza una transferencia de datos donde copia los últimos 8 bits del segmento, los
cuales son las banderas, al registro AH, el orden de las banderas serían las siguientes:
SF, ZF, ?, AF, ?, PF, ?, CF, siendo los signos de interrogación bits indefinidos
Sintaxis
LAHF // AH tiene los bits SF, ZF, ?, AF, ?, PF, ?, CF
9.5.10 SAHF
Realiza una transferencia de datos donde copia los últimos 8 bits del registro AH a los
últimos 8 bits del segmento, siendo estas las banderas.
73
Sintaxis
SAHF // SF:ZF:?:AF:?:PF:?:CF <- AH
9.5.11 PUSHF
Primero decrementa en 2 el puntero del stack y almacena los bits de las banderas en el
Stack de assembler, esperando ser recuperados por POPF
Sintaxis
PUSHF // SP <- SP - 2, [SP+1:SP] <- Flags.
9.5.12 POPF
Primero recupera los bits de las banderas en el Stack de assembler, almacenados por
PUSHF e incrementa en 2 el puntero del stack
Sintaxis
POPF // Flags <- [SP+1:SP], SP <- SP + 2
9.6.1 ADD
Realiza una operación de suma entre el operador destino(dest) y fuente(src), dejando el
valor resultante en el registro del destino.
Sintaxis
ADD dest, src
9.6.2 ADC
Realiza una operación de suma entre el operador destino(dest) y fuente(src), dejando el
valor resultante en el registro del destino, esta operación además suma la bandera CF,
la cual se encuentra activa (1) si existe acarreo, e inactiva (0) si no existe.
Sintaxis
74
ADC dest, src // Equivalente dest = dest + src + CF
9.6.3 SUB
Realiza una operación de resta entre el operador destino(dest) y fuente(src), dejando el
valor resultante en el registro del destino.
Sintaxis
SUB dest, src
9.6.4 SBB
Realiza una operación de resta entre el operador destino(dest) y fuente(src), dejando el
valor resultante en el registro del destino, esta operación además resta la bandera CF,
la cual se encuentra activa (1) si existe acarreo, e inactiva (0) si no existe.
Sintaxis
SBB dest, src // Equivalente dest = dest - src - CF
9.6.5 CMP
Realiza una operación de resta entre el operador destino(dest) y fuente(src), esta
instrucción, a diferencia de las restas anteriores, no guarda el valor en ningún registro y
únicamente sirve para alterar el estado de las banderas.
Sintaxis
CMP dest, src // Equivalente dest – src, alterando banderas AF, CF, OF, PF, SF, ZF
9.6.6 INC
Realiza una operación de suma entre el operador destino(dest) y un 1, dejando el valor
resultante en el registro del destino, siendo realmente un incremento del operador
destino, además no afecta la bandera CF.
Sintaxis
INC dest // Equivalente a dest = dest + 1
75
9.6.7 DEC
Realiza una operación de resta entre el operador destino(dest) y un 1, dejando el valor
resultante en el registro del destino, siendo realmente un decremento del operador
destino, además no afecta la bandera CF.
Sintaxis
DEC dest // Equivalente a dest = dest -1
9.6.8 NEG
Esta instrucción genera el complemento a 2 del registro y lo almacena en el mismo
operador destino.
Sintaxis
NEG dest // donde dest tiene que ser registro o memoria
9.6.9 DAA
Corrige el resultado de una suma de dos valores entre los registros de tipo BCD (decimal
codificado en binario (BCD)) empaquetados en el registro AL, esta instrucción debe estar
inmediatamente después de una instrucción ADD o ADC, alterando OF donde es
indefinido después de la operación.
Sintaxis
ADD dest, src | ADC dest, src
DAA
9.6.10 DAS
Corrige el resultado de una resta de dos valores entre los registros de tipo BCD
empaquetados en el registro AL, esta instrucción debe estar inmediatamente después
de una instrucción SUB o SBB, alterando OF donde es indefinido después de la
operación.
Sintaxis
SUB dest, src | SBB dest, src
DAS
76
9.6.11 MUL
Realiza una operación de multiplicación sin signo entre el operador destino(dest) y
fuente(src), dejando el valor resultante en el registro del destino.
Sintaxis
MUL dest, src
9.6.12 IMUL
Realiza una operación de multiplicación con signo entre el operador destino(dest) y
fuente(src), dejando el valor resultante en el registro del destino.
Sintaxis
IMUL dest, src
9.6.13 CBW
Extiende el signo de AL en AX, las banderas no se ven afectadas.
Sintaxis
CBW
9.7.1 AND
Esta instrucción lleva a cabo una operación and lógica entre dos operandos, guardando
el resultado en el operador destino (dest), la tabla de verdad de este operador es:
Fuente Destino Resultado
1 1 1
1 0 0
0 1 0
0 0 0
77
Sintaxis
AND dest, src
Sintaxis
TEST dest, src
9.7.3 OR
Esta instrucción lleva a cabo una operación or lógica entre dos operandos, guardando el
resultado en el operador destino (dest), la tabla de verdad de este operador es:
Fuente Destino Resultado
1 1 1
1 0 1
0 1 1
0 0 0
Sintaxis
OR dest, src
9.7.4 XOR
Esta instrucción lleva a cabo una operación de disyunción exclusiva entre dos operandos,
guardando el resultado en el operador destino (dest), la tabla de verdad de este operador
es:
Fuente Destino Resultado
1 1 0
1 0 1
0 1 1
0 0 0
78
Sintaxis
XOR dest, src
9.7.5 NOT
Esta instrucción genera el complemento a 1 del registro destino y lo almacena en el
mismo operador destino.
Sintaxis
NOT dest // donde dest tiene que ser registro o memoria
9.8.1 SHL/SAL
Realiza un desplazamiento lógico (SHL) o aritmético (SAL) a la izquierda en todo el
registro, comportándose de la siguiente manera:
Sintaxis
SHL dest, count // Realiza count desplazamientos en dest
SAL dest, count // Realiza count desplazamientos en dest
79
9.8.2 SHR
Realiza un desplazamiento lógico a la derecha en todo el registro, comportándose de la
siguiente manera:
Sintaxis
SHR dest, count // Realiza count desplazamientos en dest
9.8.3 SAR
Realiza un desplazamiento aritmético a la derecha en todo el registro, comportándose
de la siguiente manera:
Sintaxis
SHR dest, count // Realiza count desplazamientos en dest
80
9.8.4 ROL
Realiza una rotación a la izquierda en todo el registro, comportándose de la siguiente
manera:
Sintaxis
ROL dest, count // Realiza count desplazamientos en dest
9.8.5 ROR
Realiza una rotación a la derecha en todo el registro, comportándose de la siguiente
manera:
Sintaxis
ROR dest, count // Realiza count rotaciones en dest
81
9.8.6 RCL
Realiza una rotación a la izquierda en todo el registro, incluyendo el CF, comportándose
de la siguiente manera:
Sintaxis
RCL dest, count // Realiza count rotaciones en dest
9.8.7 RCR
Realiza una rotación a la derecha en todo el registro, incluyendo el CF, comportándose
de la siguiente manera:
Sintaxis
RCR dest, count // Realiza count rotaciones en dest
82
9.9 Instrucciones de transferencia de control
Las instrucciones de transferencia de control son aquellas que saltan la ejecución del
código hacia una etiqueta predefinida o a un procedimiento, las instrucciones de
transferencia son:
Sintaxis
JMP destino
9.9.2 CALL id
Realiza una transferencia de control que se dirige al procedimiento cuyo identificador es
especificado en la instrucción.
Sintaxis
Call proc1
9.9.3 RET
Esta es una transferencia de retorno que cuando se realizó una transferencia de control
dirigida a un procedimiento (call) puede retornar el control directamente a donde fue
llamado
Sintaxis
Ret
83
9.10.2 Aritmética sin signo (con números positivos y cero)
• JB etiqueta/JNAE etiqueta: Saltar a etiqueta si es menor.
• JBE etiqueta/JNA etiqueta: Saltar a etiqueta si es menor o igual.
• JE etiqueta: Saltar a etiqueta si es igual.
• JNE etiqueta: Saltar a etiqueta si es distinto.
• JAE etiqueta/JNB etiqueta: Saltar a etiqueta si es mayor o igual.
• JA etiqueta/JNBE etiqueta: Saltar a etiqueta si es mayor.
9.13 Interrupciones:
El manejo de interrupciones es una técnica de ensamblador basado en un mecanismo
automático en el hardware del microcontrolador, donde el flujo del programa entra a una
subrutina de atención para ejecutarla y únicamente al finalizar toda la subrutina continua
con la ejecución del programa principal.
84
Las principales instrucciones de interrupciones que maneja ensamblador son las
siguientes:
• INT numero: Guarda los flags en la pila, hace TF=IF=0 y ejecuta la interrupción
con el número indicado.
• INTO: Interrupción condicional, ejecuta la interrupción 4 Si OF = 1.
• IRET: Realiza un retorno de interrupción y restaura los indicadores del stack.
9.14.1 SEG
Instrucción que retorna el valor del segmento especificado.
Sintaxis
SEG memory-operand
Ejemplo
CMP DX, SEG A // Compara si DX es igual al segmento A
9.14.2 OFFSET
Retorna el valor del offset, el cual se refiere al desplazamiento que tuvo el registro desde
su segmento de datos, en pocas palabras retorna la dirección que tiene el registro.
85
Sintaxis
Offset memory-operand
Ejemplo
MOV DX, Offset AL // DX igual al puntero AL
9.14.3 TYPE
Retorna un valor que representa el tipo de operando, assembler cuenta con un índice
de tipos, siendo esta instrucción el retorno de dicho índice.
Índice Tipo
1 BYTE
2 WORD
4 DWORD
-1 NEAR
-2 FAR
Sintaxis
TYPE memory-operand
Ejemplo
MOV DX, TYPE Var // DX igual al índice del tipo Var
Sintaxis
Etiqueta PROC {NEAR|FAR}
// Lista Sentencias
86
ret
Etiqueta ENDP
Consideraciones
• Near/far depende si la operación implica un procedimiento cercano o lejano
• La instrucción ret regresa al segmento donde fue invocado el procedimiento.
• La llamada a un procedimiento se hace mediante call etiqueta.
Sintaxis
Nombre_macro MACRO [parámetro [,parámetro...]]*
// Lista Sentencias
ENDM
Consideraciones
• Los parámetros son opcionales. Si existen, entonces también aparecerán en
algunas de las sentencias en la definición de la macro. Al invocar la macro
mediante:
• nombre_macro [argumento [,argumento..]] se ensamblarán las sentencias
indicadas en la macro teniendo en cuenta que cada lugar donde aparezca un
parámetro se reemplazará por el argumento correspondiente.
• PURGE nombre_macro [,nombre_macro...]: Borra las macros indicadas de la
memoria para poder utilizar este espacio para otros símbolos.
Ejemplo
SUMAR MACRO xx, yy, zz
MOV AX, xx
ADD AX, yy
MOV zz, AX
ENDM
87
9.15 Operadores de macros
Son operadores que se utilizan en las definiciones de macros. Hay cinco: &, <>, !, % y
;;.
• &parámetro: reemplaza el parámetro con el valor actual del argumento.
• <texto>: trata una serie de caracteres como una sola cadena. Se utiliza cuando
el texto incluye comas, espacios u otros símbolos especiales.
• !carácter: trata el carácter que sigue al operador ! como un carácter en vez de un
símbolo o separador.
• %texto: trata el texto que sigue a continuación del operador % como una
expresión. El ensamblador calcula el valor de la expresión y reemplaza el texto
por dicho valor.
• sentencia;; comentario: Permite definir comentarios que aparecerán en la
definición de la macro pero no cada vez que éste se invoque en el listado fuente
que genera el ensamblador.
Donde valor_inicial puede ser una cadena o una expresión numérica cuyo resultado
esté entre -255 y 255.
[nombre] DW valor_inicial [, valor_inicial...]
Donde valor_inicial puede ser una expresión numérica cuyo resultado esté entre -
65535 y 65535 o un operando de memoria en cuyo caso se almacenará el offset de
este.
88
[nombre] DD valor_inicial [, valor_inicial...]
Donde valor_inicial puede ser una constante cuyo valor esté entre -4294967295 y
4294967295, una expresión numérica cuyo valor absoluto no supere 65535, o bien un
operando de memoria en cuyo caso se almacenarán el offset y el segmento del mismo
(en ese orden).
Sintaxis
nombre_segm SEGMENT [alineación][combinación]['clase']
// Lista sentencias
nombre_segm ENDS
89
• PUBLIC: Concatena todos los segmentos que tienen el mismo nombre para
formar un sólo segmento. Todas las direcciones de datos e instrucciones se
representan la distancia entre el inicio del segmento y la dirección
correspondiente. La longitud del segmento formado será la suma de las
longitudes de los segmentos con el mismo nombre.
• STACK: Es similar a PUBLIC. La diferencia consiste que, al comenzar la
ejecución del programa, el registro SS apuntará a este segmento y SP se
inicializará con la longitud en bytes de este segmento.
• COMMON: Pone el inicio de todos los segmentos teniendo el mismo nombre en
la misma dirección de memoria. La longitud del segmento será la del segmento
más largo.
• MEMORY: Es igual a PUBLIC.
• AT dirección_de_segmento: Hace que todas las etiquetas y direcciones de
variables tengan el segmento especificado por la expresión contenida en
dirección_de_segmento. Este segmento no puede contener código o datos con
valores iniciales. Todos los símbolos que forman la expresión
dirección_de_segmento deben conocerse en el primer paso de ensamblado.
Si no se indica combinación, el segmento no se combinará con otros del mismo nombre
(combinación "privada").
91
10 Manejo de errores
El compilador deberá ser capaz de detectar todos los errores que se encuentren durante
el proceso de compilación. Todos los errores se deberán de recolectar y se mostrara un
reporte de errores en el que, como mínimo, debe mostrarse el tipo de error, su ubicación
y una breve descripción de por qué se produjo.
92
11 Apéndice A: Precedencia y asociatividad de
operadores
La precedencia de los operadores indica el orden en que se realizaran las distintas
operaciones del lenguaje. Cuando dos operadores tengan la misma precedencia, se
utilizará la asociatividad para decidir qué operación realizar primero.
A continuación, se presenta la precedencia de operadores lógicos, aritméticos y
relacionales.
93
12 Entregables y Restricciones
12.1 Entregables
● Código fuente
● Aplicación funcional
● Gramáticas
● Manual técnico
● Manual de usuario
Deberán entregarse todos los archivos necesarios para la ejecución de la aplicación, así
como el código fuente, la gramática y la documentación. La calificación del proyecto se
realizará con los archivos entregados en la fecha establecida. El usuario es completa y
únicamente responsable de verificar el contenido de los entregables. La calificación se
realizará sobre archivos ejecutables. Se proporcionarán archivos de entrada al momento
de calificación.
12.2 Restricciones
● La aplicación deberá ser desarrollada utilizando el lenguaje Java haciendo uso de
flex y cup para la generación de analizadores léxicos y sintácticos.
● El código intermedio deberá analizarse y ejecutarse con Jison y node js.
● El código ensamblador deberá únicamente generarse, el estudiante no debe
aplicar ninguna ejecución sobre este código.
● Copias de proyectos tendrán de manera automática una nota de 0 puntos y serán
reportados a la Escuela de Ingeniería en Ciencias y Sistemas los involucrados.
● Para la validación del código intermedio se correrá en un ambiente externo
proveído por los auxiliares para corroborar la correcta implementación.
● Para el flujo de la aplicación es necesario que el estudiante traiga instalado
DosBox para la ejecución de código ensamblador.
12.3 Consideraciones
• El auxiliar podrá realizar cambios al enunciado de forma oficial en un documento
de cambios, estos cambios solo podrán hacerse durante los primeros 15 días
después de la publicación de este.
• El estudiante deberá realizar lo que se exprese en este documento considerando
los cambios que estén plasmados en el documento de cambios.
• Durante la calificación se realizarán preguntas sobre el código para verificar la
autoría del mismo, de no responder correctamente la mayoría de las preguntas se
reportará la copia.
94
12.4 Requisitos mínimos
Los requerimientos mínimos del proyecto son funcionalidades del sistema que permitirán
un ciclo de ejecución básica, para tener derecho a calificación se deben cumplir con lo
siguiente:
2 Descripción
2.1 Descripción de la aplicación
2.1.2 DosIDE
2.1.3 Consola
2.1.4 Debugger
2.1.6 Reportes
3 Generalidades del lenguaje DOSLang
3.1 Tipos de dato
3.1.1 Tipos primitivos
3.1.2 Tipos definidos por el usuario
3.1.3 Tipos de dato enumerados
3.1.4 Tipos de subrango
3.2 Arreglos
3.2.1 Arreglos Multidimensionales y Arreglos de arreglos
3.2.2 Acceso a los arreglos
3.3 Registros
3.4 Memoria Virtual
3.4.1 Sizeof
3.4.2 malloc
4 Definición léxica
4.3 Comentarios
4.4 Sensibilidad a mayúsculas y minúsculas
4.5 Identificadores
95
4.6 Palabras reservadas
4.7 Literales
4.8 Secuencias de escape
5 Estructura del Lenguaje
5.1 Nombre del programa
5.2 Sentencia uses
5.3 Declaración de variables
5.4 Declaración de constantes
5.5 Expresiones
5.6 Funciones y Procedimientos
5.6.1 Funciones
5.6.2 Procedimientos
5.6.3 Paso de Parámetros
6 Sentencias
6.1 Bloques
6.3 Asignación de variables
6.4 Sentencias de transferencia
6.4.1 Break
6.4.3 Exit
6.5 Sentencias de selección
6.5.1 Sentencia If
6.6 Ciclos
6.8 Sentencia Write
7 Generación de código intermedio
7.1 Temporales
7.2 Etiquetas
7.3 Identificadores
7.4 Comentarios
7.5 Operadores aritméticos
7.6 Saltos
7.6.1 Saltos condicionales
96
7.6.2 Salto incondicional
7.7 Asignación a temporales
7.8 Declaración de métodos
7.9 Llamadas a métodos
7.10 Print
7.12 Entorno de ejecución
7.12.1 Estructuras del entorno de ejecución
7.12.2 Acceso a estructuras del entorno de ejecución
9 Generación de código ensamblador
9.1 Entrada de ASM
9.2 Salida de ASM
10 Manejo de errores
10.1 Tipos de errores
10.2 Contenido mínimo de tabla de errores
10.3 Método de recuperación
11 Apéndice A: Precedencia y asociatividad de operadores
97