Si lees bien dice que la rutina esa hace que te muestre el valor hexadecimal en el LCD
Supongamos que tenes el valor 1010 que seria 0xA o 10 en decimal, vos debes mostrar una 'A', Como harias para hacer eso ?
Puedo hacer una especie de "tabla" para guiarme:
.10 o 0xA esto me tiene que dar -> 'A' = 65 o 0x41
.11 o 0xB esto me tiene que dar -> 'B' = 66 o 0x42
.12 o 0xC esto me tiene que dar -> 'C' = 67 o 0x43
.13 o 0xD esto me tiene que dar -> 'D' = 68 o 0x44
.14 o 0xE esto me tiene que dar -> 'E' = 69 o 0x45
.15 o 0xF esto me tiene que dar -> 'F' = 70 o 0x46
Estaria bueno si usamos como base el valor de 'A' es que 0xA sume 0 a esa base, para 0xB sume 1 solo y asi, si observas es solo restarle 10 al nibble.
.0 o 0xA esto me tiene que dar -> 'A' = 65 o 0x41
.1 o 0xB esto me tiene que dar -> 'B' = 66 o 0x42
.2 o 0xC esto me tiene que dar -> 'C' = 67 o 0x43
.3 o 0xD esto me tiene que dar -> 'D' = 68 o 0x44
.4 o 0xE esto me tiene que dar -> 'E' = 69 o 0x45
.5 o 0xF esto me tiene que dar -> 'F' = 70 o 0x46
Lo bueno es que ahora yo puedo tomar la base a el valor 'A' o 65, si antes tenia un 0b1010 ( que es 10 decimal y es una A hexadecimal a representar en el LCD) y le resto 10, me queda en 0, ahora si a eso le sumo la base que es 'A' voy a obtener simplemente 'A', para el caso de 'B' quedaria 'A' + 1 lo cual me daria ese 'B'.
Esto se podria escribir en formula asi:
Nibble - 10 + 'A'
Si lo tuviera que hacer en el micro esto significa que al valor del nibble deberia restarle 10 y luego sumarle 'A' ( y hacerlo en W para no modificar nada)
MOVF Valor, W
ANDLW 0xF ;Nibble bajo
SUBLW 0xA
ADDLW 'A'
Pero la suma/resta es conmutativa, por lo cual puedo escribirlo asi ( y luego le agrego un parentesis para que se note mas):
Nibble + 'A' - 10
Nibble + ('A' - 10)
Entonces si yo al valor en hexadecimal (obviamente solo para las letras A,B,C,D,E y F) le sumo ( 'A'-10 o 'A'-0xA ) me estaria dando el valor en ASCII de esa letra. El mismo resultado que antes con una instruccion menos.
MOVF Valor, W
ANDLW 0xF ;Nibble bajo
ADDLW 'A'-0xA
Espero que hubieras logrado seguirme en el hilo de pensamiento. Y ahi tenes el por que le agrega ese 0xA.
--------------------------------------------------
El otro tema es que tenes que diferenciar entre lo que genera el compilador y las instrucciones del microcontrolador.
Cuando hacemos:
ADDLW 'A'-0xA
El compilador primero revisa todo el codigo, y detecta que 'A'-0xA lo puede hacer un solo numero, entonces procede a reemplazarlo por un solo numero, es decir a la salida del compilador o en realidad la instruccion que va a ir en el microcontrolador y que se encuentra en el .hex es:
ADDLW .55
(en realidad es un opcode que genera el compilador, pero ese opcode es la instruccion esa)
Esto por que son constantes. Pero por ejemplo vos no podrias hacer esto:
ADDLW 'A' - W
Por que el compilador no sabe que es W, el compilador lo unico que hace es checkear que no hay errores, y generar un codigo "objeto" acomodar los saltos, etc. Luego agarra el linker y lo acomoda en la memoria.
Otra cosa es que no tiene nada que ver con las instrucciones, por ejemplo puedo usar la directiva EQU y hacer:
Salida EQU 1+1
el compilador sabria que el texto "Salida" es lo mismo que 2 en el texto del codigo. Pero esta "instruccion" no va en el microcontrolador, es simplemente una directiva que posee el compilador para simplificar la vida al programador
Tambien quiero que veas que todos los ejemplos claramente apuntan que los valores usados sean valores constantes como dije, y no registros ni nada por el estilo.
Hago un ejemplo mas rapido para que veas la diferencia y en donde podes usarlo. Suponete que a un registro le tenes que sumar 10 y luego 20, podes hacerlo en 2 pasos, o simplemente sumar 30. Pero supongamos que esos 10 hacen referencia a algo antes, y esos 20 a otra cosa, entonces la idea es que lo sepa el que lee el codigo
MOVF Registro, W
ADDLW .10 ; 10 de esto
ADDLW .20 ; 20 del otro
; o hacer
MOVF Registro, W
ADDLW .30 ; 10 de una cosa y 20 de otra cosa
; o hacer
MOVF Registro, W
ADDLW .10+.20 ; 10 por xxxxx cosa, y 20 por la otra cosa, esto bla bla bla bla
Los 3 ejemplos hacen lo mismo, en el primer caso uso una instruccion mas en el microcontrolador, es decir tengo 2 ADDLW, en el 2do y 3ro pueden parecer distinto, pero luego de que pase el compilador quedan iguales, lo unico que ganas es legibilidad del codigo.