Following on from the issues with AND, here's another issue I uncovered while writing the graphical LCD code posted in Contributions.

Again, using GCB v0.9 3/2/2010 with a copy of UPDATE.ZIP dated/downloaded 5th April.

My program contains the following subroutine and once again is being compiled with a #chip 16F873A, 4 directive:

SUB GLCD_xy(xpos, ypos)
' extract and set upper (MS) 4 bits of Column Address
GLCD_gen0 = xpos
ROTATE GLCD_gen0 RIGHT SIMPLE
ROTATE GLCD_gen0 RIGHT SIMPLE
ROTATE GLCD_gen0 RIGHT SIMPLE
ROTATE GLCD_gen0 RIGHT SIMPLE
GLCD_gen0 = GLCD_gen0 AND b'00001111'
GLCD_cmd GLCD_gen0 OR b'00010000' ' b'0001xxxx' = set upper (MS) 4 bits of Column Address
GLCD_cmd xpos AND b'00001111' ' b'0000xxxx' = set lower (LS) 4 bits of Column Address
' set row address
GLCD_cmd ypos OR b'10110000' ' 0xB0 = set Page ("row") Address
EXIT SUB

But it generates the following assembler. To clarify, I've annotated with where I think the BASIC commands go that generate each part of the assembler (I wasn't aware of the /K:A compiler switch when I wrote this):

GLCD_XY
; GLCD_gen0 = xpos
    movf    XPOS,W
    movwf   GLCD_GEN0
; ROTATE GLCD_gen0 RIGHT SIMPLE  (incidentally, a BASIC command for SWAP would be really helpful here...)
    rrf GLCD_GEN0,W
    rrf GLCD_GEN0,F
; ROTATE GLCD_gen0 RIGHT SIMPLE
    rrf GLCD_GEN0,W
    rrf GLCD_GEN0,F
; ROTATE GLCD_gen0 RIGHT SIMPLE
    rrf GLCD_GEN0,W
    rrf GLCD_GEN0,F
; ROTATE GLCD_gen0 RIGHT SIMPLE
    rrf GLCD_GEN0,W
    rrf GLCD_GEN0,F
; GLCD_gen0 = GLCD_gen0 AND b'00001111'
    movlw   15
    andwf   GLCD_GEN0,F
; GLCD_cmd GLCD_gen0 OR b'00010000' ' b'0001xxxx' = set upper (MS) 4 bits of Column Address
    movlw   16
    iorwf   GLCD_GEN0,W
    movwf   BYTE
    call    GLCD_CMD
; GLCD_cmd xpos AND b'00001111' ' b'0000xxxx' = set lower (LS) 4 bits of Column Address
    clrf    BYTE
    call    GLCD_CMD
; GLCD_cmd ypos OR b'10110000' ' 0xB0 = set Page ("row") Address
    movlw   176
    iorwf   YPOS,W
    movwf   BYTE
    call    GLCD_CMD
; EXIT SUB
    return
    return

As you can see, the first call to GLCD_cmd works fine when GLCD_gen0 is ORed with b'10000' but the second call, where xpos is ANDed with b'1111' simply compiles to "clrf". The third call, where ypos is ORed with b'1011000' also works fine.

Putting brackets around the AND statement produces something closer to the correct assembler:

; GLCD_cmd (xpos AND b'00001111') ' b'0000xxxx' = set lower (LS) 4 bits of Column Address
    movlw   15
    andwf   XPOS,W
    movwf   SysTemp1
    call    GLCD_CMD

But the resulting value is placed into SysTemp1 before the call, rather than BYTE, which is incorrect.

I tried changing the BASIC into two separate statements:

GLCD_gen0 = xpos AND b'00001111' ' b'0000xxxx' = set lower (LS) 4 bits of Column Address
GLCD_cmd GLCD_gen0

And got this code:

; GLCD_gen0 = xpos AND b'00001111' ' b'0000xxxx' = set lower (LS) 4 bits of Column Address
    clrf    GLCD_GEN0
    movf    GLCD_GEN0,W
    movwf   BYTE
    call    GLCD_CMD
    movf    BYTE,W
    movwf   GLCD_GEN0

The AND statement is still generating a CLRF, this time for GLCD_GEN0, before calling GLCD_CMD

At this point, I changed the AND statement to

SET GLCD_gen0.4 OFF
SET GLCD_gen0.5 OFF
SET GLCD_gen0.6 OFF
SET GLCD_gen0.7 OFF

Which did the trick, but I am confused as to why the AND statement didn't work, especially when the OR on ypos was fine the whole way through.

Mark