Programación en Ensamblador MSP430
Programación en Ensamblador MSP430
;************************************************************************
; MSP430F5529 - Práctica 2:
; Programación en lenguaje Ensamblador. Entradas y salidas de propósito general.
;************************************************************************
.cdecls C,LIST, "msp430.h" ; Archivo de cabecera del µC
;----------------------------------------------------------------------------------------------------
.def RESET ; Indicación para el linker de la dirección
; de inicio del programa.
;----------------------------------------------------------------------------------------------------
.text ; Inicio del programa.
Etiquetas
Una etiqueta debe ser un identificador 1 válido colocado en la columna 1.
Cada instrucción puede tener, opcionalmente, una etiqueta. Muchas
directivas también las admiten y en otras su uso será obligatorio.
Las etiquetas pueden ir seguidas de dos puntos (:). Su uso es opcional y
no formarán parte de la misma.
Cuando utilizamos una etiqueta ante una instrucción en ensamblador (o
una directiva), automáticamente esta etiqueta pasa a tener la dirección de
memoria en que se encuentra dicha instrucción.
Operación
El campo correspondiente a la operación se encuentra inmediatamente a la
derecha de la etiqueta. Este campo no puede empezar en la columna 1 o
será interpretado como una etiqueta. Podrá contener:
Mnemónicos correspondientes al lenguaje ensamblador (como ADD,
MOV, JMP, etc.)
Directivas del ensamblador (como .data, .equ, etc.)
Operandos
Son los elementos sobre los que se realiza la operación y pueden estar
constituidos por ninguno, uno o más elementos separados por comas.
Pueden estar constituidos por:
Una constante representativa de un valor numérico o una dirección.
Un nombre simbólico que represente un valor numérico o una
dirección.
Un registro
Un símbolo predefinido
El Contador de Programa
Comentarios
Los comentarios están constituidos por cualquier expresión o aclaración
que queramos incluir. Pueden contener cualquier carácter ASCII,
incluidos espacios en blanco y no afectan al proceso de ensamblado.
Una línea puede estar constituida únicamente por un comentario. Si
empieza en la columna 1 puede empezar con un punto y coma (;) o con
un asterisco (*). Si no empieza en la primera columna, entonces solo
podrá empezar con punto y coma.
1
Un identificador puede estar constituido por una cadena de caracteres alfanuméricos (A-Z, a-z, 0-9), el símbolo dolar
($) y el subguión (_). El primer carácter de un identificador no puede ser un número y no pueden contener espacios en
blanco. Se diferencian mayúsculas y minúsculas, por lo que ABC, Abc y abc serán tres identificadores distintos.
Sistemas Electrónicos Digitales Capítulo 2- 3
Capítulo 2: Programación en Lenguaje Ensamblador
2. Constantes
Una constante literal (que también podemos encontrar referidas como
literales o valores inmediatos en la literatura) es un valor que viene
expresado en el mismo formato convencional que utilizamos
habitualmente, como puede ser, por ejemplo, 12, 3.14, u “hola”.
El ensamblador soporta diferentes tipos de constantes:
Enteros binarios
Enteros octales
Enteros decimales
Enteros hexadecimales
Caracteres
Cadenas de caracteres
Números en coma flotante
2.1.5 Caracteres
Un carácter literal es un carácter único que se encuentra entre comillas
simples. Los caracteres se representan internamente mediante su
código ASCII con 8 bits. Se requieren dos comillas simples para
considerar cada comilla simple como parte de un carácter. Un carácter
consistente únicamente en dos comillas simples es válido y se le asigna
el valor 0. Por ejemplo:
‘a’ Define el carácter a y se representa internamente como 6116
‘C’ Define el carácter C y se representa internamente como 4316
‘’’’ Define el carácter ‘ y se representa internamente como 2716
‘’ Define el carácter nulo y se representa internamente como 0
3 Directivas
Las directivas se utilizan para proporcionar información al programa y
controlar el proceso de ensamblado. Nos permitirán entre otras acciones:
Ensamblar código y datos en secciones específicas.
Reservar espacio en memoria para variables.
Inicializar la memoria.
Ensamblar bloques condicionales.
Definir variables globales.
Para definir variables globales se hace uso de .global, que hace referencia
a símbolos definidos en un archivo que pueden ser vistos desde otro.
Para utilizar en ensamblador de archivos de cabecera y prototipos definidos
en C haremos uso de .cdecls
Para finalizar un programa haremos uso de .end
.bss
RAM
.data
.text
FLASH
6 Ejercicios
Escribe el programa de la Tabla 2.1 y compílalo comprobando que no tiene
errores. Inicia una sesión de Debug.
o Encuentra la ecuación que relaciona el contenido de R15 con el
número de ciclos que tarda en ejecutarse el bucle L1.
6.1 Cuestiones
Responde a las siguientes cuestiones:
¿Cuál es el valor de la frecuencia y periodo de parpadeo del diodo rojo?
Mide esta frecuencia haciendo uso del osciloscopio. El diodo rojo se
encuentra conectado en P1.0.
¿Durante cuántos ciclos de reloj está el diodo a uno y durante cuántos
a cero? Habilita el reloj en CCS para contabilizarlos.
¿Cuántos bytes de memoria ocupa el programa?
1. En las cuestiones anteriores hemos visto que si ejecutamos paso a paso el ejemplo de la
Tabla 2.1 obtenemos que el tiempo necesario para la ejecución de la instrucción dec.w
R15 es de 1 ciclo de reloj y jnz L1 de 2 ciclos. Por tanto, el retardo introducido es de 3
veces el contenido de R15. Si necesitamos que esté encendido 100.000 ciclos de reloj, el
valor que debemos colocar en R15 es, aproximadamente de 33.333. Para que esté
apagado 120.000 ciclos pondremos 40.000.
Aunque podemos asignar los valores directamente al escribir el programa, si lo hacemos
por ejemplo mediante etiquetas, los valores solo se sustituyen durante el ensamblado y
no se almacenan en memoria.
;-------------------------------------------------------------------------------
; MSP430 Assembler Code Template for use with TI Code Composer Studio
;-------------------------------------------------------------------------------
.cdecls C,LIST,"msp430.h" ; Include device header file
;-------------------------------------------------------------------------------
.def RESET ; Export program entry-point to
; make it known to linker.
;-------------------------------------------------------------------------------
.text ; Assemble into program memory.
Encendido .equ 33333 ; Número de ciclos encendido
Apagado .equ 40000 ; Número de ciclos apagado
RESET mov.w #__STACK_END,SP ; Initialize stackpointer
Sistemas Electrónicos Digitales Capítulo 2- 10
Capítulo 2: Programación en Lenguaje Ensamblador
;-------------------------------------------------------------------------------
; Main loop here
;-------------------------------------------------------------------------------
bis.b #001h,&P1DIR ; Colocamos P1.0 como salida
Loop xor.b #001h,&P1OUT ; Cambia el valor existente en P1.0
mov.w #Encendido,R15 ; Definimos retardo de encendido
L1 dec.w R15 ; Decrementamos el contador de tiempo
jnz L1 ; Retardo finalizado?
mov.w #Apagado,R15 ; Definimos retardo apagado
L2 dec.w R15 ; Decrementamos el contador de tiempo
jnz L2 ; Retardo finalizado?
jmp Loop
nop
;-------------------------------------------------------------------------------
; Stack Pointer definition
;-------------------------------------------------------------------------------
.global __STACK_END
.sect .stack
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
.sect ".reset" ; MSP430 RESET Vector
.short RESET
2. Para definir datos en memoria lo haremos utilizando la sección .data. Esta directiva
ubicará los datos indicados a partir del inicio de la RAM (en el MSP430F5529 en la
dirección 0x2400). La reserva de espacio la podemos hacer con la directiva .space y la
introducción de datos, puesto que son datos de 16 bits, con .word
;-------------------------------------------------------------------------------
.cdecls C,LIST,"msp430.h" ; Include device header file
;-------------------------------------------------------------------------------
.def RESET ; Export program entry-point to
; make it known to linker.
;-------------------------------------------------------------------------------
*La sección .data nos permite introducir datos en memoria.
.data
.space 10 ; Reservamos 10 bytes
datos .word 0xA111,0xB222,0xC333,0xD444,0xE555,0xF666,0xFFFF
;-------------------------------------------------------------------------------
.text ; Assemble into program memory.
RESET mov.w #__STACK_END,SP ; Initialize stackpointer
StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer
mov.w #datos,R10 ; Cargamos en R10 la dirección de
; inicio de los datos
mov.w #0x2420,R12 ; Cargamos en R12 la dirección para
; guardar los datos
mov.b #7,R5 ; Contador con la cantidad de datos
transf mov.w @R10,0(R12) ; Copiamos el dato
incd.w R10 ; Incrementamos dirección fuente
incd.w R12 ; Incrementamos dirección destino
dec.b R5 ; Decrementamos contador de datos
jnz transf ; hasta finalizar
jmp $ ; Salto sobre la misma dirección
nop ; (bucle infinito)
;-------------------------------------------------------------------------------
7 Problemas
;-------------------------------------------------------------------------------
; MSP430 Assembler Code Template for use with TI Code Composer Studio
;-------------------------------------------------------------------------------
.cdecls C,LIST,"msp430.h" ; Include device header file
;-------------------------------------------------------------------------------
.def RESET ; Export program entry-point to
; make it known to linker.
;-------------------------------------------------------------------------------
.data
datos .byte -95,17,-78,77,119,51,-44,122,-27,127
resultado .space 1
;-------------------------------------------------------------------------------
.text ; Assemble into program memory.
RESET mov.w #__STACK_END,SP ; Initialize stackpointer
StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer
mov #datos,R10 ; Cargamos dirección de inicio de datos
mov #10,R8 ; Cargamos cantidad de datos
xor.b R5,R5 ; Inicialicamos Registro Suma
suma add.b @R10,R5 ; Sumamos el dato siguiente
inc R10 ; Incrementamos dirección del dato
dec R8 ; Decrementamos contador de datos
jnz suma ; Y regresamos hasta finalizar
mov.b R5,&resultado ; Almacenamos resultado
jmp $
nop
;-------------------------------------------------------------------------------
; Stack Pointer definition
;-------------------------------------------------------------------------------
.global __STACK_END
.sect .stack
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
.sect ".reset" ; MSP430 RESET Vector
.short RESET
;-------------------------------------------------------------------------------
; MSP430 Assembler Code Template for use with TI Code Composer Studio
;-------------------------------------------------------------------------------
.cdecls C,LIST,"msp430.h" ; Include device header file
;-------------------------------------------------------------------------------
.def RESET ; Export program entry-point to
; make it known to linker.
.data
datos .word 0x1234,0xC234,0x6006,0x0345,0xAAAA
Resultado .space 10
;-------------------------------------------------------------------------------
.text ; Assemble into program memory.
RESET mov.w #__STACK_END,SP ; Initialize stackpointer
StopWDT mov.w #WDTPW|WDTHOLD,&WDTCTL ; Stop watchdog timer
mov.w #datos,R14 ; Registro puntero de datos
mov.w #Resultado,R13 ; Registro puntero resultados
mov.b #5,R15 ; Cantidad de datos
inicio mov @R14,R6 ; R6 Dato
mov.b R6,R7 ; R7 Byte bajo
mov R6,R8
swpb R8 ; Intercambio de bytes
tst R6 ; Comprobamos el bit 15 es 1 o 0
jn izquierda
and #7,R8 ; Cantidad de desplazamientos
jz hecho ; Si es 0 finalizamos
derecha clrc ; C=0, ya que se incluye en la rotación
rrc.b R7 ; Desplazamos R6 a la derecha las que
dec R8 ; las veces que indique R8
jnz derecha ;
jmp hecho
izquierda and #7,R8 ; O a la izquierda
jz hecho
izq2 clrc ; C=0, ya que se incluye en la rotación
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
.sect ".reset" ; MSP430 RESET Vector
.short RESET