Lenguaje Ensamblador El lenguaje ensamblador es una herramienta que facilita al programador la generación de instrucciones en lenguaje máquina. El trabajo del ensamblador es generar las secuencias de bytes deseados. Frecuentemente hay muchas formas de lograr esta tarea. Por ejemplo, dos secuencias de bytes 0x0, 0x!" pueden declararse de las siguientes formas#
Pero no todas representan expl$citamente lo que queremos que el código haga. El programador debe encargarse de que el código sea totalmente legible. E% prog progra rama mado dorr tamb tambi& i&n n pued puede e sele selecc ccio iona narr en qu& qu& tipo tipo de me memo mori ria a se almacenará el código. %as instrucciones a ser ejecutadas son almacenadas en la memoria F%'(). *alores constantes deben ser almacenados en la memoria EEP+-. El ensamblador genera dos campos con este propósito, cseg y eseg, para el almacenamiento en la memoria F%'() y EEP+- respectiamente. %as ariables son almacenadas generalmente en la (+'-. (+'-. %a (+'- tambi&n puede contener a la memoria (/'1. 2ing3n archio es generado para el contenido de la (+'- ya que estos son inde4nidos cuando el programa entra en marcha. %a iniciali5ación de la (+'- se produce en tiempo de ejecución. %a actiidad del del ensa ensamb mbla lado dorr relac elacio iona nada da con con la (+'(+'- es pura purame ment nte e para para asig asigna narr direcciones a identi4cadores. %os resultados son archiados en le map 4le as$ como en el listing 4le. El ensamblador hace un seguimiento de donde deben ser ubicados los bytes, estos pueden ser, en el segmento de código, data y EEP+-. 6irectias son usadas para decirle al ensamblador que segmento debe ser usado. Estos tres segmentos segmentos corres correspond ponden en f$sicame f$sicamente nte a tres áreas de almacena almacenamien miento to del procesador. 6ebido a la arquitectura tipo )arard de estos procesadores, las instrucciones máquinas deben ser almacenadas en la F%'(). 'unque este segmento está dise7ado para almacenar instrucciones, este puede almacenar ariables sin ning3n problema. %a 3nica diferencia es que el ensamblador los usará de forma distinta. %as instrucciones serán direccionadas con el fetched8execute cyclo, y la data data será será ca carg rgad ada a dent dentrro de regis egistr tros os.. El segm segmen ento to corr correc ecto to para para el almacenamiento de data 9alores constantes: es el EEP+-. -ientras que las ariables serán almacenadas en la (+'-, esto debido a su naturale5a olátil. 6;+E/;*'( %as dir %as direc ecti tia ass le dice dicen n al ensa ensamb mbla lado dorr cómo cómo comp compor orta tars rse. e.
Contadores de localización del ensamblador
En cada segmento de memoria un contador mantiene indicada la siguiente dirección disponible. Estos son llamados cloc, para el segmento de código= dloc, para el segmento de data= y eloc, para el segmento de data constante. El programador debe estar al tanto de estos contadores, ya que estos son usados para signar la dirección a la data e instrucciones. En la siguiente tabla podemos er algunas de las directias más usados en los procesadores '*+.
El siguiente ejemplo muestra como las directias, cseg, eseg y dseg separan y almacenan los bytes en los diferentes tipos de memoria. El ejemplo asume que las direcciones de las memorias F%'(h, (+'- y EEP+- son 0000, 00>0 y 0000, respectiamente. 2o olidar que las direcciones en la memoria F%'() direccionan a un ?+6 9@ bytes: y son almacenadas de manera inertida, mientras que las de la (+'- A EEP+- direccionan sólo a un byte.
El siguiente ejemplo no tiene alguna utilidad, pero nos serirá para entender cómo el ensamblador anali5a el programa y que acciones toma con cada sentencia.
uando el ensamblador en iniciali5ado sus tres contadores internos son iniciali5ados tambi&n. El alor inicial de cloc y eloc es 0, mientras que el alor de dloc ar$a dependiendo al microcontrolador que se está usando. ;nterpretaremos el código, asumiendo que dloc inicia con 00>0. Por defecto el segmento designado en cseg, as$ que si queremos iniciar con cualquier otro segmento, debemos indicarlo. .dseg selecciona a la (+'- como memoria de almacenamiento. El primer label, total, indica la posición actual de dloc, 00>0. 6os bytes son separadas en este segmento 00>0 y 00>B, dejando a dloc en 00>@. %a directia .cseg nos llea a la memoria F%'(). +C-P es una instrucción de B> bites, recordando que la memoria F%'() almacena ?ords 9@ bytes:, cloc ahora yace en la dirección 000B. %a siguiente sentencia, .org, cambia la locali5ación de cloc a 000@', entonces el siguiente label, startup, indica a dicha dirección, 00@'. %a siguiente instrucción, rjmp P, es transformada a lenguaje máquina y almacenada en la dirección 00@'de la memoria F%'(). .eseg selecciona la memoria EEP+-, en dónde .db separa e iniciali5a D bytes. 6espu&s, .dseg nos dirige a la memoria (+'-. En donde el label sum toma el alor del alor actual de dloc, 00>@ y el byte que se encuentra en esa misma dirección es guardado para su futuro uso. EXPRESIONES
Existen muchas tareas que haciendo en lenguaje máquina ser$an muy tediosas, assembly nos ayuda a reali5arlas, simpli4cándonos el trabajo. ' continuación mostraremos algunas de las expresiones de sintaxis usadas en el campo de operandos de muchas instrucciones y directias. El ensamblador reali5a todas las operaciones usando data de >D bites. El resultado es luego interpretado como un byte o ?ord 9u otro tama7o de data: como se necesite. Símbolos y Literales
%os s$mbolos son de4nidos cuando aparecen al inicio de una l$nea de código seguidos de dos puntos 9#: o, tambi&n pueden de4nirse, usando la directia .set o .equ. uando un s$mbolo es de4nido con dos puntos, se le conoce como label, a cada label se re4ere a un espacio de memoria.
%iterales son patrones expresados en decimal, hexadecimal, octal, o binario, string o formato de caracter. %os literales usualmente representan n3meros, aunque tambi&n pueden representar sólo patrones de bits. %os caracteres literales representan el alor num&rico de códigos '(;;. %iterales string representan un array o una cadena de caracteres. En 'ssembly un array es sólo un bloque de bytes continuos. En los procesadores '*+, los n3meros hexadecimales deben ser expresados son 0x o . %os literales binarios son indicados con el pre4jo 0b, literales octales inician con un cero. Estos literales representan un entero sin signo. 23mero que inician con un alor diferente de cero son asumidos como decimales. El s$mbolo P es usado para representar el alor actual de contador del segmento de código 9F%'(): independientemente de que segmento se encuentre actualmente actio. %os caracteres literales corresponden a un 3nico byte y son especi4cados dentro de comillas. )ay secuencias de escape usadas para representar alores de bytes especiales.
%as dos 3ltimas secuencias de escape, x9alor hexadecimal: y 9alor octal: deben ser usadas para representar un byte como un alor hexadecimal u octal. (i el alor especi4cado es demasiado grande para el byte, solamente el byte menos signi4catio es usado. 's$ G>"BH representará al byte 0x'!, y GxF6EH será simpli4cado a 0xE. )ay muy pocas ra5ones para usar estos dos formatos= siempre puedes usar el literal num&rico más conencional para especi4car alores de bytes que no corresponden a caracteres no imprimibles o que no tienen una secuencia de escape estander. Por otro lado, tal e5 quieras enfati5ar que el alor de un byte es destinado o representa un carácter en e5 de un n3mero. En este caso, I0J representa el caracter nulo, mientras 0 representa el n3mero cero.
de bytes, IaJ, IbJ, y IcJ. 'unque los caracteres literales pueden ser usados en cualquier lugar es necesario un alor num&rico, el formato string puede solamente ser usado con la directia .db. 6os strings escritos seguidos uno de otro 9sin signos de puntuación entre ellos: son simplemente cnectados. Esta conención, junto conel carácter de l$nea continua 9bacKslash al 4nal de la l$nea:, permiten que largos strings sean de4nidos en arias l$neas.
6;+E/;*'( 6E 6EF;2;;L2 6E 6'/' %os alores pueden ser ensamblados a las memorias F%'() o EEP+- usando las directias .db, .dM, .dd, y .dq seguidos por una expresión correcta. uando decimos que la data es ensamblada a F%'() o EEP+-, signi4ca que el ensamblador simplemente escribe estos bytes en los 4les 9 )EN y EEP+4les:. %a directia de de4nir bytes necesita un operador 9o lista de operadores:, cada uno representando un byte. El alor debe star entre 8B@O y @"". *alores más grande son simplemente truncados al byte menos signi4catio. 2ota que los alores por encima de B@ son posibles considerando un byte como unsigned. Puedes especi4car el alor en cualquiera de los formatos literales legales, puedes tambi&n usar expresiones más complejas. *alores Mord, doubleMord, y quadMord deben estar tambi&n en un rango apropiado, o el resultado será truncado de acuerdo al tama7o especi4cado del contenedor.
Es com3n de4nir un label en conjunto con las directias .db, .dM, .dd, .dq, y .byte. labels de4nidas de esta forma tendrán una alor igual a una dirección de byte asociada 9o primer byte de una directia multibyte:. 2o confundir el alor del label con el contenido de la locali5ación de memoria que el label representa. En lenguaje assembly, los labels siempre representan una dirección, nunca el alor almacenado en la dirección. 's$,
El label my'ge será la dirección de la palabra que contiene el n3mero "0 9cincuenta:, y el label my2ame será la dirección del byte con código '(;; para el caracter ICJ 90xD':, el primer carácter del string.
El ensamblador asignará direcciones secuencialmente cuando este par de sentencias es procesado. (i los bytes son ensamblados en la F%'(), segmento de código, entonces las direcciones son direcciones de Mords, as$ el alor de estas dos labels serán diferidos exactamente por uno. El label my2ame ser$a asociado con el ?ord conteniendo la ICJ 9y el IoJ:. (i estas sentencias aparecen en el segmento de la EEP+-, entonces las direcciones serán diferenciadas por @= my'ge será la dirección del primer byte de la palabra que contiene el alor "0 9y esta será almacenada en orden inerso:, y my2ame será la dirección del byte conteniendo ICJ. uando se ensambla data dentro del segmento de código, cada nuea directia .db de4nirá los bytes de inicio en una dirección de palabra. (i es necesario, un byte nulo 9nul: será agregado a la F%'() para obtener una dirección de palabra. Esto es llamado padding 9relleno:. El ensamblador genera un Marning cada e5 que un byte padding es agregado. 6ebido al requerimiento para el alineamiento de un ?ord, las siguientes sentencias no son equialentes#
El listing 4le contiene un reporte de todos los bytes ensamblados por el ensamblador. 6ebes habilitar la generación del listing 4le en las opciones de proyecto o no será creado cuando el proyecto sea ensamblado. /odos los bytes generados en el segmento de código son mostrados como palabras en el listing report. Aa que los Mords son almacenados en orden inerso, la secuencia de bytes aparecerá inertida. El reporte del ejemplo anterior ser$a#
(i enlistamos los > primeros bytes en direcciones de palabras, er$amos @F 00 @F , si lo enlistar$amos como Mords aparecer$a 00@F 00 @F. el formato inerso puede ser confuso, pero necesitamos usarlo. peradores
'sociado a cada operador es un niel de prioridad o precedencia. %os operadores de alta precedencia son ealuadas primero. %os par&ntesis pueden ser usados como requerimiento para for5ar un orden la ealuación de una espec$4ca operación. %as operaciones son asociadas de i5quierda a derecha 9en caso de igual precedencia:.
operación no tendrá sentido. %a substracción de dos labels ambos locali5ados en el segmento de código representa el n3mero de Mords intermedio, substrayendo dos labels ambos locali5ados en una de las otras dos memorias da el n3mero de bytes entre las direcciones. onsidere las siguientes sentencias, asumiendo que están en el segmento de código.
%a primera sentencia crea un array en código '(;;, iniciando en la dirección representada por el label letters. Puedes er que bytes son requeridos para las letras= sin embargo, un byte extra es agregado para preserar el alineamiento de ?ord. uando la expresión P S letters es calculada por el ensamblador, la diferencia es D. Esto es porque el array ocupa 9O con el padding: bytes los cuales son exactamente D Mords. %as direcciones de segmento de código son siempre direcciones de palabras cuando se asignan por el ensamblador. 's$, el byte asignado al label num%etters mantendrá el alor de D. Este alor es computado por el ensamblador. Puedes 4jar la expresión para representar el n3mero de bytes en el string escribiendo 9P8 letters:Q@. En este caso, el alor de O ser$a ensamblado en la locali5ación de memoria llamada num%etters.
unciones usadas en E!"resiones
En adición a los operados ya cubiertos, hay muchas funciones que son 3tiles para construir expresiones. %as funciones más comunes son las funciones high y loM las cuales retornan los bytes de mayor y menor orden de una expresión. %a función byte@ es un sinónimo para la función high. )ay tambi&n funciones llamadas byte, byteD, lMrd, y hMrd. %a función abs es otra función com3n, esta computa el alor absoluto de una expresión.
El uso de las expresiones serán ilustradas en los programas siguientes. 2o necesitas usar todas estas caracteriticas para escribir programas en lenguaje assembly, pero el uso efectio de ellas puede hacer que escribir programas sea más fácil y más interesante. %as expresiones tambi&n documentan como el alor es determinado, eliminando misterio y asegurando exactitud. -uchos programas en assembly hacen uso extenso del poder de las facilidades de ealuación de las expresiones del ensamblador. -ant&n en mente el hecho de que el uso de las expresiones de sentencias en assembly no hace más lento el programa 4nal. /odas las expresiones son completamente ealuadas en tiempo de ensamblaje. 2i una es ealuada por el procesador '*+. T%as instrucciones generadas por estas dos sentencias serán exactamente las mismasU ldi +B>, B ldi +B>, 9D" R !@V:W S B ;2(/+<;2E( %os programas en lenguaje assembly se componen de dos partes principales# data, de4nida como reserada, e instrucciones máquina que son ejecutadas por el procesador. %as instrucciones que son ejecutadas son códigos binarios, pero en lenguaje assembly con usualmente expresadas con una instrucción mnemonic. ada instrucción máquina es representada por al menos un nmnemonic. En algunos casos, dos diferente mnemocis representan la misma instrucción máquinam y ambas pueden ser usadas, pero en diferentes contextos una representada mejor la acción del programador. -nemonics pueden requerir operandos que permiten al ensamblador llenar los detalles requeridos por la instrucción. El propósito de cada instrucción máquina, cuando es ejecutada, es causar alg3n cambio en el estado de uno de los recursos controlados por el procesador. 2osotros ha hemos discutido el hecho de que los microcontroladores '*+ tienen @ registros de O bits y alguna cantidad de +'donde la data puede ser almacenada durante la ejecución. El procesador '*+ tiene muchas instrucciones que pueden establecer o cambiar la data en estos registros o la +'-.
*eremos el signi4cado de las siguientes instrucciones en más detalle en los siguientes cap$tulos donde ellas son agrupadas por funcionalidad. 'qu$ nosotros simplemente emos un peque7o ejemplo de sentencias comunes en assembly y sus correspondientes instrucciones máquina. o @ bits por cada instrucción y los mostrará a la salida del hex y object 4le. Puedes encontrar una completa lista de todas las instrucciones de '*+ en documentación del fabricante. Esta lista está tambi&n disponible en el men3 help de 'tmel (tudio.
uando lees un programa en lenguaje assembly, puedes notar que hay dos conenciones por de4nir labels.
%a otra es combinar la de4nición de label con otra instrucción en lenguaje assembly 9directia o instrucción mnemonic:. 2o hay diferencia alguna en el resultado. bits. ' continuación se muestran algunas de estas instrucciones.