6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed Nov 13, 2024 1:42 am

All times are UTC




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Jul 10, 2019 2:30 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Let's see you load a constant (let's say $42) without using any immediate values. Short programs, and surprising tactics, are better! (Edit: for example, get $42 into the accumulator, using 6502 instructions only. But if you have a remarkable solution using '816 instructions, go for it.)

Here's a spoiler-proof fence so you can have a go before you see anyone else's effort:

.
..
.
...
.
..
.
....
.
..
.
...
.
..
.


Last edited by BigEd on Wed Jul 10, 2019 3:01 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 10, 2019 2:30 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
More fence:

.
..
.
...
.
..
.
....
.
..
.
...
.
..
.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 10, 2019 3:09 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
This is the first way I though of doing it:
Code:
; Load $42 = 01000010 into A without using immediates
ASL A  ; 0
SEC
ROL A  ; 1
ASL A  ; 0
ASL A  ; 0
ASL A  ; 0
ASL A  ; 0
SEC
ROL A  ; 1
ASL A  ; 0

Total is 10 bytes / 20 cycles.

You can probably do better with code assembled at a specific address, so that JSR will push a know value onto the stack.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 10, 2019 3:53 pm 
Offline

Joined: Sat Jan 02, 2016 10:22 am
Posts: 197
Expanding on your idea, for constant time using the C02

Set A to $FF first, then ASL A shifts in a zero ROL A shifts in a 1 without needing additional SEC instructions
Code:
LDA $00   ; (2/3) any zero page location
EOR $00   ; (2/3) A is now zero
DEC A     ; (1/2) A is now $FF
SEC       ; (1/2) set the initial carry
ASL A     ; (1/2)
ROL A     ; (1/2)
ASL A     ; (1/2)
ASL A     ; (1/2)
ASL A     ; (1/2)
ASL A     ; (1/2)
ROL A     ; (1/2)
ASL A     ; (1/2)

Longer and slower at 14 bytes and 26 cycles, loading $42 but will be the same for any constant as the carry is set on every shift/rotate.

However for the best time, with A at known state at the start, there's no need to shift in any leading 1. The SEC isn't needed, as the first bit shifted in will be a zero. So to load say $F7 would be shorter at 9 bytes and 16 cycles.
Code:
LDA $00   ; (2/3) any zero page location
EOR $00   ; (2/3) A is now zero
DEC A     ; (1/2) A is now $FF
ASL A     ; (1/2) A is now $FE
ROL A     ; (1/2) A is now $FD
ROL A     ; (1/2) A is now $FB
ROL A     ; (1/2) A is now $F7

Obviously the trivial case is set A to zero, that's just 4 bytes and 6 cycles.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 10, 2019 4:08 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
For $42 specifically, I can do better:
Code:
STZ $FE ; clear A via ZP
LDA $FE
SEC
ROR A
ROR A ; $40
INC A
INC A ; $42
That's 9 bytes, 16 cycles, given a 'C02.

For a more general approach, let's do some preparation by loading $FF into a ZP location (again, assuming a 'C02):
Code:
STZ $FF
DEC $FF
Then, every time you need to load a constant, you can encode it directly into a pattern of RORs and LSRs, as C will be implicitly set by each:
Code:
LDA $FF
SEC ; only actually needed if LSB is to be set
LSR A
ROR A
LSR A
LSR A
LSR A
LSR A
ROR A
LSR A
That's 11 bytes, 21 cycles - or if you can elide the SEC, 10 bytes, 19 cycles. You can turn it around and use ROL/ASL if the MSB happens to be clear, and shorten the sequence if several most-significant or least-significant bits are all set. This code segment is even NMOS compatible!


Last edited by Chromatix on Wed Jul 10, 2019 9:19 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 10, 2019 7:42 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
And, for a borderline-cheating solution:
Code:
LDA $42
LDA *-1
That's 5 bytes, 7 cycles (assuming the program is not in ZP).


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 4:02 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
Chromatix wrote:
Code:
LDA $42
LDA *-1

Definitely my favorite! The challenge seems rather contrived from the start, but I am reminded of a situation like this (or more specifically this), where Ivan needed to include his run-time machine code in "keyboardable" Applesoft REM statements (UPPER-CASE only for full compatibility), allowing the inclusion of only a small subset of the 6502 opcodes and operands (no LDA LDX LDY STA STX STY ...).

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 5:29 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Even better: if you have STY zp anywhere - which seems likely, or at least easy to arrange - then attach a label to it. Its opcode is $84. Then you only need:
Code:
LDA sty
LSR A
That's 4 bytes, 6 cycles. You can do the same with STA zp, which is $85.

Slightly less likely is that you have CMP (zp,X) or AND (zp,X) somewhere. Use the same trick on these, but with ASL A. If you have EOR (zp,X), use INC A.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 6:27 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Nicely done, everyone. I did (eventually) think of setting carry and shifting, but at the moment of posting I didn't have an answer. I thought of looking at the stack, but not of reading the code itself.

Thanks for the pointer back to SLAMMER - that's a well-motivated case of constrained programming. We've also previously seen the case of avoiding 00 in code:
Bootstrapping an SBC

Edit: some links to SLAMMER have decayed - see this post and this one for working links.

Edit: or, I could fix up this quote:
barrym95838 wrote:
...I am reminded of a situation like this (or more specifically this), where Ivan needed to include his run-time machine code in "keyboardable" Applesoft REM statements (UPPER-CASE only for full compatibility), allowing the inclusion of only a small subset of the 6502 opcodes and operands (no LDA LDX LDY STA STX STY ...).


Edit: for want of a better place to put it, a link to Neal Parker's
S. H. Lam Revisited


Last edited by BigEd on Thu Aug 29, 2024 6:44 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 10:30 am 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 460
Location: Canada
If it's possible to place code anywhere, the stack could be used using a JSR to the next line of code, then popping the address which just happens to be $42.
It's possible to load two immediate. But the code has to be in just the right place.

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 10:41 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Some of these approaches, of course, need the assembler to know the load address - position-independent code being another kind of constraint on programming.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 1:50 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
It may also be possible to rely on the contents of a ROM. But that makes the code less portable.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 1:54 pm 
Offline
User avatar

Joined: Thu May 14, 2015 9:20 pm
Posts: 155
Location: UK
Chromatix wrote:
It may also be possible to rely on the contents of a ROM. But that makes the code less portable.

Yes, if you are running on a known system with significant amount of fixed ROM data, of course this makes the task so much easier. So much so, that it could be felt to be cheating :lol:

Mark


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 3:31 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
BigEd wrote:
... constraint on programming.
I have an apt solution to Ed's mini challenge, but I have hesitated to mention it because it involves a constraint on the hardware. Here is my somewhat dubious solution:

Code:
LDA $4200
The constraint is that $4200 is an address which causes no device to be selected, as may for example may be the case on an older system equipped with 16K or less of RAM. Thus, during the 4th cycle of the LDA abs -- when the target address is supposed to be read from -- nothing will drive the data bus. In that circumstance, capacitance will cause the bus to retain its last actively driven value... in this case, the high byte of the LDA's 16-bit operand.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 11, 2019 4:25 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Mr Hyde, that's fiendish!

(Might be worth noting that tactics like STZ/LDA or LDA/EOR also rely on something - both could fail if they happened to hit peripherals which don't happen to return the expected data.)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: