martes, 25 de septiembre de 2007

Bien, este post formara parte de una serie de articulos que escribire sobre el lenguaje ensamblador en arquitectura Intel, para empezar, veremos las herramientas que necesitaremos y posteriormente empezaremos de lleno con el lenguaje mas hermoso que puede haber, que creanme una vez lo aprendes no lo dejaras nunca.

Para empezar debemos tener instalado diversas herramientas para poder programar en ensamblador, necesitaremos un sistema operativo linux, debido a que las mejores herramientas para el desarrollo de este lenguaje estan hechas para ese sistema, aunque tambien hablaremos sobre masm que es uno de los mejores assembler para sistemas windows, las herramientas principales son:

  • un assembler - as
  • un debugger - gdb
  • un linker - ld

Adicionalmente, para crear rutinas de lenguaje ensamblador para otros lenguajes de alto nivel, necesitaremos:

  • un compilador para languajes de alto nivel - gcc
  • un desamblador de codigo objeto - objdump
  • un profiler - gprof

Todas estas herramientas forman parte de un paquete de utileria de desarrollo, este paquete que lleva por nombre binutils esta instalado por defecto en la mayoria de los sistemas linux actuales

# locate binutils
locate: warning: database /var/lib/slocate/slocate.db' is
more than 8 days
old
/var/log/packages/binutils-2.15.92.0.2-i486-3
/var/log/scripts/binutils-2.15.92.0.2-i486-3
#

assembler
Esta herramienta obviamente sirve para convertir el codigo en ensamblador a instrucciones que pueda interpretar el procesador, aunque esto depende de los opcodes y las directivas del codigo, que seran explicadas en futuros post.
-masm
-nasm
-gas
-hla

debugger
Un buen programador nunca necesitara un depurador, sin embargo, mantener un buen codigo libre de errores en mas de 10 000 lineas del programa es algo dificil, y es ahi donde se necesita un buen debugger que este disponible en la caja de herramientas.

Al igual que el assembler, el depurador especifica a el sistema operativo y la plataforma de hardware como el programa esta escrito.

Los debugger proveen funciones basicas a el programador:
-ejecutan el programa en una plataforma controlada, especificando algun parametro de ejecucion
-detienen el programa en cualquier punto
-examinan los elementos de datos, localidades de memoria y registros
-cambian elementos en el programa mientras esta ejecutandose, facilita la erradicacion de bugs

linker
Si ya estas familiarizado con los lenguajes de alto nivel, es posible que tu nunca hayas utiliza un linker. Algunos lenguajes de alto nivel (lease C y C++) al ser compilados sus codigos fuentes son transformados a un ejecutable en un solo paso y en un solo comando.

El proceso de linkear objetos consiste en ir resolviendo todas las funciones definidas y definir todas las etiquetas declarads en direcciones de memoria en el codigo del programa, algunas funciones externas como el printf del lenguaje C, son definidas e incluidas con el codigo objeto.

Para trabajar automaticamente, el linker conoce las librerias comunes del codigo objeto y son localizadas en el ordenador, o las localiza si se le especifica manualmente atravez de parametros en el compilador de linea de comandos.

compiler
Si tu plan es programar en lenguaje ensamblador, un compilador para lenguajes de alto nivel no sera necesario, sin embargo, un programador profesional, esta obligado a la optimizacion de su codigo, lo cual obliga a la utilizacion de languajes de alto nivel como C o C++.

El compilador su trabajo es convertir el codigo de un lenguaje de alto nivel a codigo de instrucciones para que el procesador las ejecutes.

object code disassemblerMientras estas intentando optimizar un lenguaje de alto nivel, es usualmente necesitar ayudar, para ver como el codigo esta ejecutandose en el procesador, entonces necesitas una herramienta que te permita ver las instrucciones que han sido generadas por el compilador de los codigos fuentes de lenguajes de alto nivel.

Un programa desamblador toma un completo programa ejecutable o un archivo codigo objeto y muestra las instrucciones de codigo que seran ejecutadas por el procesador.

