Ensamblador para PIC18
El ensamblador traduce instrucciones legibles por humanos a codigo maquina (bytes en la Flash del PIC). En el curso UNEXPO se trabaja con MPASM dentro de MPLAB v8: escribes un archivo .ASM, compilas y obtienes un .HEX que grabas en el microcontrolador.
Esta pagina cierra el bloque de Fundamentos junto con Arquitectura, Registros y Bits y hexadecimal. Ya sabes que son WREG, los SFR y las mascaras; aqui aprendes como escribir el programa linea por linea.
Flujo del programa — de .ASM al PIC
Sección titulada «Flujo del programa — de .ASM al PIC» Tu codigo (.ASM) ↓ MPASM (ensamblador) Archivo .HEX ↓ Programador / MPLAB Flash del PIC18F4550 → el chip ejecuta instruccionesMas adelante en MPLAB y Proteus veras el entorno completo. Los config bits y la palabra de configuracion van en el mismo .ASM pero se graban en una zona especial de configuracion, no como codigo ejecutable normal.
Anatomia de un archivo MPASM — estilo “sandwich”
Sección titulada «Anatomia de un archivo MPASM — estilo “sandwich”»En el curso UNEXPO el profesor pide ordenar el .ASM como un sandwich, parecido a int main() en C:
| Capa | Que va | Analogia en C |
|---|---|---|
| Arriba | Cabecera, CONFIG, variables (CBLOCK) | #include, defines, variables globales |
| Medio | Subrutinas (CALL / RETURN) | Funciones auxiliares |
| Abajo | Programa principal | main() |
| Final | END | Fin del archivo |
Solo al inicio va el vector de reset (ORG 0x0000 / 0000H + GOTO programa): es la unica excepcion — el hardware arranca en 0000H y debe saltar al main que esta al final.
; ══ ARRIBA — cabecera, config, variables ══════════════ LIST P=18F4550 #include <P18F4550.INC>
CONFIG FOSC = HS CONFIG WDT = OFF CONFIG LVP = OFF
CBLOCK 0x20contador RES 1
; ── Vector de reset (salta al main al final) ────────── ORG 0x0000 GOTO programa
; ══ MEDIO — subrutinas ═══════════════════════════════config_puertos: BCF TRISB, 0 ; RB0 salida RETURN
encender_led: BSF LATB, 0 ; RB0 en alto RETURN
; ══ ABAJO — programa principal (como main) ════════════programa: CALL config_puertos CALL encender_ledbucle: GOTO bucle ; bucle infinito
ENDDirectivas que debes conocer
Sección titulada «Directivas que debes conocer»| Directiva | Funcion |
|---|---|
LIST P=18F4550 | Indica el micro al ensamblador |
#include <P18F4550.INC> | Importa nombres de registros y bits |
CONFIG … | Palabra de configuracion (oscilador, WDT…) |
ORG addr | Fija la direccion en Flash donde empieza el codigo |
CBLOCK / RES | Reserva bytes en RAM para variables GPR |
END | Marca el final del archivo |
Etiquetas y comentarios
Sección titulada «Etiquetas y comentarios»- Etiqueta (
inicio:,bucle:): nombre de una posicion en Flash; destino deGOTOoCALL. No es un numero — MPASM la convierte en direccion al compilar. - Comentario (
; texto): ignorado por MPASM — documenta tu codigo.
Que es un literal
Sección titulada «Que es un literal»Un literal es un valor fijo escrito en la linea de codigo. No es el nombre de un registro (LATB, contador) ni una etiqueta (programa:): es el numero concreto que quieres usar.
Piensalo como una constante en C: el valor que ya decidiste y escribes tal cual, no algo que lees de una variable en RAM. Si en C pondrias resultado = 10;, en ensamblador escribes MOVLW D'10' — ese 10 es el literal (tu constante en esa linea).
En el manual MPASM aparece como k cuando la instruccion lleva un valor embebido:
| Manual | Tu codigo | Que significa |
|---|---|---|
MOVLW k | MOVLW D'10' | Carga el literal 10 en WREG |
ANDLW k | ANDLW 0xF0 | AND entre WREG y el literal 0xF0 |
ADDLW k | ADDLW B'00000001' | Suma el literal 1 a WREG |
El ensamblador traduce ese literal a bytes dentro de la instruccion en Flash. El PIC no “busca” un literal en RAM: el valor viaja dentro del opcode.
Notaciones MPASM para literales
Sección titulada «Notaciones MPASM para literales»MPASM exige prefijos para dejar clara la base del numero. El mismo valor puede escribirse de varias formas:
| Notacion | Ejemplo en .ASM | Mismo valor (informe) | Base |
|---|---|---|---|
| Decimal | D'200' | 200 | 10 |
| Binario | B'11110000' | 240 | 2 |
Hex (0x) | 0xF0 | F0H | 16 |
| Hex (sufijo h) | 0F0h | F0H | 16 en MPASM |
Reglas utiles al escribir literales:
- Decimal: siempre
D'numero'con comillas —D'10',D'255'. - Binario:
B'01010101'— util para mascaras (ver Bits y hexadecimal). - Hex en
.ASM:0xF0o0F0h(MPASM acepta ambos; a veces se escribe0FFhpara no confundir con etiqueta). - Rango de un byte: un literal de 8 bits va de 0 a 255 (
0x00…0xFF). Si te pasas, MPASM avisa al compilar.
Ejemplos en instrucciones reales:
MOVLW D'10' ; WREG = 10 (decimal)MOVLW 0xF0 ; WREG = 240 = F0HMOVLW B'00000001' ; WREG = mascara solo bit 0ANDLW 0x0F ; WREG = WREG AND 0FH (filtra nibble bajo)BSF LATB, 0 ; el 0 tambien es literal: numero de bitPara convertir entre decimal, binario y hex (tablas, mascaras, 0x vs FFH), usa Bits y hexadecimal. Aqui el foco es como escribir el valor dentro del .ASM.
Literales en directivas (direcciones)
Sección titulada «Literales en directivas (direcciones)»Las directivas no se ejecutan en el PIC; le dicen a MPASM donde o cuanto reservar. Tambien llevan literales numericos:
| Directiva | Ejemplo | Que literal indica |
|---|---|---|
ORG | ORG 0x0000 | Direccion en Flash (0000H = vector de reset) |
CBLOCK | CBLOCK 0x20 | Direccion inicial en RAM para variables (20H) |
LIST | LIST P=18F4550 | Aqui el “literal” es el nombre del micro (simbolo, no numero) |
ORG 0x0000 ; codigo empieza en 0000H CBLOCK 0x20 ; variables desde 20H en RAMcontador RES 1 ; RES 1 = reserva 1 byte (otro tipo de literal)Misma idea de notacion: 0x0000 = 0000H; 0x20 = 20H. Ver equivalencias en Bits y hexadecimal — notaciones hex.
La letra f en las instrucciones — que es y como se usa
Sección titulada «La letra f en las instrucciones — que es y como se usa»Antes de los sufijos ,W y ,F, conviene entender una convencion de los manuales MPASM que aparece en casi todas las instrucciones.
Paso 1 — Como se ven las instrucciones en el manual
Sección titulada «Paso 1 — Como se ven las instrucciones en el manual»En la documentacion, las instrucciones no traen nombres concretos como LATB o contador. Traen la letra f como hueco que tu llenas:
| Instruccion en el manual | Que dice en palabras |
|---|---|
MOVF f, W | Copia el contenido del registro f hacia WREG |
MOVWF f | Copia WREG hacia el registro f |
INCF f, F | Suma 1 al registro f y deja el resultado en f |
BSF f, b | Pone el bit b del registro f en 1 |
CLRF f | Pone el registro f en cero |
La f del manual significa: “aqui va el registro de archivo que tu quieras usar”. En ingles se llama file register (registro de archivo): cualquier byte de la RAM de datos.
Paso 2 — Reemplazas f por el registro que necesitas
Sección titulada «Paso 2 — Reemplazas f por el registro que necesitas»Cuando programas, sustituyes f por el registro concreto que quieres leer, escribir o modificar:
| Manual (generico) | Tu codigo (concreto) | Que hace |
|---|---|---|
MOVF f, W | MOVF LATB, W | Copia LATB → WREG |
MOVF f, W | MOVF contador, W | Copia contador → WREG |
MOVWF f | MOVWF LATB | Copia WREG → LATB |
INCF f, F | INCF contador, F | contador = contador + 1 |
En la linea MOVF LATB, W, el manual habria escrito MOVF f, W. En ese ejemplo, f y LATB son lo mismo: el unico registro que participa (ademas de WREG) es LATB. No hay otro registro oculto llamado F.
; Manual: MOVF f, W; Tu codigo: MOVF LATB, W; └─┬──┘; └── aqui va lo que el manual llama "f"Lo mismo con una variable tuya:
; Manual: INCF f, F; Tu codigo: INCF contador, F; └────┬────┘; └── "f" = contador en este programaPaso 3 — Que registros pueden ser f
Sección titulada «Paso 3 — Que registros pueden ser f»Cualquier byte de la RAM de datos puede ocupar el lugar de f. Hay dos familias (ver Registros y Arquitectura):
Si reemplazas f por… | Tipo | Ejemplo de uso |
|---|---|---|
TRISB, LATB, PORTB, INTCON… | SFR | Controlar hardware del PIC |
contador, temp (con RES) | GPR | Guardar datos de tu programa |
LATB y contador son registros de archivo porque pueden ser la f de una instruccion. La diferencia entre SFR y GPR es para que sirve ese byte, no el hecho de llamarse “archivo”.
Paso 4 — No confundir f con el sufijo ,F
Sección titulada «Paso 4 — No confundir f con el sufijo ,F»En una misma linea pueden aparecer dos cosas distintas con la letra F:
| Simbolo | Que es | Ejemplo |
|---|---|---|
f (minuscula, del manual) | Que registro usas — lo reemplazas por LATB, contador… | MOVF LATB, W |
,F (sufijo al final) | Donde queda el resultado — en ese mismo registro (no en WREG) | INCF contador,F |
,W (sufijo) | Donde queda el resultado — en WREG | MOVF LATB,W |
Ejemplo completo desglosado:
MOVF LATB, W; └─┬─┘ └┬┘; f destino = WREG (sufijo ,W); en codigo real, f = LATBINCF contador, F; └───┬───┘ └┬┘; f destino = el mismo registro (sufijo ,F); en codigo real, f = contadorLa seccion siguiente detalla ,W vs ,F con mas ejemplos de instrucciones.
Destino de la operacion — ,W vs ,F
Sección titulada «Destino de la operacion — ,W vs ,F»Con la seccion anterior clara: en MOVF LATB, W, f del manual = LATB en tu codigo; el sufijo ,W indica que el resultado va a WREG.
Muchas instrucciones tienen dos formas de destino:
; f = contador; destino ,W → resultado en WREGMOVF contador, W ; WREG = contador (contador no cambia)
; f = LATB; destino ,WMOVF LATB, W ; WREG = LATB
; f = contador; destino ,F → resultado en el mismo registroINCF contador, F ; contador = contador + 1Regla mental: ,W → resultado en WREG; ,F → resultado en el mismo registro que reemplaza f (LATB, contador…).
Instrucciones basicas — movimiento de datos
Sección titulada «Instrucciones basicas — movimiento de datos»| Instruccion | Que hace | Ejemplo |
|---|---|---|
MOVLW k | Carga literal k en WREG | MOVLW D'10' |
MOVWF f | Copia WREG → registro f | MOVWF LATB |
MOVF f,d | Copia registro f → d (,W o ,F) | MOVF PORTB, W |
CLRF f | Pone registro f en 0 | CLRF contador |
CLRW | Pone WREG en 0 | CLRW |
Patron tipico — cargar y guardar:
MOVLW D'55' ; WREG = 55MOVWF contador ; contador = 55Instrucciones aritmeticas
Sección titulada «Instrucciones aritmeticas»| Instruccion | Operacion | Actualiza STATUS |
|---|---|---|
ADDLW k | WREG = WREG + k | Si (Z, C, DC, OV, N) |
ADDWF f,d | WREG + f → d | Si |
SUBLW k | WREG = k − WREG | Si |
SUBWF f,d | f − WREG → d | Si |
INCF f,d | f + 1 → d | Si (Z, N…) |
DECF f,d | f − 1 → d | Si |
DECFSZ f,d | Decrementa; si queda 0, salta la siguiente instruccion | Si |
Ejemplo — contador con bucle de N iteraciones:
MOVLW D'10'MOVWF contadorbucle: ; ... trabajo ... DECFSZ contador, F ; contador--; si llega a 0, salta GOTO GOTO bucle ; aqui termina el bucleTras sumas y restas revisa las banderas de STATUS: Z (¿cero?), C (¿acarreo?), N (signo).
Instrucciones logicas
Sección titulada «Instrucciones logicas»| Instruccion | Operacion |
|---|---|
ANDLW k / ANDWF f,d | AND bit a bit |
IORLW k / IORWF f,d | OR bit a bit |
XORLW k / XORWF f,d | XOR bit a bit |
COMF f,d | Complemento (NOT) de f |
Detalle y mascaras en Bits y hexadecimal. La Practica 1 exige rutinas con estas operaciones.
Instrucciones de bit — un pin sin tocar el resto
Sección titulada «Instrucciones de bit — un pin sin tocar el resto»| Instruccion | Efecto |
|---|---|
BSF f,b | Bit b de f → 1 |
BCF f,b | Bit b de f → 0 |
BTFSS f,b | Salta la siguiente linea si bit = 1 |
BTFSC f,b | Salta la siguiente linea si bit = 0 |
; Leer boton en RB3 (entrada)BSF TRISB, 3 ; RB3 entradaBTFSS PORTB, 3 ; ¿RB3 = 1?GOTO boton_suelto ; si RB3 = 1 → salta al destino; ... codigo si boton presionado (RB3 = 0) ...boton_suelto: ; continua si el boton esta suelto (RB3 = 1)Saltos, subrutinas y la pila
Sección titulada «Saltos, subrutinas y la pila»| Instruccion | Funcion |
|---|---|
GOTO etiqueta | Salto incondicional — PC va a la etiqueta |
CALL sub | Llama subrutina — guarda retorno en la pila |
RETURN | Vuelve del CALL — restaura PC desde la pila |
RETFIE | Return from interrupt (ISR) |
; ── subrutina (medio del sandwich) ──retardo_1s: ; ... bucle que consume tiempo ... RETURN
; ── programa principal (abajo, como main) ──programa: CALL retardo_1s ; va a retardo_1s; guarda direccion de retorno BSF LATB, 0 ; al volver, enciende LED GOTO programaLa pila es LIFO: el ultimo CALL es el primero en volver con RETURN. En Arquitectura — PC esta explicado con mas detalle.
Comparar y decidir — saltos condicionales
Sección titulada «Comparar y decidir — saltos condicionales»El PIC18 no tiene instruccion CMP. Comparas operando y leyendo STATUS:
; ¿contador == 0?MOVLW D'0'XORWF contador, W ; si iguales → W=0 → Z=1BTFSS STATUS, Z ; salta si Z=1 (contador era 0)GOTO no_es_cero ; si no era 0 → salta al destino; contador == 0 ...GOTO fin_cerono_es_cero: ; contador != 0 ...fin_cero:
; ¿RB0 encendido?BTFSS LATB, 0 ; salta si bit 0 de LATB = 1GOTO led_apagado ; si RB0 = 0 → salta al destino; LED encendido (RB0 = 1) ...GOTO fin_ledled_apagado: ; LED apagado (RB0 = 0) ...fin_led:| Instruccion | Salta si… |
|---|---|
BTFSS STATUS, Z | Resultado fue cero (Z=1) |
BTFSC STATUS, Z | Resultado no fue cero (Z=0) |
BTFSS STATUS, C | Hubo acarreo (C=1) |
Ejemplo completo — LED en RB0
Sección titulada «Ejemplo completo — LED en RB0»Traduce “enciende un LED en RB0” a pasos concretos usando Registros GPIO:
LIST P=18F4550 #include <P18F4550.INC> CONFIG FOSC = HS, WDT = OFF, LVP = OFF
ORG 0x0000 GOTO programa
; ── (sin subrutinas en este ejemplo minimo) ──
programa: BCF TRISB, 0 ; 1) RB0 como salida BSF LATB, 0 ; 2) RB0 en alto → LED ONbucle: GOTO bucle ; 3) bucle (programa no termina)
ENDEn ensamblador no dices “enciende un LED”. Dices: configura direccion del pin, escribe el latch, manten el programa corriendo.
Ejercicio · Parcial
Traza este fragmento
MOVLW D'3'MOVWF contadorINCF contador, FDECFSZ contador, FGOTO $-1contadorqueda en 3, luegoINCF→ 4.DECFSZdecrementa: 3 — no es cero → no salta.GOTO $-1vuelve alDECFSZ.- Repite hasta que
contador= 0 →DECFSZsalta elGOTOy el bucle termina.
$-1 es la instruccion anterior (etiqueta implicita de MPASM).
Errores comunes
Sección titulada «Errores comunes»- Olvidar
END: MPASM puede dar error o generar codigo incompleto. MOVLWvsMOVWF:MOVLWcarga en WREG;MOVWFguarda WREG en un registro — no son intercambiables.- Escribir salidas en
PORTx: usaLATxpara salidas; lee entradas conPORTx. - Confundir
BTFSSyBTFSC: uno salta si el bit es 1, el otro si es 0 — revisa el cableado del boton. - No incluir
P18F4550.INC: sin el include,TRISByLATBno existen como simbolos. - Etiqueta sin dos puntos (
programaen vez deprograma:): el ensamblador no reconoce el destino del salto. - Programa principal arriba y subrutinas abajo: en UNEXPO va al reves —
programa:al final, subrutinas en el medio (estilo sandwich /mainal final).
Preguntas tipo parcial
Sección titulada «Preguntas tipo parcial»¿Que significa la f en MOVWF f del manual MPASM?
Es un comodin: el manual no sabe que registro usaras. Tu escribes MOVWF LATB o MOVWF contador — f se convierte en ese nombre. En MOVF LATB, W, f y LATB son lo mismo.
¿Que es un literal en MPASM?
Un valor fijo escrito en la linea (D'10', 0xF0, B'10000000') — como una constante en C — que el ensamblador incrusta en la instruccion. No es un registro (contador) ni una etiqueta (bucle:).
¿Que hace MOVLW D'5' seguido de MOVWF contador?
Carga 5 en WREG y lo copia a la variable GPR contador.
¿Para que sirve ORG 0x0000 (0000H)?
Indica que el codigo empieza en la direccion 0000H de la memoria de programa (vector de reset).
¿Que diferencia hay entre GOTO y CALL?
GOTO salta sin guardar retorno. CALL salta a una subrutina y apila la direccion para volver con RETURN.
¿Que hace DECFSZ contador, F?
Decrementa contador; si el resultado es 0, no ejecuta la instruccion siguiente (util para bucles).
Ensamblador MPASM
Basado en: instrucciones pic.pdf
0 de 0 respondidas
Inicia sesion en CALETAS para sincronizar este resultado entre dispositivos.
Iniciar sesion en CALETAS