Ed Edmondson wrote: > 1. I have been trying to learn assembler and have run across a > line in a program I don't understand. > > BCF OPTION_REG ^ 0X080, 7 > > What does the caret indicate? Ed: As others have said, the caret is an exclusive-or (XOR); OPTION_REG is defined to be 0x81, so OPTION_REG ^ 0x80 = 0x81 ^ 0x80 = 0x01 The REASON for performing the XOR is a little complicated: The 14-bit PIC instruction set only supports 7-bit-wide register operands -- that is, it only supports access to registers 0x00 through 0x7F -- but some of the the PIC's registers (like OPTION_REG, for instance, at 0x81) require 8-bit addresses outside that range. To deal with that situation, PIC instructions split the address into two parts: The least-significant 7 bits are stored in the instruction itself, but the most-significant bit is stored in the RP0 bit of the STATUS register. Registers in the range 0x00-0x7F are said to be in "register bank 0" and are accessed with RP0 = 0, and registers in the range 0x80-0xFF are in "register bank 1" and accessed with RP0 = 1. A few examples: To read register 0x01: 0x01 = binary 0000 0001. The most-significant bit is 0 and the least-significant 7 bits are 000 0001 (0x01), so clear RP0 to 0 and write MOVF 0x01,W. To read register 0x7F: 0x7F = binary 0111 1111. The most-significant bit is 0 and the least-significant 7 bits are 111 1111 (0x7F), so clear RP0 to 0 and write MOVF 0x7F,W. To read register 0x81: 0x81 = binary 1000 0001. The most-significant bit is 1 and the least-significant 7 bits are 000 00001 (0x01), so set RP0 to 1 and write MOVF 0x01,W. To read register 0xFF: 0xFF = binary 1111 1111. The most-significant bit is 1 and the least-significant 7 bits are 111 1111 (0x7F), so set RP0 to 1 and write MOVF 0x7F,W. As you can see, if you want to read a register number in the range 0x80-0xFF, you need to "mask off" the most-significant bit, leaving only the least-significant 7 bits for inclusion in the MOVF instruction. There are a few ways to do this. The most-obvious way is to AND the register number with 0x7F; to write to the option register, you might do this: BSF STATUS,RP0 ;Switch to bank 1. MOVWF OPTION_REG & 0x7F ;Write to the option register. BCF STATUS,RP0 ;Switch back to bank 0. This works fine, but there's another way to mask off the most-significant bit that's slightly preferable: Instead of ANDing with 0x7F, you can XOR with 0x80. To see why this is better, consider the following: BSF STATUS,RP0 ;Switch to bank 1. MOVWF OPTION_REG & 0x7F ;Write to the option register. MOVWF PORTB & 0x7F ;<-- BUG! PORTB isn't in bank 1! BCF STATUS,RP0 ;Switch back to bank 0. In this case, I forgot that PORTB is register 0x06, in bank 0, so I erroneously tried to write to it using the construction (reg & 0x7F) that I would use when writing to bank 1. Unfortunately, OPTION_REG (0x81) ANDed with 0x7F is 0x01, and PORTB (0x06) ANDed with 0x7F is still 0x06... And both 0x01 and 0x06 fit in 7 bits, so the code assembles without errors and I'll have a HELL of a time finding that bug. It'd be much better if the assembler could catch errors like this for me... And it can: If I XOR with 0x80 instead of ANDing with 0x7F, look what happens: BSF STATUS,RP0 ;Switch to bank 1. MOVWF OPTION_REG ^ 0x80 ;Write to the option register. MOVWF PORTB ^ 0x80 ;<-- BUG! PORTB isn't in bank 1! BCF STATUS,RP0 ;Switch back to bank 0. This time, OPTION_REG (0x81) XORed with 0x80 is 0x01 -- correct, and the same as in the "AND" code above -- but PORTB (0x06) XORed with 0x80 is 0x86... Which is INCORRECT, and too large to fit in 7 bits, so the assembler will generate a warning and the bug will be immediately obvious. In the code you're trying to understand, "BCF OPTION_REG ^ 0x80,7" is just clearing bit 7 of the option register; there's probably a "BSF STATUS,RP0" instruction close above that instruction, and there's probably a "BCF STATUS,RP0" close below. > 2. I have seen the ($) dollar sign used in some of the programs I have > looked at. I haven't seen any reference to this symbol in the > Microchip literature I have been reading. Read the assembler manual; it's in there. The "$" symbol refers to the address of the currently-assembled instruction: GOTO $ ;Infinite loop. is equivalent to: HERE: GOTO HERE ;Infinite loop. and: DECFSZ GOTO $-1 is equivalent (at least on the PIC you're using) to: LOOP: DECFSZ GOTO LOOP In general, it's best to use labels (as in the "HERE" and "LOOP" examples) rather than the "$" symbol, but there are rare situations -- which you're unlikely to encounter anytime soon in your own code -- in which the "$" symbol might be preferable. Good luck... -Andrew === Andrew Warren - fastfwd@ix.netcom.com -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist