Sie sind auf Seite 1von 9

UNIDAD 4 PROGRAMACION HIBRIDA 4.

1 DIRECTIVAS PARA COMPILACION HIBRIDA Directivas de Programacin Hbrida EL ENSAMBLADOR Y EL LENGUAJE C El lenguaje C es sin duda el ms apropiado para la programacin de sistemas, pudiendo sustituir al ensamblador en muchos casos. Sin embargo, hay ocasiones en que es necesario acceder a un nivel ms bajo por razones de operatividad e incluso de necesidad (programas residentes que economicen memoria, algoritmos rpidos para operaciones crticas, etc.). Es entonces cuando resulta evidente la necesidad de poder emplear el ensamblador y el C a la vez. Para comprender este captulo, basta tener unos conocimientos razonables de C estndar. Aqu se explicarn las funciones de librera necesarias para acceder al ms bajo nivel, as como la manera de integrar el ensamblador y el C. Sentencias ensamblador C++ dispone de la opcin de poder escribir directamente instrucciones en lenguaje ensamblador junto con el resto del cdigo fuente. Para esto dispone de una palabra clave especfica: asm. La palabra asm indica que la cadena literal que sigue ser incluida en el cdigo objeto en la posicin indicada. La sintaxis empleada depende del compilador. En el caso de C++Builder, es la siguiente: asm<opcode><operandos><; o NL> Ejemplo asm pop dx; asm push ebx; asm call @@std@%basic_ostream$c19std@%char_traits$c%%@put$qc; asm add esp,8; asm push ebx; Se permite que varias instrucciones ensamblador pueden ser agrupadas en un solo bloque precedido por el indicador asm. Ejemplo: asm { movax, 0x0e07;

xorbx, bx; int 0x10; } La sintaxis empleada por el compilador C++ GNU para Windows utilizado por Dev-C++ no utiliza la sintaxis de Intel, sino la de AT&T. Ejemplo [2]: intAdrIO; // variable global staticcharValIO; // variable global voidfoo() { __asm("mov _AdrIO, %dx") ; // cargar un registro de 16 bits __asm("mov _ValIO, %al") ; // cargar un registro de 8 bits __asm("mov %ax,%dx") ; // mover contenido registro AX a DX } Nota: no olvidar incluir el guin bajo ("underscore") precediendo los nombres de variables globales. Ni que decir tiene que cualquier cdigo ensamblador insertado mediante asm, es especfico, y por tanto dependiente, de la plataforma sobre la que se ejecutar el programa. Este tipo de sentencias deben reducirse al mximo si queremos facilitar la portabilidad del cdigo.

4.3 BLOQUES EN LENGUAJE ENSAMBLADOR

Bloques en ensamblador MODELOS DE MEMORIA. Los modelos de memoria constituyen las diversas maneras de acceder a la memoria por parte de los compiladores de C. En el caso del Turbo C se pueden distinguir los siguientes: TINY: Se emplea en los programas donde es preciso apurar el consumo de memoria hasta el ltimo byte. Los 4 registros de segmento (CS, DS, ES, SS) estn asignados a la misma direccin, por lo que existe un total de 64 Kb donde se mezclan cdigo, datos y pila. Los programas de este tipo pueden convertirse a formato COM. SMALL: Se utiliza en aplicaciones pequeas. Los segmentos de cdigo y datos son diferentes y no se solapan. Por ello, hay 64 kb para cdigo y otros 64 Kb a repartir entre datos y pila. Segmentos Punteros Modelo Tiny Cdigo Datos Pila Cdigo Datos

64 Kb near near

Small 64 Kb 64 Kb near near Medium Compact 1 Mb 64 Kb far near

64 Kb 1 Mb near far far

Large 1 Mb 1 Mb far Huge 1 Mb 1 Mb (Bloques > 64 Kb) far

far

MEDIUM: Este modelo es ideal para programas largos que no manejan demasiados datos. Se utilizan punteros largos para el cdigo (que puede extenderse hasta 1 Mb) y cortos para los datos: la pila y los datos juntos no pueden exceder de 64 Kb. COMPACT: Al contrario que el anterior, este modelo es el apropiado para los programas pequeos que emplean muchos datos. Por ello, el programa no puede

