Some code oddities I encountered

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
mackwinston
Posts: 2
Joined: 02 Apr 2022

Some code oddities I encountered

Post by mackwinston »

I'm working on some A8 (atari 8 bit) related hardware, and in the process of this I'm using an Atarimax multicart, this device if you've never met it is a cartridge that goes in your A8 and gives a menu of games. Unfortunately it's not open source (or at least, if it is, I've not found any source code) so I've had to reverse engineer it.

The loader has a couple of weird things in it that I really don't know why they would be done like that - forgive me because I'm primarily a Z80 person, so I may just be missing some tricks that experienced 6502 developers know about, but even so I can't see much of a reason why some things have been done in a certain way.

For instance, this code snippet:

Code: Select all

start_program_1:
0135        lda $02e2       ; INITAD
0138        ora $02e3       ; INITAD + 1
013b        beq goto_main   ; if INITAD is zero don't jump there (MissileCmd set to 0)

013d        jsr jump_initad

goto_main:
0140        bne main        ; surely these two can only result in the same as
0142        beq main        ; a JMP main?
Why the bne then beq? Surely a jmp would save a byte and do the same thing? I can't see how this branch would never be taken. Note that no code branches or jumps to 0142, the only branch to goto_main: is the one at 013b.

Then there's this code snippet:

Code: Select all

start_program_2:
0144        bit $30         ; status
0146        bvc jump_runad  ; if overflow clear, use RUNAD address

0148        lda $02e0       ; RUNAD
014b        sta $000c       ; DOSINI    (why not a ZP instruction?)
014e        lda $0231       ; RUNAD+1
0151        sta $000d       ; DOSINI+1  (why not ZP?)
0154        lda #$01
0156        sta $0009       ; BOOT? (why not ZP?)
0159        jmp WARMSV      ; $e474, OS ROM WARMSV - warm start. Probably for cart images?

jump_runad:
                            ; For Missile Command, this is ultimately set to $8000
015c        jmp (RUNAD)     ; $02e0 Run address from executable (xex file?)

jump_initad:
015f        jmp (INITAD)    ; $02e2 Init address from disk
Why would you use the 3-byte instruction sta $000c instead of the 2 byte zero page instruction sta $0c (not just at $014b, but all the loads/stores in that snippet are using 3 byte instructions to store in the zero page rather than the 2 byte instruction).
The only reason I can think of is to either to provide padding (unlikely, the whole routine lives in stack space, so you'd think compactness would be important to allow more stack space) and I don't think any of this is timing sensitive. The only plausible reason I can come up with is that when this routine is written out from the first 8k page of the cartridge, the addresses could be modified to be anywhere in address space, but in this instance this still doesn't make sense because DOSINI and BOOT can't be anywhere in memory (because the OS ROM will use these).
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Some code oddities I encountered

Post by BigEd »

A belated welcome!

My first thought is that this is just some inefficiency, rather than something clever. Although the code may be running on a very limited machine, once it fits the space and runs fast enough, there's no reason to optimise it further.

So, the bne+beq looks to me like a tactic which avoids needing an absolute address for the destination. It just so happens this gadget is reached by a beq. It could be that earlier versions of the code did otherwise, or that this is a standard gadget maybe even inserted by macro.

Similarly for the absolute addresses - possibly, or probably, just a case of using a suboptimal addressing mode, perhaps because a macro is in use. Just possibly using an absolute address helps with portability somehow, or code relocation, or even as a remote possibility works with some clever hardware which is responsive to the 6502 bus activity.

So, my guess is that there's nothing that's very clever that's being missed. But I'd be happy to be shown to be wrong!
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Some code oddities I encountered

Post by 8BIT »

I was thinking the same as BigEd. Possibly the original source was C and the C optimizations were not very efficient or disabled.

Daryl
Please visit my website -> https://sbc.rictor.org/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Some code oddities I encountered

Post by GARTHWILSON »

Another vote for the same here; but I would say that if it came from macros, someone doesn't know much about the power of macros.  Macros can have all kinds of conditional assembly to automatically make the best decisions for efficient code output.  I've had macros that were 50 lines or more and yet output as little as one or two assembly-language instructions if the conditions for it were right, just as efficient as a good programmer would do by hand.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
John West
Posts: 383
Joined: 03 Sep 2002

Re: Some code oddities I encountered

Post by John West »

My thought for the first (the beq/bne) is that there might be another destination that is sometimes used during development (depending on the state of the Z flag). For the release version they change it so both paths go to the same place.

For the second, many 8 bit assemblers would do that if the operand is a label defined after that line in the source code.

Code: Select all

    STA DOSINI
    ....
DOSINI = 12
On the first pass, the assembler doesn't know where DOSINI is, and makes the safe assumption that it could be anywhere in memory. Changing that decision on the second pass would change the address of every later instruction, breaking JMPs and JSRs and anything else that depends on their locations. So they stick with the less efficient 16 bit address. If the programmer wanted page zero, they had the opportunity to say so before that point.
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Some code oddities I encountered

Post by 8BIT »

John West wrote:
For the second, many 8 bit assemblers would do that if the operand is a label defined after that line in the source code.
Yes, I've seen that many times as well.

Daryl
Please visit my website -> https://sbc.rictor.org/
Post Reply