Está en la página 1de 8

Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 1

REGISTROS

Los registros son posiciones especiales de almacenamiento, con 8 bits de capacidad. Un


registro tiene la siguiente apariencia:

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

Un registro puede almacenar valores numéricos de 0 a 255 (positivos sin signo) o entre -
128 a 127 (con bit de signo en el bit 7), caracteres ASCII o simples conjuntos de bits sin
relaciones entre ellos.

Existen 32 registros en los microprocesadores AVR, etiquetados originalmente como


R0, R1,..., R31, pero que pueden ser renombrados usando la directiva .def

.def registroTemporal=r16

Las directivas son útiles para el ensamblador pero en realidad no generan instrucciones
ejecutables. En vez de emplear el nombre r16 se puede acceder con el nombre definido
en la directiva. Así la instrucción

ldi registroTemporal, 150

carga en el r16 de manera inmediata el número 150.

Otra instrucción interesante es el de copiar datos desde un registro a otro: la instrucción


mov. El siguiente código copia el contenido del r16 al registro r20.

mov r20,r16

Obsérvese que el primer registro es siempre el registro destino de la operación.

Existen diferentes tipos de registros. Así una instrucción del tipo

ldi r15, 15

no sería válida, ya que los únicos registros que permiten cargar un valor de forma
inmediato son los registros del r16 al r31. Es decir, no se puede realizar este tipo de
operación con los registros del r0 al r15. Existe una excepción a esta regla, el comando
referido a limpiar los bits (poner todos los bits a 0)

clr r15

es válido para todos los registros.

Aparte del comando ldi, las siguientes instrucciones no pueden emplearse con los
registros r0 a r15:

andi r15,4 ;Realiza el y lógico entre el registro y un número


cbr r14,45 ;Limpia los bits en el registro determinados por una máscara de bits
cpi r13,6 ;Compara el contenido del registro con una constante

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 2

sbci r9,7 ;Resta al registro el valor del contenido de la constante y del resultado
; actual del bit de carry
sbr r12,89 ; Coloca a '1' los bits en el registro determinados por una máscara de
; bits
ser r3 ;Coloca todos los bits del registro a 1
subi r15,9 ;Resta al registro el valor del contenido de la constante.

REGISTROS PUNTERO

Un papel especial es desmpeñado por las parejas de registros r16:r27, r28:r29 y r30:r31.
Estas parejas de registros de 16 bits son nombrados de una forma especial, X, Y y Z.
Pueden acceder a direcciones de 16 bits en la SRAM (X, Y, Z) o dentro de la memoria
del programa (Z).

La parte alta de la dirección se coloca en el registro de índice más alto, mientras que la
parte baja de la dirección se almacena en el registro de índice más bajo. Estas partes alta
y baja tienen sus propios nombres. Así la parte alta del registro Z (r31) se puede acceder
como ZH mientras que la baja (r30) se puede acceder como ZL.

Ejemplo:
.EQU direccion = RAMEND ;en este comentario indicaremos que RAMEND es
;la dirección más alta en la SRAM
ldi YH,high(direccion) ; carga la parte alta de la dirección
ldi YL,low(direccion) ; carga la parte baja de la dirección

El acceso a direcciones a través de estos registros punteros es muy sencillo. Los


siguientes ejemplos ilustran estos accesos de lectura (ld) y de escritura (st) con el
puntero X

ld r1,X ; Lee de la dirección X, sin cambiar el fichero


st X+,r1 ;Escribe en la dirección X, e incrementa el puntero a la siguiente dirección
ld r1,-X ;Decrementa el puntero a la anterior dirección y lee de la dirección X

Para insertar los valores en la memoria de programa se emplean las directivas .DB y
.DW. Por ejemplo:

.DB 123,56,34,1 ; una lista de 4 bytes


.DB “Esto es un texto” ; una lista de bytes, cadena de caracteres.
.DW 13454 ; una palabra

En las definiciones es recomensable usar un número par de bytes ya que el ensamblador


añadirá un 0 al final, lo cual puede no ser deseado.

En vez de constantes se pueden definir etiquetas (destino de saltos) del siguiente modo,
siempre en la primera columna:

Etiqueta1:
; aquí irían unos comandos
Tabla:

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 3

.DW 134,12312

PUERTOS

Los puertos son puertas entre la unidad de procesamiento central hasta hardware o
software externo. La CPU se comunica con estos componentes, los lee y/o los escribe.

Los puertos tienen direcciones fijas, independientemente del microprocesador AVR.


Así, por ejemplo el puerto B se encuentra siempre en la dirección 0x18 (notación
hexadecimal). Por supuesto el programador no tiene necesidad de recordar todas estas
direcciones. Los nombres vienen definidos en un fichero de encabezado para los
diferentes tipos de microcontrolador y que son proporcionados por el fabricante. Estos
ficheros ‘include’ tienen una línea para definir la dirección del puerto B como sigue:

