Shift moves all bits in a byte, word or long variable one position to the left or right.
A 0 is always shifted into the vacated bit.
The bit shifted out is discarded (not placed in the carry flag).
Multi‑byte types (Word, Long) shift correctly across all bytes using the carry flag internally.
For rotation with carry‑feedback, use Rotate instead.
Parameters
Variable — Any integer type: Byte, Word, or Long. Modified in place.
Direction —
LEFT (or L) — shift toward the MSB (equivalent to multiplying by 2).
RIGHT (or R) — shift toward the LSB (equivalent to unsigned divide by 2).
Notes
The variable is updated directly.
The shifted‑out bit is lost.
LEFT shift inserts 0 into bit 0.
RIGHT shift inserts 0 into the MSB.
Parentheses are allowed: Shift (Variable) Direction
Comma is optional: Shift Variable, Direction
Example
Dim TestByte As Byte
Dim TestWord As Word
' Byte shift left (multiply by 2)
TestByte = 1 ' 00000001
Shift TestByte, LEFT ' 00000010 result = 2
' Byte shift right (divide by 2)
TestByte = 128 ' 10000000
Shift TestByte, RIGHT ' 01000000 result = 64
' Word shift left across both bytes
TestWord = 0x0080 ' 0000 0000 1000 0000
Shift TestWord, LEFT ' 0000 0001 0000 0000 result = 256
' Word shift right across both bytes
TestWord = 0x0100 ' 0000 0001 0000 0000
Shift TestWord, RIGHT ' 0000 0000 1000 0000 result = 128
' Alternative syntax forms
Shift TestByte LEFT
Shift TestByte, LEFT
Shift ( TestByte ) LEFT
Shift ( TestByte, LEFT )
See Also
Rotate
PIC
AVR
Byte
Pre-clear carry (bcf STATUS,C) then rlf/rrf on the single byte
lsl/lsr on the single byte — carry cleared implicitly
' Test routine for SHIFT command'TestsByte,WordandLongforbothLEFTandRIGHTshifts' Results are printed via serial so connect a terminal at 9600 baud'' Expected results are shown in comments for each test#chip mega328p, 16#option explicit'Serialforoutput#define USART_BAUD_RATE 9600#define USART_TX_BLOCKING#define USART_DELAY OFF' VariablesDim TestByte As ByteDim TestWord As WordDim TestLong As LongDim PassCount As ByteDim FailCount As BytePassCount = 0FailCount = 0wait 3 sHSerPrintCRLFHSerPrint "SHIFT Command Test Suite"HSerPrintCRLFHSerPrint "========================"HSerPrintCRLF'-------------------------------------------------------' BYTE TESTS' -------------------------------------------------------HSerPrint "--- Byte Tests ---"HSerPrintCRLF'ByteLEFT:1->2TestByte=1ShiftTestByte,LEFTIfTestByte=2ThenHSerPrint"PASS: Byte LEFT 1->2 got "HSerPrintTestByteHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Byte LEFT 1->2 got "HSerPrintTestByteHSerPrintCRLFFailCount=FailCount+1EndIf' Byte LEFT: 64 -> 128TestByte = 64Shift TestByte, LEFTIf TestByte = 128 Then HSerPrint "PASS: Byte LEFT 64->128 got " HSerPrint TestByte HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Byte LEFT 64->128 got " HSerPrint TestByte HSerPrintCRLF FailCount = FailCount + 1End If'ByteLEFT:128->0(bitfallsofftheend,nocarryback)TestByte=128ShiftTestByte,LEFTIfTestByte=0ThenHSerPrint"PASS: Byte LEFT 128->0 got "HSerPrintTestByteHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Byte LEFT 128->0 got "HSerPrintTestByteHSerPrintCRLFFailCount=FailCount+1EndIf' Byte RIGHT: 128 -> 64TestByte = 128Shift TestByte, RIGHTIf TestByte = 64 Then HSerPrint "PASS: Byte RIGHT 128->64 got " HSerPrint TestByte HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Byte RIGHT 128->64 got " HSerPrint TestByte HSerPrintCRLF FailCount = FailCount + 1End If'ByteRIGHT:2->1TestByte=2ShiftTestByte,RIGHTIfTestByte=1ThenHSerPrint"PASS: Byte RIGHT 2->1 got "HSerPrintTestByteHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Byte RIGHT 2->1 got "HSerPrintTestByteHSerPrintCRLFFailCount=FailCount+1EndIf' Byte RIGHT: 1 -> 0 (bit falls off the end, no carry back)TestByte = 1Shift TestByte, RIGHTIf TestByte = 0 Then HSerPrint "PASS: Byte RIGHT 1->0 got " HSerPrint TestByte HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Byte RIGHT 1->0 got " HSerPrint TestByte HSerPrintCRLF FailCount = FailCount + 1End If'-------------------------------------------------------' WORD TESTS' -------------------------------------------------------HSerPrint "--- Word Tests ---"HSerPrintCRLF'WordLEFT:1->2TestWord=1ShiftTestWord,LEFTIfTestWord=2ThenHSerPrint"PASS: Word LEFT 1->2 got "HSerPrintTestWordHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Word LEFT 1->2 got "HSerPrintTestWordHSerPrintCRLFFailCount=FailCount+1EndIf' Word LEFT: 128 -> 256 (carry from byte 0 into byte 1)TestWord = 128Shift TestWord, LEFTIf TestWord = 256 Then HSerPrint "PASS: Word LEFT 128->256 got " HSerPrint TestWord HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Word LEFT 128->256 got " HSerPrint TestWord HSerPrintCRLF FailCount = FailCount + 1End If'WordLEFT:32768->0(MSBfallsoff,nocarryback)TestWord=32768ShiftTestWord,LEFTIfTestWord=0ThenHSerPrint"PASS: Word LEFT 32768->0 got "HSerPrintTestWordHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Word LEFT 32768->0 got "HSerPrintTestWordHSerPrintCRLFFailCount=FailCount+1EndIf' Word RIGHT: 256 -> 128 (carry from byte 1 into byte 0)TestWord = 256Shift TestWord, RIGHTIf TestWord = 128 Then HSerPrint "PASS: Word RIGHT 256->128 got " HSerPrint TestWord HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Word RIGHT 256->128 got " HSerPrint TestWord HSerPrintCRLF FailCount = FailCount + 1End If'WordRIGHT:32768->16384TestWord=32768ShiftTestWord,RIGHTIfTestWord=16384ThenHSerPrint"PASS: Word RIGHT 32768->16384 got "HSerPrintTestWordHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Word RIGHT 32768->16384 got "HSerPrintTestWordHSerPrintCRLFFailCount=FailCount+1EndIf' Word RIGHT: 1 -> 0 (LSB falls off, no carry back)TestWord = 1Shift TestWord, RIGHTIf TestWord = 0 Then HSerPrint "PASS: Word RIGHT 1->0 got " HSerPrint TestWord HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Word RIGHT 1->0 got " HSerPrint TestWord HSerPrintCRLF FailCount = FailCount + 1End If'-------------------------------------------------------' LONG TESTS' -------------------------------------------------------HSerPrint "--- Long Tests ---"HSerPrintCRLF'LongLEFT:1->2TestLong=1ShiftTestLong,LEFTIfTestLong=2ThenHSerPrint"PASS: Long LEFT 1->2 got "HSerPrintTestLongHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Long LEFT 1->2 got "HSerPrintTestLongHSerPrintCRLFFailCount=FailCount+1EndIf' Long LEFT: 128 -> 256 (carry from byte 0 into byte 1)TestLong = 128Shift TestLong, LEFTIf TestLong = 256 Then HSerPrint "PASS: Long LEFT 128->256 got " HSerPrint TestLong HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Long LEFT 128->256 got " HSerPrint TestLong HSerPrintCRLF FailCount = FailCount + 1End If'LongLEFT:32768->65536(carryfrombyte1intobyte2)TestLong=32768ShiftTestLong,LEFTIfTestLong=65536ThenHSerPrint"PASS: Long LEFT 32768->65536 got "HSerPrintTestLongHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Long LEFT 32768->65536 got "HSerPrintTestLongHSerPrintCRLFFailCount=FailCount+1EndIf' Long LEFT: 8388608 -> 16777216 (carry from byte 2 into byte 3)TestLong = 8388608Shift TestLong, LEFTIf TestLong = 16777216 Then HSerPrint "PASS: Long LEFT 8388608->16777216 got " HSerPrint TestLong HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Long LEFT 8388608->16777216 got " HSerPrint TestLong HSerPrintCRLF FailCount = FailCount + 1End If'LongRIGHT:256->128(carryfrombyte1intobyte0)TestLong=256ShiftTestLong,RIGHTIfTestLong=128ThenHSerPrint"PASS: Long RIGHT 256->128 got "HSerPrintTestLongHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Long RIGHT 256->128 got "HSerPrintTestLongHSerPrintCRLFFailCount=FailCount+1EndIf' Long RIGHT: 65536 -> 32768 (carry from byte 2 into byte 1)TestLong = 65536Shift TestLong, RIGHTIf TestLong = 32768 Then HSerPrint "PASS: Long RIGHT 65536->32768 got " HSerPrint TestLong HSerPrintCRLF PassCount = PassCount + 1Else HSerPrint "FAIL: Long RIGHT 65536->32768 got " HSerPrint TestLong HSerPrintCRLF FailCount = FailCount + 1End If'LongRIGHT:16777216->8388608(carryfrombyte3intobyte2)TestLong=16777216ShiftTestLong,RIGHTIfTestLong=8388608ThenHSerPrint"PASS: Long RIGHT 16777216->8388608 got "HSerPrintTestLongHSerPrintCRLFPassCount=PassCount+1ElseHSerPrint"FAIL: Long RIGHT 16777216->8388608 got "HSerPrintTestLongHSerPrintCRLFFailCount=FailCount+1EndIf' -------------------------------------------------------'SUMMARY' -------------------------------------------------------HSerPrintCRLFHSerPrint "========================"HSerPrintCRLFHSerPrint "PASS: "HSerPrint PassCountHSerPrintCRLFHSerPrint "FAIL: "HSerPrint FailCountHSerPrintCRLFDoLoop
Test results on real UNO.
SHIFT Command Test Suite========================
--- Byte Tests ---
PASS: Byte LEFT 1->2 got 2
PASS: Byte LEFT 64->128 got 128
PASS: Byte LEFT 128->0 got 0
PASS: Byte RIGHT 128->64 got 64
PASS: Byte RIGHT 2->1 got 1
PASS: Byte RIGHT 1->0 got 0
--- Word Tests ---
PASS: Word LEFT 1->2 got 2
PASS: Word LEFT 128->256 got 256
PASS: Word LEFT 32768->0 got 0
PASS: Word RIGHT 256->128 got 128
PASS: Word RIGHT 32768->16384 got 16384
PASS: Word RIGHT 1->0 got 0
--- Long Tests ---
PASS: Long LEFT 1->2 got 2
PASS: Long LEFT 128->256 got 256
PASS: Long LEFT 32768->65536 got 65536
PASS: Long LEFT 8388608->16777216 got 16777216
PASS: Long RIGHT 256->128 got 128
PASS: Long RIGHT 65536->32768 got 32768
PASS: Long RIGHT 16777216->8388608 got 8388608
========================
PASS: 19
FAIL: 0
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You can now consider changing the dozens, if not hundreds, of instances of "SET C OFF : ROTATE" to "SHIFT" in all the .h and library files. Casually browsing through some of them I saw many. This will improve the emitted assembler code for microcontrollers that have a native shift instruction. At least on AVRs this will make a noticeable difference.
Shifting is used in many places. Think about all the serial communication where bytes have to be shifted out and in. Think about all the multiplications and divisions by powers-of-2 that the shift will speed up.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Have a look at the change in gcbasic.bas and preprocessor. I committed. Have a go at extending.
The syntax would need to default to 1, then you need to make the decision what is fastest? or is it hybrid? Is multiple instructions faster then a repeat N - end repeat cycles? You would to analyse. One shift v two shifts v repeat n: one shift: end repeat.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You do that in GCBASIC. All the does is call fnLsL or fnLrL and this is where this started as that is not optimised code is all case ( constants are OK).
Syntax
Description
Shiftmoves all bits in a byte, word or long variable one position to the left or right.Word,Long) shift correctly across all bytes using the carry flag internally.For rotation with carry‑feedback, use Rotate instead.
Parameters
Byte,Word, orLong. Modified in place.Notes
0into bit 0.0into the MSB.Shift (Variable) DirectionShift Variable, DirectionExample
See Also
bcf STATUS,C) thenrlf/rrfon the single bytelsl/lsron the single byte — carry cleared implicitlybcf STATUS,C) thenrlf/rrfbyte 0,rlf/rrfbyte 1lsl/lsrbyte 0, thenrol/rorbyte 1bcf STATUS,C) thenrlf/rrfbyte 0, 1, 2, 3 in orderlsl/lsrbyte 0, thenrol/rorbytes 1, 2, 3 in orderrlf— rotate left through carry, byte 0 first to byte Nlslbyte 0,rolbytes 1..N — lowest byte firstrrf— rotate right through carry, byte N first to byte 0lsrbyte N,rorbytes N-1..0 — highest byte firstbcf STATUS,Cbefore the looplsl/lsrshifts a 0 into the vacated bitrlf/rrflsl/lsrfeeds into next byte viarol/rorrlf/rrfoperates on file registers directlylds SysValueCopy/ operate /stsback to memoryImpact Statement
gcbasic.bas— PreprocessorOne new
ElseIfblock added to the existing preprocessor tokenisation loop. TheROTATEblock is completely unchanged.ElseIf Left(CurrLine->Value, 6) = "SHIFT "added after the existingROTATEblockRIGHT→RandLEFT→LROTATEis untouched, no shared stategcbasic.bas— CompilerOne new sub
CompileShiftadded.CompileROTATEis completely unchanged.Sub CompileShiftadded alongside existingSub CompileROTATESHIFT VarName R/Ltoken, emits correct AVR (lsl/lsr/rol/ror) or PIC (bcf/rlf/rrf) instructions for Byte, Word and Long variablesCompileShiftadded in the same location thatCompileROTATEis called fromSummary
gcbasic.baspreprocessorgcbasic.bascompilerLast edit: Anobium 4 days ago
Test program and results.
Test results on real UNO.
Wonderful! Can't wait to test it on some of my applications. I use SHIFT often in my coding.
I can drop this into a ZIP. Would that work for you? Onedrive download again?
Changes will get longer and longer to implement... on vacation soon
Yes, zip file on Onedrive works for me.
On a PIC this is exactly the same as Clear C+rotate?
Still, very nice not having to keep nulling status C!
Yep. That is it.
You can now consider changing the dozens, if not hundreds, of instances of "SET C OFF : ROTATE" to "SHIFT" in all the .h and library files. Casually browsing through some of them I saw many. This will improve the emitted assembler code for microcontrollers that have a native shift instruction. At least on AVRs this will make a noticeable difference.
Shifting is used in many places. Think about all the serial communication where bytes have to be shifted out and in. Think about all the multiplications and divisions by powers-of-2 that the shift will speed up.
That would be a 'no'. We would have to test on real silicon across 1000's of programs.
Shift is a single command for clear and shift.
Some sensors require shifting of the raw data.
ie. adc_T = adc_T/16 ' shift to the right 4 places
the code would be :
shift adc_T, right
shift adc_T, right
shift adc_T, right
shift adc_T, right
Looks like you need a number in your command?
Sorry, Greetings Anobium!
:-)
Not able to do changes for a while.
Have a look at the change in gcbasic.bas and preprocessor. I committed. Have a go at extending.
The syntax would need to default to 1, then you need to make the decision what is fastest? or is it hybrid? Is multiple instructions faster then a repeat N - end repeat cycles? You would to analyse. One shift v two shifts v repeat n: one shift: end repeat.
In some other language:
int left = x << 2; // Shift left by 2 -> 00000100 (Decimal 20)
int right = x >> 1; // Shift right by 1 -> 00000010 (Decimal 2)
I am only giving suggestions. Not asking for change.
BW
M
Last edit: mmotte 2 days ago
You do that in GCBASIC. All the does is call fnLsL or fnLrL and this is where this started as that is not optimised code is all case ( constants are OK).
;Dim varstart = 4
ldi SysValueCopy,4
sts VARSTART,SysValueCopy
;Dim varright = varstart >> 1; // Shift right by 1 -> 00000010 (Decimal 2)
lds SYSBYTETEMPB,VARSTART
ldi SysValueCopy,1
sts NUMBITS,SysValueCopy
rcall FN_FNLSR88
lds SysValueCopy,SYSFNLSRBYTE
sts VARRIGHT,SysValueCopy
;
Dim varright = 4 >> 1
ldi SysValueCopy,2
sts VARRIGHT,SysValueCopy
;varright = varstart
lds SysValueCopy,VARSTART
sts VARRIGHT,SysValueCopy
;shift varright, right
lsr SysValueCopy
sts VARRIGHT,SysValueCopy
So, it depends what is needed.