exceder de 64 Kb aunque los datos que controla pueden alcanzar el Mb, ya que los punteros de datos son de tipo far por defecto. LARGE: Empleado en las aplicaciones grandes y tambin por los programadores de sistemas que no tienen paciencia para andar forzando continuamente el tipo de los punteros (para rebasar el lmite de 64 Kb). Tanto los datos como el cdigo pueden alcanzar el Mb, aunque no se admite que los datos estticos ocupen ms de 64 Kb. Este modo es el que menos problemas da para manejar la memoria, no siendo quiz tan lento y pesado como indica el fabricante. HUGE: Similar al anterior, pero con algunas ventajas: por un lado, todos los punteros son normalizados automticamente y se admiten datos estticos de ms de 64 Kb. Por otro, y gracias a esto ltimo, es factible manipular bloques de datos de ms de 64 Kb cada uno, ya que los segmentos de los punteros se actualizan correctamente. Sin embargo, este modelo es el ms costoso en tiempo de ejecucin de los programas. Usando la pila Una seccin de la memoria del programa es reservado para el uso de una pila. La Intel 80386 y procesadores superiores contienen un registro llamado puntero a la pila, esp, el cual almacena la direccin del tope de la pila, la figura 1 de abajo muestra 3 valores enteros, 49, 30 y 72, almacenados en la pila(cada entero ocupando 4 bytes) con el registro esp apuntando a la direccin del tope de la pila.

A diferencia de una pila creciendo hacia arriba, en las mquinas intel crecen hacia abajo. En la Figura 2 muestra las capas de la pila despus de la ejecucin pushl $15. El punter de la pila es decrementado de cuatro en cuatro y el nmero 15 es almacenando como lugares de 4 bytes, 1988, 1989, 1990 y 199

La instruccin popl %eax copia el valor del tope de la pila(4 bytes) a eax e incrementa esp en 4. Qu sucede si no quieres copiar el valor del tope de la pila a un registro?. Puedes ejecutar la instruccin addl $4, %esp el cual simplemente incrementa el puntero de la pila. #Listing 3 .globl main main: movl $10, %eax call foo ret foo: addl $5, %eax ret En Listing 3, la instruccin callfoo pone la direccin de la instruccin despus de call en la llamada al programa sobre la pila y va hacia foo. La subrutina termina con ret, el cual transfiere el control a la instruccin cuya direccin se toma desde el tope de la pila. Obviamente el tope de la pila debe contener una direccin vlida.

4.4 OPERADORES LENGUAJE ENSAMBLADOR


Operadores VARIABLES GLOBALES PREDEFINIDAS INTERESANTES. _version /* devuelve la versin del DOS de manera completa */ _osmajor /* devuelve el nmero principal de versin del DOS: ej., 5 en el DOS 5.0 */ _osminor /* devuelve el nmero secundario de versin del DOS: ej., 0 en el DOS 5.0 */ _psp /* segmento del PSP */ _stklen /* contiene el tamao de la pila, en bytes */ _heaplen /* almacena el tamao inicial del heap, en bytes (0 para maximizarlo) */ De estas variables predefinidas, las ms tiles son quiz las que devuelven la versin del DOS, lo que ahorra el esfuerzo que supone averiguarlo llamando al DOS o empleando la funcin de librera correspondiente. Tambin es til _psp, que permite un acceso a este rea del programa de manera inmediata. Operadores Aritmticas, de Comparacin y Ciclos El siguiente programa realize un factorial de un nmero almacenado en eax. El factorial es almacenado en ebx. #Listing 2 .globlmain main: movl $5, %eax movl $1, %ebx L1: cmpl $0, %eax //compare 0 withvalue in eax je L2 //jump to L2 if 0==eax (je - jump if equal) imull %eax, %ebx // ebx = ebx*eax decl %eax //decrement eax jmp L1 // unconditional jump to L1 L2: ret L1 and L2 son etiquetas.Cuando el flujo de control llega a L2, ebx contendr el factorial de un nmero almacenado en eax. INSERCIN DE CDIGO EN LNEA. void _ _emit_ _ (argumento,...); voidgeninterrupt (int interrupcin); Por medio de _ _emit_ _() se puede colocar cdigo mquina de manera directa dentro del programa en C. No es conveniente hacerlo as porque as, ya que alterar directamente los registros de la CPU acabar alterando el funcionamiento