.EQU PORTB, 0x18

por lo que solamente se debe recordar el nombre del puerto y no su dirección. El fichero
correspondiente se incluye mediante la siguiente directiva

.include “8515def.inc”

Los puertos generalmente se organizan en conjunto de 8 bits relacionados entre sí, pero
pueden estar organizados en conjuntos sin relación. En este caso es habitual que cada
uno de los bits tenga su propio nombre y función determinados. Como ejemplo, el
registro MCUCR consiste en un número de bits de control del integrado, cada uno de
ellos con sus nombres (por ejemplo ISC00, ISC01). La forma de enviar un valor
determinado a uno de estos puertos es mediante la instrucción out y mediante el empleo
de un registro intermedio:

ldi r16, 0b00010000 ; ejemplo de configuración binaria


out MCUCR, r16

El caso contrario, el de lectura, se realiza mediante el comando in

in r16, MCUCR

En este caso debemos aclarar que existen algunos puertos que tienen bits que no son
usados o están reservados. En este caso se devuelve un bit a 0.

Es frecuente que se desee poner a 0 ó 1 un bit concreto de un puerto. Una opción para
ello consistiría en leer el registro correspondiente, emplear las operaciones lógicas para
alterar el bit seleccionado y reenviar el byte al puerto. Sin embargo, esto se puede llevar
a cabo mediante las instrucciones sbi (poner el bit a 1) y cbi (poner el bit a 0). Como
ejemplos:

.EQU bitCambiado = 5
sbi PortB, bitCambiado
cbi PortB, bitCambiado

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 4

Las dos instrucciones tienen una limitación, solamente afectan a puertos con una
dirección inferior a 0x20

PUERTOS RELEVANTES EN AVR

Componente Nombre del puerto Registro-Puerto


Acumulador SREG Registro de estado
Pila SPL/SPH Puntero de pila
SRAM externa, MCUCR Registro de Control General MCU
interrupción externa
Interupción externa GIMSK Registro de máscara de interrupción
GIFR Registro de flags de interrupción
Interrupción del TIMSK Registro de máscara de interrupción
timer del timer
TIFR Registro de flags de interrupción del
timer
Timer 0 TCCR0 Registro de control del contador 0
TCNT0 Contador 0
Timer 1 TCCR1A Registro A de control del timer
TCCR1B Registro B de control del timer
TCNT1 Contador 1
OCR1A Registro de comparación A
OCR1B Registro de comparación B
ICR1L/H Registro de captura de entrada
EEPROM EEAR Registro de direcciones EEPROM
EEDR Registro de datos EEPROM
EECR Registro de control EEPROM
UART UDR Registro de datos UART
USR Registro de estado UART
UCR Registro de control UART
UBRR Registro de baudios
Comparador ACSR Registro de control y estado del
analógico comparador analógico
Puertos de entrada y PORTx Registro de salida del puerto
salida DDRx Registro de dirección del puerto
PINx Registro de entrada del puerto

RAM ESTÁTICA, SRAM

La SRAM es una memoria que no es accesible directamente por la CPU (ALU) como es
el caso de los registros. Para acceder a esta parte de la memoria se deben emplear los
registros como paso intermedio. Por lo tanto las operaciones que involucran a la SRAM
son más lentas que la de los registros. A partir del modelo AT90S8515 se permite
conectar una RAM externa adicional.
Uno de los casos de empleo más importante de la SRAM es como pila.

El acceso a la SRAM se lleva a cabo mediante las instrucciones STS y LDS. Ejemplos

STS 0x0060, R1 ; el contenido del registro R1 se copia en la dirección 0x0060

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 5

LDS R1, 0x0060 ; el contenido de la dirección 0x0060 se copia en el registro R1

Se suelen emplear nombres simbólicos para evitar emplear direcciones fijas.

.EQU direccionMemoria = 0x0060


STS direccionMemoria, R1

SRAM como pila

El uso más común de la SRAM es como pila. La pila es como una torre de bloques.
Cada bloque que se añade se coloca en el tope de la pila, cada vez que se extrae un dato
de la pila también se saca del tope de pila. Esta estructura es llamada LIFO (last in, first
out, el último en entrar, el primero en salir).

Para emplear la SRAM como pila se necesita definir el puntero de pila. El puntero de
pila es de 16 bits, accesible como un puerto. SPH es la parte más significativa y SPL la
parte menos significativa. Para construir la pila, el puntero se carga con el valor de la
dirección más alta de la SRAM (la pila crece hacia las direcciones más bajas).

ldi r16, HIGH(RAMEND)


out SPH, r16
ldi r16, LOW(RAMEND)
out SPL, r16

El empleo de la pila es sencillo. Los contenidos de los registros pueden volcarse en la


pila de la siguiente forma

push r16

De modo análogo para extraer elementos de la pila,

pop r16

