Ensamblador

Para mi primer entrega de Lenguaje Ensamblador decidí hacer un programa sencillo pero que cubriera lo básico del lenguaje;

mi programa realiza la funcion la siguiente formula:  nCr

esta formula calcula la cantidad de combinaciones que se pueden generar con n y r  , realmente se le pueden llamar de la forma que se desee n combinacion con m ,n=numero de variables totales, m=numero de variables que se combinaran.

aqui esta el codigo en C… en el cual la maneje como aCb   pero es exactamente lo mismo😛

(lo empecé a hacer en nasm para aprender como se hacia desde 0 pero au no lo termino😐   )asi que estuve investigando y me encontre con lo que la mayoria de mis compañeros estuvo trabajando “traducir” el codigo a  lenguaje ensamblador con las herramientas de gcc, con la instruccion gcc -S archivo.c, con esto se genera un archivo.s el cual ya esta hecho en ensamblador con las caracteristicas de nuestro equipo; cuando estuve batallando con mi programa en nasm :p encontré ciertos documentos en los que puedo resaltar esta información.

El compilador gcc se puede ejecutar con varias opciones.

-o    indica el nombre del archivo de salida, cuando no se usa, el compilador genera un archivo llamado a.out por defecto.
-S   ensambla, la salida es un archivo en lenguaje ensamblador con el sufijo
-c    enlaza, la salida será un archivo en código objeto con el sufijo .o su contenido se encuentra en binario. Se puede utilizar la  herramienta objdump para desensamblar este archivo y visualizar su contenido.
-O opción de optimización, se acompaña con un número que indica el nivel de optimización deseado.
Se puede escoger entre O0, O1, O2 u O3.
-g produce información para la depuración del programa.

Usando el programa el comando:

gcc C.c -O3 -S

tambien se genera un archivo .s

Existe otra opción de (-v, verbose), la cual nos permite observar la manera en la
que gcc invoca a cada una de las herramientas mencionadas (el compilador, el
ensamblador y el enlazador) para generar el archivo ejecutable. Por ejemplo, si
repetimos la compilación del archivo ejemplo.s utilizando esta opción, podemos
distinguir cada uno de los pasos descritos anteriormente:

gcc C.s -o C.s -v

En este caso, se pueden observar las siguientes líneas dentro de la salida
producida por gcc:

Usando especificaciones internas.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.6.1/lto-wrapper
Objetivo: i686-linux-gnu
Configurado con: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Modelo de hilos: posix
gcc versión 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
COLLECT_GCC_OPTIONS='-o' 'C.s' '-v' '-mtune=generic' '-march=i686'
 as --32 -o /tmp/ccWrfl7s.o C.s
COMPILER_PATH=/usr/lib/gcc/i686-linux-gnu/4.6.1/:/usr/lib/gcc/i686-linux-gnu/4.6.1/:/usr/lib/gcc/i686-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6.1/:/usr/lib/gcc/i686-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.6.1/:/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../../lib/:/lib/i386-linux-gnu/:/lib/../lib/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-o' 'C.s' '-v' '-mtune=generic' '-march=i686'
 /usr/lib/gcc/i686-linux-gnu/4.6.1/collect2 --build-id --no-add-needed --as-needed --eh-frame-hdr -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 -z relro -o C.s /usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crt1.o /usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crti.o /usr/lib/gcc/i686-linux-gnu/4.6.1/crtbegin.o -L/usr/lib/gcc/i686-linux-gnu/4.6.1 -L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu -L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../../../lib -L/lib/i386-linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/i686-linux-gnu/4.6.1/../../.. /tmp/ccWrfl7s.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i686-linux-gnu/4.6.1/crtend.o /usr/lib/gcc/i686-linux-gnu/4.6.1/../../../i386-linux-gnu/crtn.o
karenalduncin@lilalduncin:~$

Se observa que el gcc llevó a cabo tres pasos:

as --32 -o /tmp/ C.s

Llamó al compilador (cc1) pasando el archivo “C.c” como entrada, y
generando el archivo “ccWrfl7s.o” como salida. Llamó al ensamblador (as), pasando la salida del compilador como entrada, y generando el archivo objeto relocalizable “cc4ziThv.o” como salida.
Llamó al enlazador (collect2) pasando como entrada la salida del ensamblador y un conjunto de bibliotecas estándar, y generando como salida el archivo objeto ejecutable “comb” Luego de observar este resultado, es importante aclarar algunos puntos:
El archivo fuente original puede utilizarse directamente como entrada al compilador. En caso de que la entrada haya sido pre procesada previamente, debe utilizarse la opción –fpreprocessed para indicarle este hecho al cc1. El enlazador real es ld pero gcc hace la llamada a ollect2 debido al funcionamiento interno de esta herramienta.
Cada una de las herramientas llamadas por gcc cuenta con su propio conjunto de opciones que permiten un mayor control sobre todo el proceso de traducción en caso de ser necesario.
Finalmente, es posible realizar todos los pasos del proceso de traducción de manera manual, llamando a cada una de las herramientas con las opciones más adecuadas de acuerdo a lo que se quiere lograr. Por ejemplo, para generar el archivo ejecutable “Combb” podemos realizar  los siguientes pasos:

cpp C.c -o C.i
as C.s -o C.o

aqui se crea el fichero que contiene la dirección del archivo  lo podemos abrir con nuestro editor de texto que utilizemos.

En la vida real se dan situaciones en que se nos proporciona una biblioteca previamente compilada (.o, .a, .so) sin ningún tipo de  documentación, y debemos averiguar la forma correcta de utilizarla dentificarlas de alguna manera, bien sea obteniendo una lista de los símbolos globales que identifican a dichas funciones (entry points) o bien sea desensamblando el código binario y analizando el mismo.

Es posible llevar a cabo estas tareas utilizando un grupo de herramientas provistas por GNU para el manejo de archivos binarios, conocidas como binutils, entre las cuales se encuentran:

ld                         El enlazador GNU
as                         El ensamblador GNU
addr2line           Permite convertir direcciones a nombres de archivo y números de línea
ar                         Herramienta para el manejo de bibliotecas estáticas
nm                      Lista los símbolos contenidos en un archivo objeto
objcopy              Permite convertir entre formatos de archivo objeto
objdump           Muestra la información contenida en un archivo objeto
readelf               Extrae la información contenida en un archivo objeto en formato ELF
size                     Muestra el tamaño de los segmentos de un archivo objeto o una biblioteca estática
strings               Lista todas las cadenas imprimibles de un archivo
strip                   Elimina símbolos y secciones de un archivo objeto

De esta forma, podemos utilizar la herramienta objdump para desensamblar el segmento de código del archivo binario ejemplo.o y analizar su contenido:

karenalduncin@lilalduncin:~$ gcc C.c -O2 -c -o Com.o
C.c: En la función ‘main’:
C.c:14:8: aviso: se descarta el valor de devolución de ‘scanf’, se declaró con el atributo warn_unused_result [-Wunused-result]
C.c:16:8: aviso: se descarta el valor de devolución de ‘scanf’, se declaró con el atributo warn_unused_result [-Wunused-result]
karenalduncin@lilalduncin:~$ objdump C.o -d
//debajo les aparecera el desensamblado :B

En la cual se identifica claramente el procedimiento main y las instrucciones que conforman el cuerpo del mismo.
La herramienta objdump tiene varias opciones entre las que vale la pena destacar:
-d desensambla el código del segmento de texto.
-D desensambla todo el programa incluyendo los datos (el programa trata de traducir toda la información como instrucciones así que en la parte de datos la traducción no se corresponde con la información almacenada).
-G muestra la información de depuración de programas.
-l muestra los números de línea.
-r muestra las entradas de relocalización.
-R muestra las entradas de relocalización dinámica.
-t muestra la tabla de símbolos.
Si se incluye información de depuración del archivo binario (utilizando la opción –g), es posible relacionar cada dirección del programa desensamblado con las líneas originales del programa en lenguaje de alto nivel, mediante la utilización de addr2line:

gcc C.c -o C-o -c -g -O2
karenalduncin@lilalduncin:~$ addr2line -e C.o -s

Algunas opciones importantes de esta herramienta son:
-e permite especificar el archivo de entrada a analizar.
-s evita que se imprima la ruta completa del archivo en lenguaje de alto nivel al consultar una dirección.
-f Imprime el nombre de la función a la cual corresponde la línea del programa.Para archivos binarios que utilicen el formato ELF, podemos utilizar la herramienta readelf. La misma permite analizar toda la información adicional almacenada en el archivo, como por ejemplo la tabla de símbolos o la información de relocalización:

readelf C.o –r

Siguiente Imagen.

Esta herramienta también permite examinar el contenido de cualquier sección o encabezado del programa. Por ejemplo, podemos visualizar las características de todas las secciones, y observar el contenido de la sección de datos de solo lectura:

readelf C.o –S

Siguiente Imagen.

Clave para Opciones:

W (escribir), A (asignar), X (ejecutar), M (mezclar), S (cadenas)
I (info), L (orden enlazado), G (grupo), x (desconocido)
O (se requiere procesamiento extra del SO) o (específico del SO)
p (específico del procesador)

readelf C.o –x 5

Las principales opciones de readelf son las siguientes:
-a muestra toda la información contenida en el archivo
-h muestra la información de encabezado del archivo ELF
-S muestra la información de los encabezados de sección
-s muestra la tabla de símbolos
-r muestra la información de relocalización
-x vacía el contenido de la sección especificada

:c
Referencias
http://assembly-marcelinha.googlecode.com/files/EnsAmelia.pdf
http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html
http://www.itch.edu.mx/academic/industrial/sabaticorita/_private/07Combinaciones.htm

este ya es el codigo en ensamblador

http://pastebin.com/9zgZXtJb

y este fue el de nasm que aun no eh terminado D:

http://pastebin.com/uGmYzPYd


		

2 comentarios (+¿añadir los tuyos?)

  1. Karen Alduncin
    Abr 19, 2012 @ 12:43:58

    los codigos que pongo se ven gordos u_u

    Responder

  2. asdf
    May 16, 2012 @ 02:12:44

    En tu codigo para nasm, en la seccion bss guardaste solo 1 byte para las variables, ten en cuenta que solo podras usar hasta el numero 255.
    Esta bien la forma de sacar los argumentos, pero no necesitas hacer una interrupcion en la linea 18.
    En el sys_read no se utiliza el registro B, en el registro C se coloca el puntero de que es lo que se va a leer, en tu caso para emular un scanf ocuparas leer el STDIN.
    Te recomendaria 1 de estas 2 soluciones.
    1- recibir todos en los argumentos para evadir los sys_read.
    2- utilizar funciones externas para que puedas llamar el scanf tal cual es.

    Responder

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: