viernes, 27 de abril de 2012

Tarea Intro. Lenguaje Ensamblador

"El lenguaje ensamblador es un lenguaje de programación de bajo nivel para los computadores, microprocesadores, microcontroladores, y otros circuitos integrados programables."


Un programa ensamblador se utiliza para traducir sentencias de lenguaje ensamblador a código máquina de un computador. El ensamblador realiza una traducción desde las sentencias mnemónicas a las instrucciones y datos de máquina.


Mnemónico es un código de operación (lenguaje de máquina) con el que es más facil la programación. Por ejemplo la instrucción MOV, que indica al microprocesador que debe mover datos de un lugar a otro. El microprocesador entiende números binarios por lo que se necesita la traducción del término mnemónico a código objeto.

Ventajas de lenguaje ensamblador
  • Velocidad
  • Eficiencia de tamaño
  • Flexibilidad
Un programa en ensamblador requiere menos memoria, así como menos tiempo de ejecución que un programa escrito en C, C++, Java, etc. 

El lenguaje ensamblador te permite realizar tareas que serían difíciles o hasta imposibles con un lenguaje de alto nivel. 

Conociendo el lenguaje ensamblador se puede entender la arquitectura de la máquina, lo cual ningún lenguaje de alto nivel proporciona. 


Desventajas de lenguaje ensamblador
  • Tiempo de programación
  • Programa fuente grande
  • Peligro de afectar recursos inesperadamente
  • Falta de portabilidad

Realicé un programa en lenguaje C que calcula el área y perímetro de ciertas figuras, utilizando un switch para elegir la figura de la que desea sacar el área y perímetro. Las figuras que puedes seleccionar son cuadrado, rectángulo y círculo. 

#include 

int main ()
{
  int opcion;
  float ladosqrt, baserect, alturarect, radio, area =0, perimetro = 0;
 

  printf("-------------------------------------------------\n");
  printf("Elige una figura: \n");
  printf("1.Cuadrado\t\t\t2.Rectangulo\n");
  printf("3.Circulo\t\t\n");
  printf("----> ");
  scanf("%d", &opcion);


  if (opcion == 1 == 2 == 3)
    {
      printf("El numero que ingresaste no es valido");
    }

  switch(opcion)
    {
    case 1:
      printf("\n\nHaz elegido cuadrado");
      printf("\nDame la medida de un lado: ");
      scanf("%f", &ladosqrt);
      area = ladosqrt*ladosqrt;
      perimetro = ladosqrt*4;
      printf("\nArea: %.2f\t\tPerimetro: %.2f\n", area, perimetro);
      break;

    case 2:
      printf("\n\nHaz elegido rectangulo");
      printf("\nDame la medida de la base: ");
      scanf("%f", &baserect);
      printf("Dame la medida de la altura: ");
      scanf("%f", &alturarect);
      area = baserect*alturarect;
      perimetro = (baserect*2)+(alturarect*2);
      printf("\nArea: %.2f\t\tPerimetro: %.2f\n", area, perimetro);
      break;

    case 3:
      printf("\n\nHaz elegido circulo");
      printf("\nDame el radio: ");
      scanf("%f", &radio);
      area = 3.1416*radio*radio;
      perimetro = 3.1416*radio*2;
      printf("\nArea: %.2f\t\tPerimetro: %.2f\n", area, perimetro);
      break;

    default:
      break;
      
    }


  return 0;
}


Para generar el código  en ensamblador  con gcc se utiliza

gcc -S area.c
Con esto se genera un archivo area.s el cual muestro a continuación. El archivo que se generó cuenta con 186 líneas de código.
 .file "area.c"
 .section .rodata
 .align 4
.LC1:
 .string "-------------------------------------------------"
.LC2:
 .string "Elige una figura: "
.LC3:
 .string "1.Cuadrado\t\t\t2.Rectangulo"
.LC4:
 .string "3.Circulo\t\t"
.LC5:
 .string "----> "
.LC6:
 .string "%d"
.LC7:
 .string "\n\nHaz elegido cuadrado"
.LC8:
 .string "\nDame la medida de un lado: "
.LC9:
 .string "%f"
.LC11:
 .string "\nArea: %.2f\t\tPerimetro: %.2f\n"
.LC12:
 .string "\n\nHaz elegido rectangulo"
.LC13:
 .string "\nDame la medida de la base: "
.LC14:
 .string "Dame la medida de la altura: "
.LC15:
 .string "\n\nHaz elegido circulo"
.LC16:
 .string "\nDame el radio: "
 .text
.globl main
 .type main, @function
main:
 pushl %ebp
 movl %esp, %ebp
 andl $-16, %esp
 subl $80, %esp
 movl $0x00000000, %eax
 movl %eax, 76(%esp)
 movl $0x00000000, %eax
 movl %eax, 72(%esp)
 movl $.LC1, (%esp)
 call puts
 movl $.LC2, (%esp)
 call puts
 movl $.LC3, (%esp)
 call puts
 movl $.LC4, (%esp)
 call puts
 movl $.LC5, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC6, %eax
 leal 68(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 movl 68(%esp), %eax
 cmpl $2, %eax
 je .L4
 cmpl $3, %eax
 je .L5
 cmpl $1, %eax
 jne .L7
.L3:
 movl $.LC7, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC8, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 64(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 flds 64(%esp)
 flds 64(%esp)
 fmulp %st, %st(1)
 fstps 76(%esp)
 flds 64(%esp)
 flds .LC10
 fmulp %st, %st(1)
 fstps 72(%esp)
 flds 72(%esp)
 flds 76(%esp)
 fxch %st(1)
 movl $.LC11, %eax
 fstpl 12(%esp)
 fstpl 4(%esp)
 movl %eax, (%esp)
 call printf
 jmp .L6
.L4:
 movl $.LC12, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC13, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 60(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 movl $.LC14, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 56(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 flds 60(%esp)
 flds 56(%esp)
 fmulp %st, %st(1)
 fstps 76(%esp)
 flds 60(%esp)
 fld %st(0)
 faddp %st, %st(1)
 flds 56(%esp)
 fadd %st(0), %st
 faddp %st, %st(1)
 fstps 72(%esp)
 flds 72(%esp)
 flds 76(%esp)
 fxch %st(1)
 movl $.LC11, %eax
 fstpl 12(%esp)
 fstpl 4(%esp)
 movl %eax, (%esp)
 call printf
 jmp .L6
.L5:
 movl $.LC15, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC16, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 52(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 flds 52(%esp)
 fldl .LC17
 fmulp %st, %st(1)
 flds 52(%esp)
 fmulp %st, %st(1)
 fstps 76(%esp)
 flds 52(%esp)
 fldl .LC17
 fmulp %st, %st(1)
 fadd %st(0), %st
 fstps 72(%esp)
 flds 72(%esp)
 flds 76(%esp)
 fxch %st(1)
 movl $.LC11, %eax
 fstpl 12(%esp)
 fstpl 4(%esp)
 movl %eax, (%esp)
 call printf
 jmp .L6
.L7:
 nop
.L6:
 movl $0, %eax
 leave
 ret
 .size main, .-main
 .section .rodata
 .align 4
.LC10:
 .long 1082130432
 .align 8
.LC17:
 .long 776530087
 .long 1074340351
 .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
 .section .note.GNU-stack,"",@progbits


Al crear el archivo en ensamblador, gcc agrega líneas de más que son innecesarias por lo cual hay que optimizar el código de manera que se eliminen esas líneas que no se necesitan para que el programa siga funcionando. Aquí esta el resultado el cual contiene 165 líneas de código. En este programa agregue comentarios para que se entienda más facilmente que es lo que hace cada comando, en las últimas líneas donde ya no agregue comentarios es por que se vuelve a hacer lo mismo que en las anteriores líneas.




.LC1:  #etiquetas
 .string "-------------------------------------------------"  #cadena
.LC2:
 .string "Elige una figura: "
.LC3:
 .string "1.Cuadrado\t\t\t2.Rectangulo"
.LC4:
 .string "3.Circulo\t\t"
.LC5:
 .string "----> "
.LC6:
 .string "%d"
.LC7:
 .string "\n\nHaz elegido cuadrado"
.LC8:
 .string "\nDame la medida de un lado: "
.LC9:
 .string "%f"
.LC11:
 .string "\nArea: %.2f\t\tPerimetro: %.2f\n"
.LC12:
 .string "\n\nHaz elegido rectangulo"
.LC13:
 .string "\nDame la medida de la base: "
.LC14:
 .string "Dame la medida de la altura: "
.LC15:
 .string "\n\nHaz elegido circulo"
.LC16:
 .string "\nDame el radio: "
.globl main
main:
 pushl %ebp            #coloca el registro en la pila
 movl %esp, %ebp       #se mueve %ebp a %esp
 subl $80, %esp        #se reserva espacio en %esp
 movl $.LC1, (%esp)    #se mueve el contenido de la pila
 movl $.LC3, (%esp)
 call puts             #se hace una llamada a la funcion puts
 movl $.LC4, (%esp)  
 call puts
 movl $.LC5, %eax
 movl %eax, (%esp)     #se mueve encima de la pila para imprimir
 call printf           #se llama a la funcion de imprimir
 movl $.LC6, %eax
 leal 68(%esp), %edx   #se actualiza el registro de %edx con la direccion de %esp
 movl %edx, 4(%esp)  
 movl %eax, (%esp)
 call __isoc99_scanf   #se hace una llamada a la funcion para recibir un valor
 movl 68(%esp), %eax
 cmpl $2, %eax         #se comparan los valores
 je .L4                #saltar a .L4 si es igual 
 cmpl $3, %eax         #se comparan los valores
 je .L5                #saltar a .L5 si es igual
 cmpl $1, %eax         #se comparan los valores
 jne .L7               #saltar a .L7 si no es igual
.L3:
 movl $.LC7, %eax      #se mueve %eax a .LC7
 movl %eax, (%esp)     #se mueve encima de la pila para imprimir
 call printf           #llamada a la funcion de imprimir
 movl $.LC8, %eax      #se mueve %eax a .LC8
 movl %eax, (%esp)     #se mueve encima de la pila para imprimir
 call printf           #llamada a la funcion para imprimir
 movl $.LC9, %eax      #se mueve %eax a .LC9
 leal 64(%esp), %edx  
 movl %edx, 4(%esp)
 movl %eax, (%esp)     #se mueve encima de la pila para recibir valor
 call __isoc99_scanf   #llamada a la funcion para recibir un valor
 flds 64(%esp)         #cargar un float de la memoria
 flds 64(%esp)         #cargar un float
 fmulp %st, %st(1)     #multiplicar valores 
 fstps 76(%esp)  
 flds 64(%esp)         #cargar un float 
 flds .LC10   
 fmulp %st, %st(1)     #multiplicar valores
 fstps 72(%esp)
 flds 72(%esp) 
 flds 76(%esp)
 fxch %st(1)           #intercambia el valor de la parte superior de la pila con una de otro registro
 movl $.LC11, %eax
 fstpl 12(%esp)        #quita el valor de la pila FPU y lo pone a mero arriba de la pila del programa usando %esp
 fstpl 4(%esp)
 movl %eax, (%esp)     #se mueve encima de la pila para imprimir
 call printf   #se hace la llamada a la funcion de imprimir
 jmp .L6   #salta a .L6 
.L4:
 movl $.LC12, %eax  
 movl %eax, (%esp)
 call printf
 movl $.LC13, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 60(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 movl $.LC14, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 56(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 flds 60(%esp)
 flds 56(%esp)
 fmulp %st, %st(1)
 fstps 76(%esp)
 flds 60(%esp)
 fld %st(0)
 faddp %st, %st(1)
 flds 56(%esp)
 fadd %st(0), %st        #se suman los valores
 faddp %st, %st(1)
 fstps 72(%esp)
 flds 72(%esp)
 flds 76(%esp)
 fxch %st(1)
 movl $.LC11, %eax
 fstpl 12(%esp)
 fstpl 4(%esp)
 movl %eax, (%esp)
 call printf
 jmp .L6
.L5:
 movl $.LC15, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC16, %eax
 movl %eax, (%esp)
 call printf
 movl $.LC9, %eax
 leal 52(%esp), %edx
 movl %edx, 4(%esp)
 movl %eax, (%esp)
 call __isoc99_scanf
 flds 52(%esp)
 fldl .LC17
 fmulp %st, %st(1)
 flds 52(%esp)
 fmulp %st, %st(1)
 fstps 76(%esp)
 flds 52(%esp)
 fldl .LC17
 fmulp %st, %st(1)
 fadd %st(0), %st
 fstps 72(%esp)
 flds 72(%esp)
 flds 76(%esp)
 fxch %st(1)
 movl $.LC11, %eax
 fstpl 12(%esp)
 fstpl 4(%esp)
 movl %eax, (%esp)
 call printf
 jmp .L6
.L7:
.L6:
 leave                  #termina
 .section .rodata 
.LC10:
 .long 1082130432
.LC17:
 .long 776530087
 .long 1074340351

Ahora se crea el archivo ejecutable con el siguiente comando:
gcc -o area.exe area.s

Después ejecutamos el archivo con el siguiente comando:
./area.exe


Y aquí esta el programa ejecutándose en terminal






Referencias:
Intel Assembler

martes, 24 de abril de 2012

Shields

Los shields son placas que sirven para controlar diferentes aparatos, adquirir datos, entre otras cosas. Éstas se colocan encima de la placa Arduino y amplian una nueva función para que sea controlada desde el Arduino.

Los Shields nos permiten utilizar el arduino para hacer cosas como reproductores de mùsica, robots, etc. Se conectan sobre la placa de arduino.

Aquì mostrarè algunos ejemplos de shields que se utilizan comunmente en el arduino:

 Sparkfun SM5100B Cellular Shield

 
Incluye todas las partes necesarias para añadir funcionalidades de mensajerìa SMS, GSM/GPRS y TCP/IP a algùn proyecto de arduino. Lo ùnico que necesitas es una tarjeta SIM y una antena. Se puede tambien implementar funciones para hacer llamadas. 

Adafruit Data logging shield for Arduino


Este dispositivo electrónico, además de ser facil de armar y de personalizar, incluye una gran variedad de documentación y librerías.
Incluye un reloj en tiempo real que ayuda a marcar la informaciòn con el tiempo, para poder saber que pasò a que hora.
Además se puede guardar información en un FAT16 o FAT32 y en una tarjeta SD.


Liquidware: Touch Shield slide 

 

Incluye una pantalla Touchscreen 320x240 OLED. Tiene capacidad para 4 imagenes de full resolution o 60 de 128x128. Permite dibujar figuras, pixeles, colores, gráficas, botones, entre otras cosas.

Wayne and Layne Video Game Shield

 Este shield permite la creación de videojuegos incluyendo gráficos, texto, efectos de sonido y música. Incluye lo que necesitas para crear juegos en blanco y negro. Soporta dos controles Nintendo Wii Nunchucks para facilitar su uso. 

Bibliografía

Arduino Shields










Arduino

Arduino es una plataforma de hardware y software abierta para la creación de prototipos. Está diseñado para facilitar una amplia gama de proyectos de electrónica.


Usualmente un Arduino  se conecta a la computadora por medio de un cable USB estándar y contiene todo lo necesario para programar la placa, sin embargo, existen otros diferentes tipos de arduino que tienen diversas maneras de conectarse, por ejemplo, el Arduino BT que funciona por medio de tecnología Bluetooth, ésto da la facilidad de programarse sin necesidad de estar físicamente conectado con algún cable.


Hardware

Actualmente existe una gran cantidad de placas arduino. La placa básica actual (Duermilanove) utiliza un microprocesador Atmel ATmega328, pero hay otros microprocesadores como el ATmega168, ATmega8, ATmega1280 (Ésta última la utiliza el Arduino Mega)

Software

El software consiste en un entorno de desarrollo que implementa el lenguaje de programación Arduino (basasdo en Wiring) y el entorno de desarrollo Arduino (basado en Processing). Los proyectos hechos con Arduino pueden ejecutarse sin necesidad de conectar a la computadora, pero se pueden conectar y después comunicar con diferentes tipos de software (p.ej. Flash, Processing, MaxMSP).

El software puede ser descargado de forma gratuita de la siguiente página


Para instalar el software de Arduino en el sistema operativo Ubuntu.

1. Descargar el .debs para arduino, arduino-core, y librxtx-java desde estas páginas:

2. Entramos a la carpeta donde instalamos el .debs

cd carpeta


3. sudo dpkg -i *deb

4. Podemos eliminar el directorio si queremos.

Si queremos instalar el software sin el "Arduino Package":

1. Descarga e instala la versión más nueva

2. Instalar el compilador (gcc-avr) y las librerias (avr-libc):


sudo apt-get install gcc-avr avr-libc 


Si queremos instalarlo en Mac OSX tenemos que seguir los siguientes pasos:


1. Descargar el software de Arduino de la siguiente pàgina:


http://arduino.googlecode.com/files/arduino-0019.dmg


2. Una vez que se descargue el software tenemos que ponerlo en la carpeta de aplicaciones


Los pasos a seguir para programar el arduino en Mac OSX son los siguientes:


1.) Conseguir un Arduino y un cable USB (Si el arduino se conecta por medio de USB)
2.) Descargar el software de arduino (Los pasos estàn mencionados en esta entrada)
3.) Instalar el software
4.) Conectar el arduino
5.) Abrir la aplicaciòn de Arduino
6.) Podemos abrir el codigo ejemplo que viene en File > Examples > 1.Basics > Blink.


7.) Seleccionamos el modelo de nuestro arduino






