Bitwise operations: Difference between revisions
Content added Content deleted
Puppydrum64 (talk | contribs) |
Puppydrum64 (talk | contribs) (→{{header|68000 Assembly}}: also revised 6502 example) |
||
Line 136: | Line 136: | ||
</pre> |
</pre> |
||
=={{header|6502 Assembly}}== |
=={{header|6502 Assembly}}== |
||
Bitwise operations are done using the accumulator and an immediate constant (prefixed with #) or a value at a specified memory location (no #.) |
|||
Integer one is in the accumulator, integer two is in zero page memory location "temp". Both are considered to be unsigned. |
|||
<lang 6502asm>AND temp ;ANDs accumulator with temp. |
|||
<lang 6502asm>LDA #$05 |
|||
OR temp ;ORs accumulator with temp. |
|||
STA temp ;temp equals 5 for the following</lang> |
|||
;AND |
|||
EOR temp ;XORs accumulator with temp. |
|||
<lang 6502asm>LDA #$08 |
|||
AND temp</lang> |
|||
;OR |
|||
EOR #$FF ;bitwise NOT on the accumulator.</lang> |
|||
<lang 6502asm>LDA #$08 |
|||
ORA temp</lang> |
|||
;XOR |
|||
The 6502 can only shift left or right by one. Shifting by a variable number requires a loop. |
|||
<lang 6502asm>LDA #$08 |
|||
There is also no arithmetic shift right on the 6502, only logical. It can also be replicated with a few commands. |
|||
EOR temp</lang> |
|||
;NOT |
|||
<lang 6502asm>multi_ASL: |
|||
<lang 6502asm>LDA #$08 |
|||
LDX temp |
|||
EOR 255</lang> |
|||
CPX #$08 |
|||
BNE loop_ASL |
|||
;although this is called "ASL" the name is misleading because it doesn't preserve the sign of bit 7! |
|||
;value will be zero anyway so don't bother |
|||
LDA #0 |
|||
RTS |
|||
The 6502 doesn't have arithmetic shift right, but it can be replicated, provided the negative flag is set according to the value in the accumulator. |
|||
loop_ASL: |
|||
<lang 6502asm> LDA #$FF |
|||
ASL |
|||
CLC ;clear the carry. That way, ROR will not accidentally shift a 1 into the top bit of a positive number |
|||
DEX |
|||
BPL |
BPL SKIP |
||
SEC ;if the value in A is negative, setting the carry will ensure that ROR will insert a 1 into bit 7 of A upon rotating. |
|||
RTS |
|||
SKIP: |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
ROR</lang> |
|||
multi_LSR: |
|||
LDX temp |
|||
CPX #$08 |
|||
BNE loop_LSR |
|||
;value will be zero anyway so don't bother |
|||
LDA #0 |
|||
RTS |
|||
The 6502 can only rotate a value by one, not an arbitrary number. A looping routine is needed for rotates larger than 1. |
|||
loop_LSR: |
|||
Also, the 6502's <code>ROL</code> and <code>ROR</code> rotate instructions both rotate through the carry, unlike the instructions on other architectures with the same name. (68000, x86, and ARM all have a "ROR" command but it doesn't rotate through the carry on those CPUs.) |
|||
LSR |
|||
<lang 6502asm>LDA #$01 |
|||
DEX |
|||
ROL ;if the carry was set prior to the ROL, A = 3. If the carry was clear, A = 2.</lang> |
|||
BPL loop_LSR |
|||
RTS |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
multi_ASR |
|||
LDX temp |
|||
CPX #$08 |
|||
BNE loop_ASR |
|||
;value will be either 0 or #$FF anyway so don't bother |
|||
PHA |
|||
PLA ;set the flags according to the accumulator |
|||
<lang 6502asm>LDA #$01 |
|||
BMI returnFF |
|||
ROR ;if the carry was set prior to the ROR, A = 0x80. If clear, A = 0.</lang> |
|||
LDA #0 |
|||
RTS |
|||
returnFF: |
|||
LDA #$FF |
|||
RTS |
|||
loop_ASR: |
|||
jsr ASR |
|||
DEX |
|||
BPL loop_ASR |
|||
RTS |
|||
=={{header|68000 Assembly}}== |
|||
ASR: |
|||
Like with most 68000 commands, you can specify a length parameter. Anything outside that length is unaffected by the operation. |
|||
CLC ;clear the carry |
|||
;AND |
|||
PHA |
|||
<lang 68000devpac>MOVE.W D0,#$100 |
|||
PLA ;sets flags according to accumulator |
|||
MOVE.W D1,#$200 |
|||
BPL skip |
|||
AND.W D0,D1</lang> |
|||
SEC ;set the carry, the carry rotates into bit 7 during the ROR |
|||
skip: |
|||
;OR |
|||
ROR ;top bit will be the same as it was before. |
|||
<lang 68000devpac>MOVE.W D0,#$100 |
|||
RTS |
|||
MOVE.W D1,#$200 |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
OR.W D0,D1</lang> |
|||
multi_ROL: |
|||
LDX temp |
|||
;XOR |
|||
loop_ROL: |
|||
<lang 68000devpac>MOVE.W D0,#$100 |
|||
ROL |
|||
MOVE.W D1,#$200 |
|||
DEX |
|||
EOR.W D0,D1</lang> |
|||
BPL loop_ROL |
|||
RTS |
|||
;NOT |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
<lang 68000devpac>MOVE.W D0,#$100 |
|||
multi_ROR: |
|||
NOT.W D1</lang> |
|||
LDX temp |
|||
loop_ROR: |
|||
;Left Shift |
|||
ROR |
|||
<lang 68000devpac>MOVE.W D0,#$FF |
|||
DEX |
|||
MOVE.W D1,#$04 |
|||
BPL loop_ROR |
|||
LSL.W D0,D1 ;shifts 0x00FF left 4 bits</lang> |
|||
RTS</lang> |
|||
;Right Shift |
|||
<lang 68000devpac>MOVE.W D0,#$FF |
|||
MOVE.W D1,#$04 |
|||
LSR.W D0,D1 ;shifts 0x00FF right 4 bits</lang> |
|||
;Arithmetic Right Shift |
|||
<lang 68000devpac>MOVE.W D0,#$FF00 |
|||
MOVE.W D1,#$04 |
|||
ASR.W D0,D1 ;shifts 0xFF00 right 4 bits, preserving its sign</lang> |
|||
;Left Rotate |
|||
<lang 68000devpac>MOVE.W D0,#$FF00 |
|||
MOVE.W D1,#$04 |
|||
ROL.W D0,D1</lang> |
|||
;Right Rotate |
|||
<lang 68000devpac>MOVE.W D0,#$FF00 |
|||
MOVE.W D1,#$04 |
|||
ROR.W D0,D1</lang> |
|||
;Left Rotate Through Extend Flag |
|||
<lang 68000devpac>MOVE.W D0,#$FF00 |
|||
MOVE.W D1,#$04 |
|||
ROXL.W D0,D1</lang> |
|||
;Right Rotate Through Extend Flag |
|||
<lang 68000devpac>MOVE.W D0,#$FF00 |
|||
MOVE.W D1,#$04 |
|||
ROXR.W D0,D1</lang> |
|||
=={{header|8051 Assembly}}== |
=={{header|8051 Assembly}}== |