Shifting
and rotating right works same as rotating left except in opposite
direction so the bits move from high to low. The right shift command
is LSR while the rotation command is ROR.
In
the previous article we packed a playing card into a byte. We had a
bit to representing if the card was revealed, 4 bits to hold the face
value, and 2 bits to hold the suit. This would give us a packed byte
in the format 0RFFFFSS. To unpack the card byte we can do the
following
LDA
cardToUnpack
TAX
AND
#3
STA
cardSuit
TXA
LSR
LSR
TAX
AND
#15
STA
cardFace
TXA
LSR
LSR
LSR
LSR
STA
cardShowing
As
with multiplication, shifting right is the equivalent of dividing by
powers of 2. Unfortunately non-powers of two are a bit more
complicated to perform than non-power of two multiplications.
Working
with multi-byte shifting is a bit different with multiple bytes as
you start with the highest byte and work your way towards the lowest
byte using LSR on the high byte (ROR if doing a multi-byte rotation)
and using ROR for all the remaining bytes working towards the lowest
byte. Here is a two-byte example:
LDA
highByte
LSR
STA
highByte
LDA
lowByte
ROR
STA
lowByte
ROR
– ROtate
Right by one bit
Address
Mode
|
Decimal
OPCode
|
Hexadecimal
OpCode
|
Size
|
Cycles
|
Accumulator
|
106
|
$6A
|
1
|
2
|
Zero
Page
|
102
|
$66
|
2
|
5
|
Zero
Page,X
|
118
|
$76
|
2
|
6
|
Absolute
|
110
|
$6E
|
3
|
6
|
Absolute,X
|
126
|
$7E
|
3
|
7
|
Flags
affected:
CNZ
Usage:
Rotates
bits right using the carry bit to fill in the missing bit and putting
the low order bit into the carry flag. Used primarily for division by
powers of 2 and reading serial data though can be used to reposition
bits.
Test
Code:
;
ROR accumulator
CLC
LDA
#1
ROR
A
BRK
;
expect A=0, Z=1, C=1, N=0
;
ROR with memory
LDX
#1
ROR
254
ROR
254,X
ROR
256
ROR
256,X
BRK
.ORG
254
.BYTE
1 254 $EF 254
;expect
MFE=0 MFF=255 M100=$77 M101=$FF N=1, Z=0, C=0
Implementation:
//
Accumulator
state.acc
= performRightBitShift(state.acc, true)
//
Zero Page
val
address = mem.read(state.ip+1)
mem.write(address,
performRightBitShift(mem.read(address), true))
//
Zero Page, X
val
address = mem.read(state.ip+1)+state.x
mem.write(address,
performRightBitShift(mem.read(address), true))
//
Absolute
val
address = findAbsoluteAddress(state.ip)
mem.write(address,
performRightBitShift(mem.read(address), true))
//
Absolute, X
val
address = findAbsoluteAddress(state.ip)+state.x
mem.write(address,
performRightBitShift(mem.read(address), true))
LSR
– Logical
Shift Right by one bit
Address
Mode
|
Decimal
OPCode
|
Hexadecimal
OpCode
|
Size
|
Cycles
|
Accumulator
|
74
|
$4A
|
1
|
2
|
Zero
Page
|
70
|
$46
|
2
|
5
|
Zero
Page,X
|
86
|
$56
|
2
|
6
|
Absolute
|
78
|
$4E
|
3
|
6
|
Absolute,X
|
94
|
$5E
|
3
|
7
|
Flags
affected:
CNZ
Usage:
Shifts
bits right using 0 to fill in the missing bit and putting the
low order bit into the carry flag. Used primarily for single byte
division by powers of 2 and reading serial data though can be used to
reposition bits.
Test
Code:
;
LSR accumulator
LDA
#1
SEC
LSR
A
BRK
;
expect A=0, Z=1, C=1, N=0
;
LSR with memory
LDX
#1
LSR
254
LSR
254,X
LSR
256
LSR
256,X
BRK
.ORG
254
.BYTE
128 127 $EE $76
;expect
MFE=64 MFF=63 M100=$77 M101=$3B N=1, Z=0, C=0
Implementation:
//
Accumulator
state.acc
= performRightBitShift(state.acc, false)
//
Zero Page
val
address = mem.read(state.ip+1)
mem.write(address,
performRightBitShift(mem.read(address), false))
//
Zero Page, X
val
address = mem.read(state.ip+1)+state.x
mem.write(address,
performRightBitShift(mem.read(address), false))
//
Absolute
val
address = findAbsoluteAddress(state.ip)
mem.write(address,
performRightBitShift(mem.read(address), false))
//
Absolute, X
val
address = findAbsoluteAddress(state.ip)+state.x
mem.write(address,
performRightBitShift(mem.read(address), false))