^Yes.
Ok, so I see that controlling this via a LAT register is better than the PORT register, but I would like to understand more about the origins of the "read-modify-write" problem and how the LAT register is handled differently. I also gather from googling around that some PICs don't have LAT registers and this problem has to be overcome via other means. Is there some more detailed reading someone can recommend on the subject?
Thank you all for your prompt responses.
When you write bsf PORTB,4, the hardware (the actual transistor machinery that sets the pin tristates) only accepts a full byte. A bit operation to a port is like a lottery ticket with only one number penciled in, and you try to put that in the lottery ticket machine to buy your ticket. The older micros don't remember what the rest of the port is set to. So what the micro actually does with a bit instruction can be viewed as multiple distinct operations in a specific sequence.
1. READ: perform a read of PORTB. This depends on the actual physical voltage of the pin at this time. And also will automatically read as 0/lo if ANSEL is on for that pin.
So let's say that PORTB,0 is set as output high through TRISB and LATB registers. But the pin is soldered to the ground rail; so the actual read will record as lo/0. Let's say PORTB,1 is using an analog peripheral, so ANSEL is on for that pin, i.e. ANSELB contains b'00000010'. No matter if the voltage on RB1 is actually equal to Vdd (and even if LATB,1 is set to 1), the port read will automatically return a zero for RB1, because of the digital filter being turned off for that pin.
2. copy this reading into working memory, which is now XXXX XX00
3. MODIFY: set bit 4 of working memory, so it's now XXX1 XX00 ;bit 4 is the 5th order bit, 5th from the right. This is because the bits start at 0 by convention, not 1.
4. WRITE: Now we have the full lottery ticket request, with all of the digits plus the powerball. This gets fed into LATB (or PORTB, in the older micros). So now LATB will be XXX1 XX00. LATB,4 is now high. This is what you wanted. But LATB,0 and LATB,1 are also going to be set to low, if they weren't already.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;edit: example of shadow register, for a device that doesn't have a LAT register
bsf myLATBshadowregister,4 ;this is a register you defined in user data memory, yourself.
;And of course, you also initialized it, essentially the same way as a normal LAT register.
;and during this initialization, you already copied this register into PORTB, so they
;are initially synced
movf myLATBshadowregister,w ;copy it these parts you have to do inline, or in a subroutine
movwf PORTB ;into PORTB vs in the modern PIC that does this automagically.
;When you write the entire byte, it's a straight write-over operation. There's no read-modify-write.