Compiladores. Guía 10 1 Facultad: Ingeniería Escuela: Computación Asignatura: Compiladores Tema: Lenguaje ensamblador embebido Contenido En esta guía se presenta una breve introducción a las estructuras básicas de lenguaje ensamblador embebidas en lenguaje C++. Estas pueden ser interpretadas y ejecutadas perfectamente por el compilador Dev C++ que se ocupara en la práctica. Se pretende que sea una herramienta más para construir un generador de código. Objetivos Específicos Reconocer las diferentes instrucciones para la generación de código ensamblador. Realizar segmentos de código a través de ejemplos de ASM embebidos en C++. Material y Equipo Guía de Laboratorio Nº 10. Computadora con DevC++ Introducción Teórica El lenguaje ensamblador que se utiliza para traducir Guía 3 al código de máquina. Cada microprocesador o micro programas controlador tiene su propio lenguaje ensamblador con su particular conjunto de instrucciones y sus varios modos de Guía 4 direccionamiento que dependen de la arquitectura del hardware, cada nuevo procesador de INTEL que sale al mercado, fíafabricante agrega algunas instrucciones a su conjunto de el instrucciones, pero siempre conservan las instrucciones y registros de los modelos anteriores por razones de compatibilidad. 2 Compiladores. Guía 10 Registros del procesador Los primeros procesadores proveían registros de 16 bits AX, BX, CX, DX, SI, DI, BP, SP, CS, DS, SS, ES, IP, y FLAGS. El procesador soportaba hasta 1Mb de memoria y solo podía operar en modo Real. En este modo el programa podía acceder a cualquier dirección de memoria, incluso a direcciones utilizadas por otros programas. Sus cuatro registros principales, AX, BX, CX, y DX están divididos en dos registros de 8 bits cada uno. En la Fig. 1 se puede observar el registro AX que posee una parte que contiene los primeros 8 bits denominada AH (high) y una parte que contiene los últimos 8 bits denominada AL (low), y así sucesivamente con cada uno de los registros mencionados. Este tipo de registros se usa especialmente en operaciones aritméticas, ya que nos permite manejarnos con comodidad cuando trabajamos con datos que no superan un byte, pero se debe tener cuidado ya que AH y AL no son independientes de AX, o sea que si hacemos algún movimiento de datos referenciando a AX, también estamos cambiando los valores de AH y AL. Los registros SI y DI son utilizados generalmente como punteros. Los registros BP y SP se conocen como los punteros de pila. Se utilizan para moverse dentro de la pila. CS, DS, SS, y ES son los segments registers. Son los encargados de direccionar las distintas partes de cada programa: CS para el code segment, donde se guardan los datos del código de máquina de las instrucciones que constituyen el programa. Compiladores. Guía 10 3 DS para el data segment, que guarda los datos que el programa debe operar y los resultados de la ejecución del mismo. SS para el stack segment, Almacena datos y direcciones necesarias durante la ejecución de cada parte del programa y que es localizada dentro del segmento mediante el registro SP (stack pointer). ES para el extra segment, utilizado para guardar datos tipo strings, también como prolongación del DS (data segment), y como registro temporal. Cada dato es apuntado dentro del segmento por el registro puntero DI. El registro IP es utilizado para mantener una pista de la dirección de la próxima instrucción a ejecutarse por el procesador. Normalmente cuando se ejecuta una instrucción, IP se adelanta a apuntar a la próxima instrucción en memoria. El FLAGS es un registro de 16 bits que se divide en 16 partes de 1 bit. Cada uno de estos bits guarda información importante sobre el resultado de la instrucción anterior. Este resultado se guarda con un solo un bit que puede ser 1 ó 0. Por ejemplo, el bit Z es 1 si el resultado de la instrucción anterior fue 0, y es 0 si el resultado fue 1. El bit C será 1 si la última operación produjo acarreo, y 0 si no lo hizo. A partir del procesador 80386 se produce un salto en el diseño. Extendiendo la mayoría de sus registros a 32 bits y renombrándolos como EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP y agregan también dos registros nuevos de 16 bits denominados FS y GS. Para guardar compatibilidad con los diseños anteriores se conviene de que al hacer referencia a AX, se hace referencia a los últimos 16 bits de EAX (lo mismo que era AL de AX); pero no se puede tener acceso directo a los primeros 16 bits de EAX. Instrucciones de lenguaje ensamblador: Instrucción MOV: La función de la instrucción MOV, es como su nombre da a entender, "mover" un valor. Por ejemplo: MOV AX,BX Esta instrucción copia el contenido de BX en AX, conservando el valor de BX. Otro ejemplo: MOV AX,2000 MOV [A100],AX 4 Compiladores. Guía 10 En este caso introducimos el valor 2000 en AX, y luego lo llevamos a la dirección de memoria A100. Con la instrucción operaciones: MOV se puede realizar las siguientes Instrucciones INC y DEC: Son las más básicas a la hora de hacer operaciones con registros: INC, incrementa el valor de un registro o de cualquier posición de memoria en una unidad. DEC, lo decrementa un registro en el mismo valor. Ejemplos: INC AX DEC AX Incrementa en una unidad el valor de AX y lo decrementa, por lo que no ha cambiado su valor. Estas dos instrucciones nos van a servir mucho en el uso de contadores en los bucles. Son equivalentes a ++ y -- del lenguaje C/C++. Instrucciones ADD y SUB: Se trata de dos operadores que contienen todos los lenguajes de programación: la suma y la resta. Tienen dos operandos, uno de destino y otra fuente. Para la suma, se suman los dos operandos y se almacena el resultado en el primero (destino). Para la resta, se le resta al primero el segundo, y se almacena el resultado en el primero (destino). Ejemplos: ADD AX,BX ;Suma a AX con BX, y lo guarda en AX. (AX+BX) -> AX ADD AX,[SI] ;Se suman AX y el contenido de lo que esta apuntado por SI y se almacena en AX. ADD AX,3 ;Suma 3 a AX y lo almacena en AX. (AX+3) -> AX SUB AX,AX ;Resta AX de AX. Se utiliza para poner a AX en 0. SUB CX,DX ;Se resta el valor de CX con DX y se almacena en CX. SUB CX,20 ;Se resta de CX el valor 20, y queda en CX el resultado. Compiladores. Guía 10 5 Nota: el uso de la “;” es para hacer comentarios. Procedimiento Desarrolle el siguiente programa Guía 3 embebido: #include <cstdlib> #include Guía 4 <iostream> using namespace std; int a; fía b; int main() { asm("movl $9, %eax"); asm("subl $4, %eax"); asm("movl %eax, _a"); printf("a = %d\n", a); asm("movl $3, %eax"); asm("addl $9, %eax"); asm("movl %eax, _b"); printf("b = %d\n", b); system("PAUSE"); return 0; } de C++ con ensamblador Debe notar que las variables globales a y b declaradas dentro del código ensamblador se denotan como _a y _b. Ejecute el programa siguiente, observe el resultado justifique la forma de implementar código embebido: #include <cstdlib> #include <iostream> using namespace std; int a=3; int b=9; main() { asm("movl _b, %eax"); asm("subl _a, %eax"); asm("movl %eax, _a"); printf("a = %d\n", a); asm("movl _b, %eax"); y 6 Compiladores. Guía 10 asm("addl _a, %eax"); asm("movl %eax, _b"); printf("b = %d\n", b); system("PAUSE"); return 0; } _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ Ejecute también el programa siguiente, observe el resultado y justifique la forma de implementar código embebido: #include <cstdlib> #include <iostream> using namespace std; int a=3; int b=9; main() { asm("movl _a, %eax"); asm("movl _b, %ebx"); asm("mul %ebx"); asm("mov %eax, _a"); printf(" %d\n", a); system("PAUSE"); return 0; } _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ _____________________________________________________________ Compiladores. Guía 10 7 Análisis de resultados Explique, Como se puede hacer mejoras al programa siguiente: #include <cstdlib> #include <iostream> using namespace std; int a=3; int b=20; int c=7; int d=1; int e=0; main() { asm("movl _a, %eax"); asm("add _b, %eax"); asm("add _c, %eax"); asm("add _d, %eax"); asm("movl $4, %ecx"); asm("cltd"); asm("divl %ecx"); asm("mov %eax, _c"); asm("movl %edx, _e"); printf(" %d\n", c); printf(" %d\n", e); system("PAUSE"); return 0; } 8 Compiladores. Guía 10 Investigación complementaria Se pide los programas que generen código ensamblador para: 1. sentencias condicionales if (i 2 j > 7) { <Bloque A> else { <Bloque B> } <Bloque C> 2. sentencias repetitivas for for (inicial; condicion; incremento) { <cuerpo de for> } 3. sentencias repetitivas while. while (inicial) { <cuerpo de while> } 4. funciones Investigar: o Que es un interprete o Cuál es la función principal o Como funciona o Que resultado genera o Convenciones léxicas de ENSAMPOCO/3 o Ejemplo de ENSAMPOCO/3 Bibliografía http://www.gui.uva.es/udigital/ http://repositori.uji.es/xmlui/bitstream/handle/10234/59 16/codigo.apun.pdf?sequence=1 Compiladores. Guía 10 9 Guía 10: Embebido Lenguaje Hoja de cotejo: Ensamblador Docente: Tema: Presentación del programa Alumno : 10 1 Máquina No: Máquina No: Máquina No: GL: Alumno: Docente: GL: Docente: GL: Fecha: a EVALUACION % CONOCIMIENTO Del 20 al 30% APLICACIÓN DEL CONOCIMIENTO Del 40% al 60% 1-4 5-7 8-10 Conocimie nto deficient e de los fundament os teóricos Conocimiento y explicación incompleta de los fundamentos teóricos Conocimiento completo y explicación clara de los fundamentos teóricos No tiene actitud proactiva . Actitud propositiva y con propuestas no aplicables al contenido de la guía. Tiene actitud proactiva y sus propuestas son concretas. ACTITUD Del 15% al 30% TOTAL 100% Nota