Yo pienso que el ejemplo de aplicacion es ... raro. Pero tiene un par de puntos a considerar e interesantes.
Primero vamos a responder tu pregunta.
Cuando en una variable se opera con su valor y cuando con su dirección
Depende, si vos tenes que acceder a 1 valor, 2 valores, o multiples valores totalmente dispersos sin ninguna relacion matematica entre ellos, es mejor acceder de forma directa al registros.
Ejemplo si tuvieras un registro en la direccion 0x20, luego en 0x35 y finalmente en 0x37, es complejo de realizar UNA operacion matematica que transforme el 0x20 en 0x35, y luego el 0x35 en 0x37.
Distinto si vos tenes que trabajar con varios registros que se encuentran seguidos, suponete 0x20 ,0x21 ,0x22 ,0x23 ,0x24 ,0x25 hasta 0x39
Ahi usas el registro indirecto ( FSR) y luego le vas sumando 1 (tu operacion matematica) para recorrer facilmente todos esas posiciones de memoria.
Y aca es ... ¿cuando es que terminas? Por que si seguimos sumando de a 1, nunca vamos a parar, entonces podes hacerlo de 2 formas.
La primera es usar un contador, y cargar previamente la cantidad de direcciones de memoria, 32 en este ejemplo, Esto lo hace tu programa pero lo calcula al momento de compilarlo.
La otra es verificar cuando el FSR es igual a la ultima posicion de memoria que debo escribir, en este ejemplo para cuando FSR seas 0x39, ya no debo incrementar mas y salir o volver al inicio.
Doy otro ejemplo, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A , en ves de incrementar en 1 a FSR, esta ves lo haces de a 2, (suponete que son numeros de 16bits y tenes que pasar por estos)
---------------------------------------------------------------------------------
Luego de solucionado CUANDO es que vas a usar el acceso indirecto, vamos a hablar un poco del codigo.
CBLOCK 0x0C
RAM_Contador
ENDC
Constante EQU 2Ah ; Por ejemplo.
RAM_UltimaDireccion EQU 4Fh ; Ultima dirección de RAM de datos utilizada para
CBLOCK y EQU cumplen la misma funcion, ambos asignan a un nombre el valor de una constante, la diferencia es que CBLOCK ( bloque de constantes ) le das un valor inicial y se va incrementando desde alli. Si tuviera 1 "nombre" mas dentro del CBLOCK ese, tendria el valor 0x0D.
Como dije son CONSTANTES, por eso mismo uno puede operar moviendo ese valor constante a W, como si fuera un numero cualquiera. El compilador al compilar (valga la redundancia):
movlw RAM_UltimaDireccion-RAM_Contador ; Número de posiciones a escribir.
movwf RAM_Contador
movlw RAM_Contador+1 ; Primera posición de RAM libre.
movwf FSR ; Primera dirección de memoria RAM a escribir
Procede a reemplazar cada uno de esas constantes que definiste antes por sus valores numeros correspondientes.
movlw 0x4F - 0x0C ; Número de posiciones a escribir.
movwf 0x0C
movlw 0x0C+1 ; Primera posición de RAM libre.
movwf FSR ; Primera dirección de memoria RAM a escribir
El problema viene ahora entender que cada instruccion funciona distinto. No es lo mismo MOVLW 0x0C que MOVWF 0x0C. A pesar que tienen el mismo valor, la primera hace que W sea igual a 0x0C, pero NO SIGNIFICA que en W voy a tener el CONTENIDO de la direccion de 0x0C. Entonces vamos a hacer un paso a paso con la version ya "compilada":
movlw 0x43 ; Número de posiciones a escribir 0x4F - 0x0C = 0x43 = W.
movwf 0x0C ; Aca la direccion de 0x0C va a tener el valor 0x43
movlw 0x0C+1 ; Primera posición de RAM libre. W = 0x0D
movwf FSR ; Primera dirección de memoria RAM a escribir FSR = 0x0D
Entonces lo primero que genera es la cantidad de posiciones a escribir que es el numero 0x43, computado con las constantes definidas antes.
Luego lo guarda en RAM_Contador, ya que es necesario llevar el contador en algun registro, para saber cuantos me faltan.
Y finalmente procede a cargar el FSR con la direccion de memoria que le sigue (0x0D) a RAM_Contador ( 0x0C ).
Y esa fue tu preparacion inicial, luego vas a decrementar RAM_Contador hasta que llegue a 0, para determinar cuando necesitas parar con tu codigo (lo que vas a repetir).
Y tu codigo lo unico que hace es asignar un valor llamado Constante ( 0x2A ) a cada una de las posiciones de memoria.
PD:
Por si no lo entendiste, pensa todo lo que definis como EQU y CBLOCK como constantes, no necesariamente necesitan ser una direccion de memoria RAM valida.
Por ejemplo suponete que tenes un programa, lo voy a hacer en pseudocodigo. A pesar que lo vas a hacer otra forma a este ejemplo, quiero mostrarte que podes hacer.
Si ( estado = 0 )
-> Hago esto.
Si (estado = 1 )
-> Hago lo otro
Si ..... etc, sigue como con 5 estados.El principal punto de un codigo es que sea legible, cuando lo abras recuerdes facilmente que escribiste o hiciste, entonces estados 0,1,2,3,4 no se que es cada cosa.
Ahora supongamos que sabes que es cada cosa, y digamos que 0 es APAGADO, 1 es PRUEBA, 2 es COMUNICACION, esto por darle unos nombres. Vos podrias hacer:
CBLOCK 0x00
APAGADO ;0x00
PRUEBA ;0x01
COMUNICACION ;0x02
ENDC
Y ahora en tu programa en ves de comparar con 0x1, 0x2, vas a comparar con APAGADO, PRUEBA, etc. Que para el compilador ES LO MISMO, ya que al compilar va a reemplazar esos nombres por los valores. Pero si observas no lo usamos como posiciones de memoria en la RAM a esas constantes.
Obviamente si usas una instruccion como MOVF, MOVWF con APAGADO, vas a intentar acceder a la posicion 0x00 que es la del registro INDF