This is the expected behaviour, and can't be avoided unfortunately! The For loop needs to use the C bit to check if it should continue looping, so it will overwrite it. The Print commands will also overwrite C. Perhaps this is something to document.
There is a workaround, though. If you replace the For loop with a Repeat loop, and take out the print, then this should work:
'Rotate a "1" through a byte
mask = 0
C=1
Repeat 8
rotate mask left
C=0
End Repeat
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
On a PIC, the second example works, but the first (rotating through a 0) doesn't. In both examples, the next at the end of the For loop compiles like this:
;next ii
movlw 8
subwf II,W,BANKED
btfss STATUS, C,ACCESS
bra SysForLoop1
SysForLoopEnd1
Any time that 8 - II is greater than or equal to 0, the subwf instruction will set C to 1. If 8 - II is negative, then C will be set to 0 to indicate that a borrow has occurred. Therefore, for every value of II that is 8 or less - so all of the values used in the For loop - C will be set to 1 and the loop will continue.
On AVR, the polarity of C is reversed. If C is 1, a borrow occurred, and if C is 0 a borrow did not occur. So on AVR, C will always be set to 0 at the end of the loop.
Edit: For comparison, this is the assembly code for Next on AVR. It affects C as well, but this isn't as obvious immediately.
;next ii
lds SysCalcTempA,II
cpi SysCalcTempA,8
brlo SysForLoop1
Last edit: Hugh Considine 2014-06-17
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It should work, but there seems to be a compiler bug that stops it from working when C is set using an assignment. I'll look into this. (The rotate command is still the most efficient way, but I can understand that there may be reasons to use a For instead!)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Rotating a "1" left through a byte doesn't work as expected. See following code:
#chip mega328p, 16
#define USART_BLOCKING
#define USART_BAUD_RATE 57600
dim mask as Byte
'Rotate a "0" through a byte
mask = 255
C=0
for ii = 1 to 8
rotate mask left
C=1
hserprint ByteToBin(mask): hserprintcrlf
next ii
'Output:
'11111110
'11111101
'11111011
'11110111
'11101111
'11011111
'10111111
'01111111
hserprintcrlf
'Rotate a "1" through a byte
mask = 0
C=1
for ii = 1 to 8
rotate mask left
C=0
hserprint ByteToBin(mask): hserprintcrlf
next ii
'Output:
'00000001
'00000011
'00000111
'00001111
'00011111
'00111111
'01111111
'11111111
Last edit: joe rocci 2014-06-16
You are correct and that's not right.
This is an error within the compiler, and, as yet, I do not venture in the compiler. We need Hugh. :-)
This is the expected behaviour, and can't be avoided unfortunately! The For loop needs to use the C bit to check if it should continue looping, so it will overwrite it. The Print commands will also overwrite C. Perhaps this is something to document.
There is a workaround, though. If you replace the For loop with a Repeat loop, and take out the print, then this should work:
But, this works ok on a Pic. Why the difference ?
On a PIC, the second example works, but the first (rotating through a 0) doesn't. In both examples, the next at the end of the For loop compiles like this:
Any time that 8 - II is greater than or equal to 0, the subwf instruction will set C to 1. If 8 - II is negative, then C will be set to 0 to indicate that a borrow has occurred. Therefore, for every value of II that is 8 or less - so all of the values used in the For loop - C will be set to 1 and the loop will continue.
On AVR, the polarity of C is reversed. If C is 1, a borrow occurred, and if C is 0 a borrow did not occur. So on AVR, C will always be set to 0 at the end of the loop.
Edit: For comparison, this is the assembly code for Next on AVR. It affects C as well, but this isn't as obvious immediately.
Last edit: Hugh Considine 2014-06-17
Would this also work?
dim cmirror as bit
mask = 0
cmirror = 1
for ii =1 to 8
c=cmirror
rotate mask left
cmirror = 0
hserprint bytetobin(mask): hserprintcrlf
next ii
It should work, but there seems to be a compiler bug that stops it from working when C is set using an assignment. I'll look into this. (The rotate command is still the most efficient way, but I can understand that there may be reasons to use a For instead!)
I assume you meant "Repeat", not "Rotate".
Yes, I discovered this problem when I coded it.
Thanks
Yes, I did mean Repeat sorry. Should learn to proof read better!
I've uploaded a new gcbasic.exe file to http://gcbasic.sourceforge.net/temp/gcbasic.exe that should fix that bug and allow C to be set as in your code.
I used the Repeat method and it wotks. Thanks for your attentiveness.