Para los que están aprendiendo lenguaje ensamblador y quieren manejar un LCD 16x2 les traigo el siguiente código espero que les ayude para sus trabajos o proyectos.
Está implementado en el microcontrolador Atmega164P.

/*
/*
* LCD.asm
*
* Created: 30/05/2016 10:34:05
* Author: CRIS
*/
.INCLUDE "m164pdef.inc"
; ASIGNACIÓN DE ETIQUETAS A REGISTROS
.DEF AUX1 = R16 ; REGISTRO AUX1
.DEF AUX2 = R17 ; REGISTRO AUX2
.DEF AUX3 = R18 ; REGISTRO AUX3
.DSEG
BUFFER: .BYTE 10
COLUM: .BYTE 4
; SEGMENTO DE PROGRAMA o MEMORIA FLASH
.CSEG
; ASIGNACIÓN DE ETIQUETAS PARA EL MANEJO DEL DISPLAY
.EQU BUSSAL = PORTC ; BUS PARA ESCRITURA
.EQU BUSINP = PINC ; BUS PARA LECTURA
.EQU CONTROL = PORTD ; LÍNEAS DE CONTROL
.EQU ENABLE = PD7 ; HABILITACIÓN
.EQU RW = PD6 ; LEER=1 ESCRIBIR=0
.EQU RS = PD5 ; DATOS=1 COMANDO=0
; INICIALIZACIÓN DEL STACK
LDI AUX1,LOW(RAMEND)
OUT SPL,AUX1
LDI AUX1,HIGH(RAMEND)
OUT SPH,AUX1
RCALL LCDRST
ESCRIBIR:
LDI ZL,LOW(TEXT1<< 1)
LDI ZH,HIGH(TEXT1<< 1)
RCALL WRTMSJ
RJMP ESCRIBIR
; SUBRUTINA DE INICIALIZACIÓN DEL LCD CON BUS DE 8 BITS
LCDRST:
LDI AUX1,0xFF ; BUS DEL LCD COMO SALIDA
OUT DDRC,AUX1
LDI AUX1,0xE0 ; LINEAS DE CONTROL DEL LCD
OUT DDRD,AUX1
LDI ZL,LOW(TBLLCD<< 1)
LDI ZH,HIGH(TBLLCD<< 1)
LDI AUX2,5
LCDRST1:
LPM AUX1,Z+
RCALL WRTCMD
DEC AUX2
BRNE LCDRST1
RET
TBLLCD:
.DB 0x33,0x32,0x38,0x06,0x0E,0x00
; SUBRUTINA PARA ESCRIBIR UN MENSAJE EN EL LCD
WRTMSJ: LDI AUX1,0x80
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0xC0
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0x94
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0xD4
RCALL WRTCMD
RCALL WRTLIN
RET
; SUBRUTINA PARA ESCRIBIR UNA LINEA DE 20 CARACTERES
WRTLIN: LDI AUX2,20
WRTLIN1:LPM AUX1,Z+
RCALL WRTDAT
DEC AUX2
BRNE WRTLIN1
RET
; SUBRUTINA PARA ESCRIBIR UN NÚMERO DESDE EL BUFFER
WRTNUM: RCALL POSCUR
LDI XL,LOW(BUFFER)
LDI XH,HIGH(BUFFER)
CLR AUX3
WRTNUM1:LD AUX1,X+
CPI AUX1,0
BRNE WRTNUM2
CPI AUX3,0
BREQ WRTNUM3
WRTNUM2:INC AUX3
RCALL WRTDIG
WRTNUM3:CPI XL,LOW(BUFFER)+10
BRNE WRTNUM1
CPI AUX3,0
BRNE WRTNUM4
RCALL WRTDIG
WRTNUM4:RET
; SUBRUTINA PARA ESCRIBIR UN CARACTER
WRTCHR: RJMP WRTDAT
; SUBRUTINA PARA ESCRIBIR UN BYTE
WRTBYT: PUSH AUX1
SWAP AUX1
RCALL WRTDIG
POP AUX1
RCALL WRTDIG
RET
; SUBRUTINA PARA ESCRIBIR UN DIGITO
WRTDIG: ANDI AUX1,0x0F
ORI AUX1,0x30
CPI AUX1,0x3A
BRCS WRTDAT
LDI AUX2,7
ADD AUX1,AUX2
RJMP WRTDAT
; SUBRUTINA PARA MOSTRAR EL CURSOR
ONCUR: LDI AUX1,0x0E
RJMP WRTCMD
; SUBRUTINA PARA APAGAR EL CURSOR
OFFCUR: LDI AUX1,0x0C
RJMP WRTCMD
; SUBRUTINA PARA QUE PARPADEE EL CARACTER Y MOSTRAR EL CURSOR
TITCHR: LDI AUX1,0x0F
RJMP WRTCMD
; SUBRUTINA PARA QUE PARPADEE EL CARACTER
TITCUR: LDI AUX1,0x0D
RJMP WRTCMD
; SUBRUTINA PARA MOVER EL CURSOR EN 80 CARACTERES
POSCUR: CPI AUX1,20
BRCS POSCUR4
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR3
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR2
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR1
RET
POSCUR1:LDI AUX2,0xD4
RJMP POSCUR5
POSCUR2:LDI AUX2,0x94
RJMP POSCUR5
POSCUR3:LDI AUX2,0xC0
RJMP POSCUR5
POSCUR4:LDI AUX2,0x80
POSCUR5:ADD AUX1,AUX2
RJMP WRTCMD
; SUBRUTINA PARA ESCRIBIR UN COMANDO
WRTCMD: CBI CONTROL,RS
RJMP WRTDAT1
; SUBRUTINA PARA ESCRIBIR UN DATO
WRTDAT: SBI CONTROL,RS
WRTDAT1:CBI CONTROL,RW
OUT BUSSAL,AUX1
SBI CONTROL,ENABLE
CBI CONTROL,ENABLE
RCALL BUSY
RET
; SUBRUTINA QUE ESPERA MIENTRAS EL LCD ESTÁ OCUPADO
BUSY: LDI AUX1,0x00
OUT DDRC,AUX1
CBI CONTROL,RS
SBI CONTROL,RW
BUSY1: SBI CONTROL,ENABLE
NOP
IN AUX1,BUSINP
CBI CONTROL,ENABLE
SBRC AUX1,7
RJMP BUSY1
LDI AUX1,0xFF
OUT DDRC,AUX1
RET
TEXT1:
.DB "Hola "
.DB " Cristian "
.DB "Ponce "
.DB " "