Si se le llama subrutina, normalmente la mandas llamar con un "CALL" y regresas con el "RETURN", en cuanto a tu pregunta de que si se utiliza el nop, eso depende de que retardo quieres lograr, normalmente el nop se utiliza gastar tiempo, por ejemplo, si tienes un cristal de 4Mhz, cada "nop" que hagas te va a tardar 1 microsegundo en ejecutarse, supongamos si quieres hacer un retardo de 26 microsegundos, y con una rutina de decremento de un registro (DECFSZ) solo logras 25 us entoces le agregas un NOP para completar los 26 us, en pocas palabras el NOP sirve para rellenar los retardos en el caso de que requieras un retardo muy exacto.
este es un ejemplo de un retardo de 25 us, mandas llamar la subrutina "DEMORA" con un CALL y al regresar ya tienes un retardo de 25 us, recuerda que La instruccion CALL y la instruccion RETURN tambien gastan tiempo, lo puedes checar en la hoja de datos y depende de el cristal que uses, en el ejemplo se utiliza un cristal de 4 Mhz. este retardo lo generó un programa llamado "Picdel", y te ahorra el calcular todo.
DEMORA movlw . 5 ; se carga a W numero de repeticion en este caso el 5
movwf REGISTRO ; luego se mueve ese 5 a "REGISTRO"
Loop clrwdt ; se borra el watchdog (en caso de que lo tengas activado)
decfsz REGISTRO, 1 ; decrementa "REGISTRO" en 1, y se brinca si el resultado es cero
goto Loop ; si no es cero se regresa a "LOOP"
return ; Fin.
;Delay de 25 ciclos (incluyen call+return)
Bueno lo del NOP seria asi en caso de que queramos 26 us, somo solo nos faltan 1 us para completarlo, pues le agregamos una instruccion que consuma 1 us y que no nos afecte en nuestro programa, las intrucciones que sirven pueden ser: NOP, el CLRWDT, etc. Generalmente siempre se usa el NOP, bueno el codigo quedaria asi:
DEMORA movlw . 5 ; se carga a W numero de repeticion en este caso el 5
movwf REGISTRO ; luego se mueve ese 5 a "REGISTRO"
Loop clrwdt ; se borra el watchdog (en caso de que lo tengas activado)
decfsz REGISTRO, 1 ; decrementa "REGISTRO" en 1, y se brinca si el resultado es cero
goto Loop ; si no es cero se regresa a "LOOP"
nop ; el microsegundo que nos faltaba
return ; Fin.
;Delay de 26 ciclos (incluyen call+return)
Ten cuidado de no poner el nop dentro de un ciclo, pues si lo pones dentro entonces le sumaras 1us a por cada ciclo que hagas. por eso lo pongo despues del "goto Loop " , asi cuando termina el ciclo el NOP se ejecuta una solo vez.
Para verificar si efectivamente, obtienes el tiempo de retardo exacto, lo puedes simular en el MPLAB, con el Stopwatch, que esta en el boton Debugger, pero eso ya es otro tema.
Saludos.