Here's my entry (11 bytes)
sta <00 ; 2 bytes
and #$F0 ; 4 bytes
clc ; 5 bytes
adc <00 ; 6 bytes
rol ; 7 bytes
rol ; 8 bytes
rol ; 9 bytes
rol ; 10 bytes
Oops! The total count is 11 bytes, of course. The adc <00 should count for 2.
Can anyone do better than 11?
-Lucas
[Quiz: shortest 6502 code that swaps nibbles in accumulator]
On Wed, 17 Mar 2004 18:28:27 +0000 (UTC), lscharen@d.umn.edu wrote:
> Here's my entry (11 bytes)
>
> sta <00 ; 2 bytes
> and #$F0 ; 4 bytes
> clc ; 5 bytes
> adc <00 ; 6 bytes
> rol ; 7 bytes
> rol ; 8 bytes
> rol ; 9 bytes
> rol ; 10 bytes
>
> Oops! The total count is 11 bytes, of course. The adc <00 should count for 2.
> Can anyone do better than 11?
The obvious way, after Michael McMahon explained how to do a
carry-excluded ROL, takes 12 bytes:
cmp #$80
rol
cmp #$80
rol
cmp #$80
rol
cmp #$80
rol
Of course, you can loop: that takes only 8 bytes, but it uses up a
precious index register. I should have mentioned in the problem
statement that the use of X or Y is not allowed, otherwise it's
too easy:
ldx #4
.1 cmp #$80
rol
dex
bne .1
Here is a weird way to use the stack for looping (the same idea can be
used to loop 2^n times). It's really slow, though, and cannot be inlined,
so it's mostly a curiosity (10 bytes but you need to JSR to it, so +3):
jsr .1
.1 jsr .2
.2 cmp #$80
rol
rts
Actually, in this case, it's faster and just as short to unroll once:
jsr .1
.1 cmp #$80
rol
cmp #$80
rol
rts
Finally, here's my solution in 10 bytes, no index registers used. It's
similar to yours but the add is done later and shifts in the last bit
(from the carry) at the same time, so there's no need for a clc.
asl
rol
rol
rol
sta $00
and #07
adc $00
Paul Guertin
pg@sff.net
> Here is a weird way to use the stack for looping (the same idea can be
> used to loop 2^n times). It's really slow, though, and cannot be inlined,
> so it's mostly a curiosity (10 bytes but you need to JSR to it, so +3):
>
> jsr .1
> .1 jsr .2
> .2 cmp #$80
> rol
> rts
I've seen a variation of this in NES games where space is so important. They
used it as a way of calling a subroutine with two different args without
wasting space. i.e.
lda #arg1
jsr .1
lda #arg2
.1 other code
rts
-Lucas
Paul Guertin wrote:
> Doing the same for ROR is slightly more involved.
> The quickest and shortest way (I think) is
>
> LSR ; c contains lsb
> BCC .1 ; lsb was clear, skip next instruction
> ADC #$7F ; add #$80 to set high bit
> .1 ; program continues here
Five bytes, six or seven cycles.
PHA
ROR
PLA
ROR
Four bytes, eleven cycles.
TAX
ROR
TXA
ROR
Four bytes, eight cycles, but uses an index register
> Quiz: what's the shortest 6502 code that will swap nibbles
> in a byte (e.g. $6D will become $D6, $81 will become $18, etc.)?
Simple code:
CMP #$80
ROL
ROL
ROL
ROL
Six bytes, ten cycles
TAX
LDA TABLE,X
Four bytes of CODE, but uses 256 bytes of data.
--
Paul
Monroe, Michigan USA
> > Quiz: what's the shortest 6502 code that will swap nibbles
> > in a byte (e.g. $6D will become $D6, $81 will become $18, etc.)?
>
> Simple code:
>
> CMP #$80
> ROL
> ROL
> ROL
> ROL
This doesn't work. All that done is the MSB is replicated and you are
still missing bit 4 in the answer. To illustrate
Let Accumulator = 10110110, carry = 0
cmp #$80; Acc = 10110110, carry = 1
rol; Acc = 01101101, carry = 1
rol; Acc = 11011011, carry = 0
rol; Acc = 10110110, carry = 1
rol; Acc = 01101101, carry = 1
So, we started with $B6 and ended with $6D.
-Lucas
Lucas wrote:
>> > Quiz: what's the shortest 6502 code that will swap nibbles
>> > in a byte (e.g. $6D will become $D6, $81 will become $18, etc.)?
>>
>> Simple code:
>>
>> CMP #$80
>> ROL
>> ROL
>> ROL
>> ROL
>
>This doesn't work. All that done is the MSB is replicated and you are
>still missing bit 4 in the answer. To illustrate
>
>Let Accumulator = 10110110, carry = 0
>
>cmp #$80; Acc = 10110110, carry = 1
>rol; Acc = 01101101, carry = 1
>rol; Acc = 11011011, carry = 0
>rol; Acc = 10110110, carry = 1
>rol; Acc = 01101101, carry = 1
>
>So, we started with $B6 and ended with $6D.
Right.
To make this scheme work, you need to put a CMP #$80
before each ROL, to keep the carry virtually out of the shift
path.
-michael
Check out amazing quality sound for 8-bit Apples on my
Home page: http://members.aol.com/MJMahon/
Paul Guertin wrote:
>Finally, here's my solution in 10 bytes, no index registers used. It's
>similar to yours but the add is done later and shifts in the last bit
>(from the carry) at the same time, so there's no need for a clc.
>
> asl
> rol
> rol
> rol
> sta $00
> and #07
> adc $00
Nice, Paul! A great example of how the low bits of a
byte can be shifted left independently of higher bits.
I've been doing programming with exact timing requirements
for so long that I am especially fond of non-branching code.
(BTW, my name is "Mahon", minus the "Mc". ;-)
-michael
Check out amazing quality sound for 8-bit Apples on my
Home page: http://members.aol.com/MJMahon/
On 18 Mar 2004 09:09:53 GMT, mjmahon@aol.com (Michael J. Mahon) wrote:
> Nice, Paul! A great example of how the low bits of a
> byte can be shifted left independently of higher bits.
People interested in this sort of thing, mixing logical and
arithmetic operations on bits, will probably enjoy a book
called "Hacker's Delight" by Henry S. Warren, published by
Addison-Wesley.
The web site:
http://www.hackersdelight.org/
Read reviews at Amazon:
http://www.amazon.com/exec/obidos/tg/detail/-/0201914654/104-4013520-2511168?v=glance
> (BTW, my name is "Mahon", minus the "Mc". ;-)
Oops. Sorry about that.
Paul McGuertin
pg@sff.net