8.) Seleccionamos el puerto


 
9.) Programamos nuestro arduino



Cuando terminemos de subir nuestro programa al arduino se nos mostrarà el mensaje: "Done Uploading".


Bibliografìa
Arduino





jueves, 19 de abril de 2012

Mnemonics

En lenguaje ensamblador, un mnemonic es un còdigo, que normalmente consta de 1 a 5 letras y representa un código de operación.
Si programamos en lenguaje máquina proporcionando a la computadora los números de operaciones que debe realizar puede ser una gran carga, porque por cada operación que se realiza se le asigna un número, éste debe ser recordado y posteriormente buscado. 
Buscar todos los números de operaciones puede tomar mucho tiempo y consumir muchos recursos, además, si por alguna causa se llega a olvidar o perder el número puede ser desastroso.
Por este motivo se idearon los mnemotics. Cada número es representado con un código alfabético, entonces, por ejemplo, en vez de utilizar el número correpondiente a una operación de suma, podemos escribir simplemente "add".
También los mnemonics sirven para diferenciar diferentes diseños de CPU. Algunos son muy comunes, por ejemplo el de "add" que mencionamos anteriormente, o "sub" cuando se quiere restar (substract), "div" cuando se quiere dividir (divide), "mul" para multiplicar (multiply), entre otros. 
Esto puede ayudarnos a recordar los números más fácilmente sin tener que recurrir al lenguaje escrito en ensamblador y buscar los números. 

Bibliografía

Mnemonics