Un caso especial de uso de las pilas es el de la llamada a las subrutinas. Al llamar a la


subrutina el programa almacena en la pila la dirección de la próxima instrucción a
ejecutar

rcall rutina ;saltar a la subrutina


...
rutina:
; aquí las instrucciones de la subrutina
ret ; instrucción de retorno de la subrutina

DIRECTIVAS

.CODE
Para indicar el comienzo de un código de un programa.

.DSEG
La sección de la SRAM en el integrado (datos)

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 6

.ESEG
La sección EEPROM

.ORG
Para indicar que el segmento de código o datos comienza en una dirección distinta de la
de por defecto.

SALTOS

La ejecución de un programa es lineal. Sin embargo, las instrucciones de bifurcación


(branches) y los saltos incondicionales alteran esta ejecución lineal. Supóngase que se
desea implementar un contador de 32 bits empleando los registros r1 a r4. El bit más
significativo en r1 se incrementa en 1 (operación inc). Si el registro se desborda, el
registro tendrá el valor de 0 (255+1=0), y se tendrá que sumar 1 al r2. En caso de
desborsamiento de r2, se incrementa r3 y así sucesivamente. Para ello se emplea la
instrucción brne.

inc r1
brne sigue
inc r2
brne sigue
inc r3
brne sigue
inc r1
sigue:

Como ejemplo de instrucciones de salto condicional:

brge ; mayor o igual (con bit de signo)


brlt ; menor que (con bit de signo)

MACROS

Una macro permite la utilización repetida de secuencias de instrucciones. Por ejemplo:

.MACRO Delay
nop
nop
nop
nop
.ENDMACRO

; instrucciones
Delay
; más instrucciones

Una macro no ahorra espacio de memoria puesto que al compilar la etiqueta de la macro
es reemplazada por el conjunto de instrucciones correspondientes. Para el caso de
querer ahorrar espacio se emplean las subrutinas.

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 7

SALTOS INCONDICIONALES

Aparte del rcall para llamar a las subrutinas, existe otra clase de salto incondicional, el
rjmp: saltar directamente a la dirección deseada. Aquí, a diferencia no va a haber un
retorno (ret) a la siguiente instrucción.

Existen unas instrucciones que permiten saltarse (skip) la siguiente instrucción a


ejecutar, por ejemplo

sbrc r1,7 ;saltarse la siguiente dirección si el bit 7 del registro está a baja
rcall siBitDistinto7 ;ejecutada solamente si el bit 7 está a 0
rcall otro ;ejecutada de todas maneras

Análogamente se encuentra la instrucción sbic para los puertos de entrada/salida

sbic PINB,0 ; saltarse la siguiente instrucción si el bit 0 del puerto b está a baja

Otro tipo de instrucción de skip es la de comparación de registros

cpse r1,r2 ;saltarse la siguiente instrucción si los contenidos de r1 y r2 son


;iguales

INTERRUPCIONES

Con frecuencia se debe reaccionar ante condiciones hardware u otros eventos, por
ejemplo en el cambio de valor de un pin de un puerto (por ejemplo detectar que un
usuario ha pulsado una tecla). Un modo de procesarlo podría consistir en hacer un bucle
que leyese contínuamente el valor de esa línea. Desgraciadamente, un programa debe
hacer en general más cosas que estar leyendo en un bucle un puerto y no puede
permitirse el lujo de ese bucle. Además en caso de detección de pulsos muy pequeños,
el método del bucle es inútil. Es más adecuado emplear interrupciones.

Las interrupciones se disparan por alguna condición, que debe ser habilitada primero, ya
que todas las interrupciones hardware se encuentran deshabilitadas por defecto. El
microprocesador posee un bit en su registro de estado para permitir que se procesen las
interrupciones. Para activar/desactivar este bit se emplean las instrucciones sei y cli.

Si la condición de la interrupción se produce, el procesador coloca en la pila, la


dirección de la siguiente instrucción a ejecutar. De este modo, la ejecución del programa
puede continuar después de procesar la interrupción. Después procesa la instrucción
correspondiente en su vector de interrupción, que generalmente es un salto
incondicional a la subrutina de procesamiento de interrupción. El vector de interrupción
es una posición dependiente del procesador.

Existe un orden de prioridad en las interrupciones, de modo que si dos o más


interrupciones habilitadas se producen simultáneamente solamente será procesada la de
mayor prioridad. Las demás simplemente esperarán a que se haya procesado la de
mayor prioridad. La rutina de procesamiento puede terminar con la instrucción

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna
Guía rápida del ensamblador de los microprocesadores ATMEL-AVR 8

RETI

BIBLIOGRAFIA

Gerhard Schmidt, Beginners Introduction to the Assembly Language of ATMEL-AVR-


Microprocessors, http://www.avr-asm-tutorial.net. Diciembre de 2003.

Evelio J. González González, Grupo de Computadores y Control. Universidad de la


Laguna

También podría gustarte