2
\$\begingroup\$

I am following a tutorial on programming baseline 12F series PICs in assembler.

I have a question regarding bitwise operators specifically the << left shift operator.

Lets use an example the PIC I'm using is a 12F509 so if I wanted to set GP1 and GP0 as outputs and the rest of the I/O pins as inputs I would normally do it like this.

movlw    b'111100' ; Set GP1 and GP0 as outputs
tris     GPIO    

If I wanted to use a bitwise operator to achieve the same thing I think I could use << left shift like this.

movlw    0<<1 ; Shift 0 left once to set GP1 and GP0 as outputs
tris     GPIO

I take it after this operation the last 2 bits would be 00. Since << left shift shifts all the bits to the left discards the leftmost bit and sets the bit to the right to 0.

This is my understanding of how the bit shift left operator works. Hopefully it's correct.

Now in the tutorial this bit of code was introduced there was an explanation of what it does but not how it does it.

movlw    ~(1<<1) ; set GP1 as an output
tris     GPIO

I'm going to take a stab at what this code is doing let me know if I've got it right. It's first shifting a binary 1 left once into the GP1 position which leaves a 0 in the GP0 position.

So when the operation in the parenthesis is complete the value would look like this 000010.

Then the ~ is inverting the 1 in the GP1 position to 0 and the 0 in all of the other positions to 1? Leaving the value set to 111101 (GP1 as an output)?

Thanks In Advance.

\$\endgroup\$
  • \$\begingroup\$ From what I read, movlw 0<<1 sets the W register to be 0x00. tris GPIO then sets the GPIO TRIS register to have the value from W. So that would be all-0's, not just 0 in the lsb. So that would set all the pins on the GPIO port as outputs. \$\endgroup\$ – The Photon Oct 17 '15 at 1:37
  • \$\begingroup\$ You're right the operation is occurring in the W register. I updated the question to avoid confusion. \$\endgroup\$ – Krankshaft Oct 17 '15 at 1:47
3
\$\begingroup\$

The operand of the PIC instruction is evaluated to a constant at assembly time- the code emitted will contain a constant in that position. For example:

movlw ~(1<<1) ; set GP1 as an output

1 << 1 is evaluated as b'00000010' (b'00000001' left-shifted by 1 - it is understood that a 0 is shifted in)

The the complement is applied (all 8 bits are flipped), so you get

b'11111101'

and the code emitted is

movlw b'11111101'

It's the same as directly writing the above except you might find it more readable to write it in the way shown.

\$\endgroup\$
  • \$\begingroup\$ Thank you that's what I thought. For some reason I confused myself into thinking that I was working with the values in the tris register directly. So it's similar to using math to derive a value the assembler does the math and puts the result in the final code? For example movlw .500000 / (.1023+.1023+.3). After assembly it would be movlw .244. \$\endgroup\$ – Krankshaft Oct 17 '15 at 2:01
  • \$\begingroup\$ Yes, exactly. The value is pre- processed. \$\endgroup\$ – Spehro Pefhany Oct 17 '15 at 6:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.