profiler
Si has trabajado con C o C++, tu necesitas determinar que funciones de tu programa estan demorando mas tiempo en el performance del programa total, es decir un profiler ayuda a visualizar el tiempo de ejecucion que tarda una funcion de un programa en realizar su ciclo.

Por ahora sera todas las herramientas que utilizaremos, el objetivo de este post era proveer informacion sobre las herramientas que se necesitan y sugerir al lector su instalacion para proseguir en la lectura de futuros post relaciones con este tema.

Para que no todo sea teoria, veremos un ejemplo para poner en marcha nuestras tools.

Metodo burbuja
Como bien se conoce el metodo burbuja consiste en el intercambio de los datos de un array y mantenerlos en un orden definido. En el lenguaje Java el metodo burbuja seria de la siguiente forma:


for(int i=0;i<v.length-1;i++){
if(v[i]<v[i+1]){
int aux=v[i];
v[i]=v[i+1];
v[i+1]=aux;
}
}




Mientras que en ensamblador el codigo es muy distinto:


.section .data
values:
.int 105,235,61,315,134,221,53,145,117,5
.section .text
.globl _start
_start:
movl $values, %esi
movl $9, %ecx
movl $9, %ebx
loop:
movl (%esi), %eax
cmp %eax, 4(%esi)
jge skip
xchg %eax, 4(%esi)
movl %eax, (%esi)
skip:
add $4, %esi
dec %ebx
jnz loop
dec %ecx
jz end
movl $values, %esi
movl %ecx,%ebx
jmp loopend:
movl $1, %eax
movl $0, %ebx
int $0x80

Por ahora no es importante la compresion del codigo ya que los valores y los registros seran explicados en futuros post.

Para compilar el codigo es necesario guardarlo con extension .s, es decir nos quedara un archivo buble.s y haremos el siguiente procedimiento para su compilacion:

# as -gstabs -o buble.o buble.s
# ld -o buble buble.o
# gdb -q buble
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) break *end
Breakpoint 1 at 0x80480a1: file buble.s, line 26.
(gdb) x/10d &values
0x80490b0 : 105 235 61 3150
x80490c0 : 134 221 53 1450
x80490d0 : 117 5
(gdb) run
Starting program:
/root/666/buble
Breakpoint 1, end () at buble.s:2626 movl $1, %eax
Current language: auto; currently asm
(gdb) x/10d &values
0x80490b0 : 5 53 61 105
0x80490c0 : 117 134 145 221
0x80490d0 : 235 315
(gdb)


Los parametros utilizados estan bastante bien descriptos en el manual de as, ld y gdb (man), pero lo explicare por asi acaso.
-gstabs : funciona para brindarle parametros y mas opciones para el depurador
-o : es para especificaar el nombre de salida que tendra el codigo

Los comandos de gdb, son bastante faciles de seguir:
break *end : es el punto de partida del programa
x/10d &values : especifica la salida de 10 valores en decimal del dato values
run : ejecuta el programa desde el punto de partida

En el codigo se logra ver como el ordenamiento de datos es satisfactorio, todos los registros que se usaron seran explicados en el siguientes post, pero por ahora eso es todo.

Un saludo y nos vemos en la proxima.

4 comentarios :

  1. Acido 69 dijo...

    Yo seguiré con expectativa estos post :D
    thx

  2. Anónimo dijo...

    Yo también lo seguiré, aunque no estoy en nada de acuerdo con la frase "Un buen programador nunca necesitara un depurador".

  3. AiVW dijo...

    Buena esa frase en realidad nunca es utilizada, solo es un decir, ya que los programadores perfectos no utilizan debuggers, pero los programadores perfectos no existen. =)

  4. Miguel dijo...

    Es verdad lo que ha dicho AiVW, solo es cuestion de abrirse a posibilidades en la programacion para la mejora del codigo y un debugger es la herramienta perfecta para esto.