Conociendo el lenguaje ensamblador
Imagina que vives en una época donde para comunicarnos sólo existen dos palabras, “SI” y “NO”, entonces si tu dices: “SI SI SI NO SI NO SI NO” lo que tendría que interpretar la persona con la que estás hablando es: – “Hola, ¿cómo estás?”-, suena interesante, pero algo complicado, ¿no crees?,
Piensa que un día llegas a tu casa y dices: “SI NO SI NO SI SI SI SI”, pensando que lo que dijiste fue: -“Cierra la llave del gas”-, pero la otra persona lo que entendió fue: “SI NO NO NO SI SI SI SI” , lo que quiere decir: -“Enciende la estufa”-, creo que en este punto es bastante obvio que va a haber un problema grave en tu casa.
Si te das cuenta el simple hecho de haber cambiado un SI por un NO hizo que el mensaje se modificara bastante. Entonces llegó alguien y dijo: “Esto es muy complicado, vamos a crear frases”, entonces para comunicarte se crearon algunas frases ya establecidas, por ejemplo: “Hola”, “Ve a la tienda”, “Haz tu tarea”, etc., esto facilitaría demasiado la comunicación con otras personas, algo similar es lo que sucede con el lenguaje ensamblador, lo que realiza es “convertir” diferentes instrucciones a código máquina (compuesto únicamente por “1” y “0”).
Los microcontroladores utilizan un lenguaje digital, compuesto únicamente por “1” y “0”, y están llenos de registros que se pueden entender como “espacios” dentro del microcontrolador que sirven para algo en particular o que pueden utilizarse para propósitos generales.
Por ejemplo, en algún registro tendremos la información de un puerto en particular, como PORTB, con PORTB podemos escribir o leer sus valores para tener comunicación con el mundo real, existen otros registros como TRISB, el cual se utiliza para configurar si el puerto B será entrada o salida, por lo tanto es un registro de configuración.
Las instrucciones de lenguaje ensamblador van a modificar los valores de los registros para lograr crear las aplicaciones y los códigos deseados. Estas instrucciones se pueden dividir en:
- Operaciones orientadas a bytes
MOVWF TRISB ;Mueve el valor del registro W al registro TRISB
- Operaciones orientadas a bits
bsf INTCON,7 ;Pone en "1" el bit 7 del registro INTCON
- Operaciones con literales
movlw 0x00 ;Mueve el valor literal 0x00 al registro W
- Operaciones de control
goto BUCLE ;Va a la etiqueta "BUCLE"
Tanto el PIC 18F4550 (Miuva) como el 18F87J50 (Miuva Pro) cuentan con un total de 75 instrucciones. Estas instrucciones puedes encontrarlas en las hojas de datos de los PICs, por ejemplo, en la del 18F4550 puedes encontrar en la página 316 lo siguiente:
Puedes observar que la estructura de las instrucciones es similar, y tienen algunas letras (f, d, a) a un lado de la instrucción, esto quiere decir:
- f: El registro con el que se está trabajando
- d: El destino del resultador; si es 0 el resultado se guarda en el registro W, si es 1 se guarda en el registro f
- a: La memoria a la que se accesó
Similarmente está explicado en la hoja de datos para el caso de los parámetros de las instrucciones orientadas a bits, con literales o de control.
También podemos notar que muchas veces se hace mención del registro W, éste es el registro de trabajo (Work), es un registro que se utiliza como un operando para la ALU y que incluso puede almacenar el resultado, o visto de otra forma, es un registro dónde podremos guardar información temporalmente para usarla en una gran cantidad de instrucciones.
Por ejemplo para escribir un 0x00 (literal) en el registro TRISB, podemos mover el valor 0x00 al registro W y posteriormente mover lo que hay en el registro W al registro TRISB:
MOVLW 0x00 ;Movemos el 0x00 al registro de trabajo MOVWF TRISB ;Movemos el contenido de W al registro TRISB
Ahora tal vez puedas preguntarte, ¿para qué sirve el lenguaje ensamblador si puedo usar C?, a pesar de que el lenguaje C ofrece muchas ventajas, entre ellas un entendimiento más fácil y legible a la hora de programar y una menor cantidad de líneas de código, por ejemplo, para hacer parpadear un led en C:
#include <18F87J50.h> #fuses HSPLL, NOWDT, NOPROTECT, NODEBUG, PLL2 #use delay (clock=8M) void main(){ output_high(PIN_E1); delay_ms(200); output_low(PIN_E1); }
Mientras que en ensamblador son necesarias las siguientes líneas:
LIST P = 18F4550 ;PIC a utilizar INCLUDE <P18F4550.INC> CONFIG FOSC = HS CONFIG PWRT = ON CONFIG BOR = OFF CONFIG WDT = OFF CONFIG MCLRE = ON CONFIG PBADEN = OFF CONFIG LVP = OFF CONFIG DEBUG = OFF CONFIG XINST = OFF CBLOCK 0x000 Ret1 ;Variables para los retardos de 1 segundo Ret2 Ret3 ENDC ORG 0x0000 GOTO START org 0x30 START movlw 0x0F movwf ADCON1 ;Configuración de entradas digitales movlw 0x00 movwf TRISE ;Configura PUERTO E como salida movlw 0x07 movwf PORTE ;Valores iniciales del puerto E INICIO Retardo1sON movlw .255 ;Cargamos los valores de los retardos a las constantes movwf Ret1 ;correspondientes movlw .255 movwf Ret2 movlw .11 movwf Ret3 Ret1sON decfsz Ret1, F ;Decrementa el valor de Ret1 y salta si es igual a 0 bra Ret1sON ;Saltamos a Ret1sON decfsz Ret2, F ;Decremente el valor de Ret2 y salta si es igual a 0 bra Ret1sON ;Saltamos a Ret1sON decfsz Ret3, F ;Decremente el valor de Ret3 y salta si es igual a 0 bra Ret1sON ;Saltamos a Ret1sON movlw 0x06 movwf PORTE ;Encendemos el led ubicado en E0 Retardo1sOFF movlw .255 movwf Ret1 movlw .255 movwf Ret2 movlw .11 movwf Ret3 Ret1sOFF decfsz Ret1, F bra Ret1sOFF decfsz Ret2, F bra Ret1sOFF decfsz Ret3, F bra Ret1sOFF movlw 0x07 movwf PORTE ;Apaga el LED goto INICIO ;Regresa al INICIO END ;Fin de Programa
Al utilizar un lenguaje como C, estamos limitados a las funciones ya existentes del compilador, por lo cual a veces se realizarán tareas que no necesitaremos, lo cual nos hará perder tiempo o bajar el rendimiento de nuestro microcontrolador, entonces cuando necesitemos aplicaciones que requieren ser optimizadas podemos apoyarnos del lenguaje ensamblador, pero como podrás notar, para esto será necesario conocer más a fondo el funcionamiento y la estructura del microcontrolador con el cual estaremos trabajando.
Al trabajar más directamente con el hardware el lenguaje ensamblador se conoce como un lenguaje de bajo nivel mientras que C se conoce como un lenguaje de alto nivel.