2

I'm trying to disassemble some 6502 using Ghidra. The following (prerequisites: POSIX-style shell, Python 2.x) will generate a file called test.dat that demonstrates the issue:

python -c "open('test.dat','wb').write(''.join([chr(x) for x in [0xa2,0xa3,0xa9,0x00,0x9d,0x40,0x00,0xca,0x10,0xfa,0x60]]))"

Then, from in Ghidra:

  1. create new project (wherever you like)
  2. import test.dat created above, with Language as 6502/default and Base Address as 0x400
  3. double click test.dat in Active Project to get to the CodeBrowser window
  4. say No when analysis is offered
  5. go to location $400 and press D to disassemble

The disassembly is pretty short.

                             //
                             // RAM 
                             // fileOffset=0, length=11
                             // RAM: 0400-040a
                             //
            0400 a2 a3           LDX        #0xa3
            0402 a9 00           LDA        #0x0
                             LAB_0404                                        XREF[1]:     0408(j)  
            0404 9d 40 00        STA        $0x40,X=>DAT_00e3                                = ??
            0407 ca              DEX
            0408 10 fa           BPL        LAB_0404
            040a 60              RTS

The odd thing here is that rather than generating a label for $0040, which is the base address of the table, it's generated one for $00e3 - the first byte accessed - as if X is a TOC pointer, or similar, and $0040 is the offset. This isn't appropriate for 6502 code.

In this little example I can right click and fix up the references by hand, but I don't mind admitting that I don't want to have to do this for an entire program. 6502 code is full of this stuff.

Can I stop this from happening?

(I got very lost trying to follow through the Java source provided! - but I did figure out that this sort of reference is known as an extended reference, and appears to be common to all targets. I couldn't find anything in the documentation about these, though, or how to disable them.)

2

To get rid of these references, you need to disable the "Basic Constant Reference Analyzer" located in the Analysis Options (Analysis -> Auto Analyze ...)

After this, select your code and clear it (C hotkey by default) and then disassemble again.

  • Excellent, thanks - this looks promising, and stops it creating the spurious DAT_00e3 label, but no label is created for address 0x40, so from my perspective this still isn't quite a solution. But it might be that this is as good as it gets (I doubt 6502 was high on their priority list...), so I'll be happy to accept this as the answer if it starts to look like that's the case. It does give me a few more things to look for in the code. – Tom Seddon Mar 10 at 18:31
  • 1
    From what I can see, how it works is ConstantPropagationAnalyzer emulates p-code (the internal ghidra representation) of your program instructions and once it sees a load from an address, it creates a reference. Now, the address it sees is the computed result, 0xE3, so this is what it adds a reference to. You'll probably need to write a custom analyzer for 6502 that would use the original instruction (not its p-code) and create a reference to 0x40. – xyz Mar 10 at 22:31
1

haven't used ghidra yet but checking your bytes on radare2 it appears the diassembly is right

C:\>radare2 -
[0x00000000]> e io.cache = true
[0x00000000]> w \xa2\xa3\xa9\x00\x9d\x40\x00\xca\x10\xfa\x60
[0x00000000]> px 10
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  a2a3 a900 9d40 00ca 10fa                 .....@....
[0x00000000]> e asm.arch = 6502
[0x00000000]> pd 6
            0x00000000      a2a3           ldx #0xa3
            0x00000002      a900           lda #0x00
        .-> 0x00000004      9d4000         sta 0x0040,x  //(0xa3 + 0x40 == 0xe3)
        :   0x00000007      ca             dex
        `=< 0x00000008      10fa           bpl 0x000004
            0x0000000a      60             rts
[0x00000000]> af
[0x00000000]> pdc
function fcn.00000000 () {
    //  3 basic blocks
    loc_0x0:

       x = #0xa3
       a = #0x00
   do
   {
        loc_0x4:

           [0x0040+x ] = a
           dex
           bpl 0x000004             //unlikely
       } while (?);
  return;

    loc_0xa:

       rts
(break)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.