esperado del compilador y haciendo fallar el programa. Sin embargo, en un procedimiento dedicado exclusivamente a almacenar cdigo inline (en lnea), es seguro este mtodo, sobre todo si se tiene cuidado de no alterar los registros SI y DI (empleados muy a menudo por el compilador como variables de tipo register). Por medio de geninterrupt() se puede llamar directamente a una interrupcin: geninterrupt (interr) es exactamente lo mismo que _ _emit_ _(0xCD, interr) ya que 0xCD es el cdigo de operacin de INT. Por ejemplo, para volcar la pantalla por impresora se puede ejecutar geninterrupt(5). Con los smbolos _AX, _AL, _AH, _BX, _BL, _BH, _CX, _CL, _CH, _DX, _DL, _DH, _SI, _DI, _BP, _SP, _CS, _DS, _ES, _SS y _FLAGS se puede acceder directamente a los registros de la CPU. Hay que tomar tambin precauciones para evitar efectos laterales (una asignacin tipo _DS=0x40 no afectar slo a DS). El GNU C soporta la arquitectura x86 muy bien, e incluye la habilidad de insertar cdigo en programas C, tal como los espacios de registros. Por supuesto, las instrucciones son dependientes de la arquitectura. La instruccin asm permite insertar instrucciones dentro de C y C++, como las siguientes: asm ("fsin" : "=t" (answer) : "0" (angle)); que es una manera de codificar en C la siguiente instruccin: answer = sin(angle); Se puede ver que a diferencia de ensamblador comn se permite especificar entradas y salidas usando la sintaxis de C. Pero como no se deben usar indiscriminadamente por qu razones debemos usarlas?:
y

Sentencias Asm permiten acceder al hardware de la computadora directamente. Esto puede generar que los programas se ejecuten ms rpidamente. Se puede usar cuando se escriben cdigos de sistema operativo que necesita directamente interactuar con el hardware. Instrucciones inline tambin aumentan la velocidad del recorrido de ciertos ciclos de los programas. Por ejemplo, seno y coseno de los mismos ngulos pueden encontrarse desde fsincos x86. Probablemente, los siguientes ejemplos ayuden a entender mejor lo expuesto en estos dos puntos.

#Listing 11 #Name : bit-pos-loop.c #Description : Find bit position using a loop #include <stdio.h>

#include <stdlib.h> int main (intargc, char *argv[]) { long max = atoi (argv[1]); long number; long i; unsigned position; volatile unsigned result; for (number = 1; number <= max; ; ++number) { for (i=(number>>1), position=0; i!=0; ++position) i >>= 1; result = position; } return 0; } #Listing 12 #Name : bit-pos-asm.c #Description : Find bit position using bsrl #include <stdio.h> #include <stdlib.h> int main(intargc, char *argv[]) { long max = atoi(argv[1]); long number; unsigned position; volatile unsigned result; for (number = 1; number <= max; ; ++number) { asm("bsrl %1, %0" : "=r" (position) : "r" (number)); result = position; } return 0; } Compile the two versions with full optimizations as given below: $ cc -O2 -o bit-pos-loop bit-pos-loop.c $ cc -O2 -o bit-pos-asm bit-pos-asm.c Mide el tiempo de ejecucin de cada versin usando el comando time y especificando el valor longitud en los argumentos de la lnea de comandos para asegurarte que cada versin toma al menos unos segundos ejecutarse.

$ time ./bit-pos-loop 250000000 and $ time ./bit-pos-asm 250000000 El resultado puede variar en diferentes mquinas. Sin embargo se notar que la versin que usa funciones inline se ejecuta ms rpido que la otra. Nota: El optimizador de GCC intenta reorganizar y escribir el cdigo del programa para minimizar el tiempo de ejecucin incluso en presencia de expresiones asm. Si el optimizador determina que la salida de un asm no es usada, la instruccin ser omitida a menos que la palabra volatile est entre asm y sus argumentos. Cualquier asm puede ser movido de manera que sea difcil de predecir, incluso en saltos cruzados. La nica manera de garantizar ensamble en particular con un orden de instruccin es incluir todas las instrucciones en el mismo asm.

Das könnte Ihnen auch gefallen