address-of (&) fragment error (ca65)

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
User avatar
Firefox6502
Posts: 44
Joined: 01 Feb 2021
Location: Sydney, Australia

address-of (&) fragment error (ca65)

Post by Firefox6502 »

Hi Guys, I'm trying to get the address of some of my variables.

Code: Select all

               .zeropage
ZPLoc:      .res 20

                .bss
BSSLoc:    .res 10

                .data
DataLoc:   .res 15

                lda #ZPLoc   
                lda #BSSLoc
                lda #DataLoc
ld65 config file
ZP starts at $0000
RAM starts at $0200
where BSS is the first segment under RAM, and DATA is the second segment under RAM.

The ca65 assembler throws the following error for BSSLoc and DataLoc:
Error: Range error (Address size 2 does not match fragment size 1)

But works fine for ZPLoc.

I've tried a number of things, moving the variables around, but still getting the same error. Always works in zero page memory but not the others.

Background: I wanted the address of the variables so I could clear their memory locations with an stz in a loop.
Then I learn't that ca65 can declare and initialise a variable in one statement, e.g. ZPLoc: .res 20, $00

Regardless, I would still like to understand why this fragmentation error is occurring, as no doubt I will eventually need to get the address of a variable sooner or later.
According to the error, Address size 2 and Fragment size 1 are the clues here, but I don't understand what is going on. Isn't LDA working with bytes (8 bits) here?
Thanks for your help.
Greetings Professor Falken.
leepivonka
Posts: 167
Joined: 15 Apr 2016

Re: address-of (&) fragment error (ca65)

Post by leepivonka »

The assembler expects that BSSLoc & DataLoc are 16bit values. There are problems trying to generate object code to load them into an 8bit register.

You can split these addresses into hi & lo 8bit values, & load them into a pair of registers:

Code: Select all

  lda #<BSSLoc
  ldy #>BSSLoc

  lda #<DataLoc
  ldy #>DataLoc
  sta ZPLoc+0
  sty ZPLoc+1
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: address-of (&) fragment error (ca65)

Post by drogon »

Firefox6502 wrote:
Hi Guys, I'm trying to get the address of some of my variables.

Code: Select all

               .zeropage
ZPLoc:      .res 20

                .bss
BSSLoc:    .res 10

                .data
DataLoc:   .res 15

                lda #ZPLoc   
                lda #BSSLoc
                lda #DataLoc
ld65 config file
ZP starts at $0000
RAM starts at $0200
where BSS is the first segment under RAM, and DATA is the second segment under RAM.

The ca65 assembler throws the following error for BSSLoc and DataLoc:
Error: Range error (Address size 2 does not match fragment size 1)

But works fine for ZPLoc.

I've tried a number of things, moving the variables around, but still getting the same error. Always works in zero page memory but not the others.

Background: I wanted the address of the variables so I could clear their memory locations with an stz in a loop.
Then I learn't that ca65 can declare and initialise a variable in one statement, e.g. ZPLoc: .res 20, $00

Regardless, I would still like to understand why this fragmentation error is occurring, as no doubt I will eventually need to get the address of a variable sooner or later.
According to the error, Address size 2 and Fragment size 1 are the clues here, but I don't understand what is going on. Isn't LDA working with bytes (8 bits) here?
Thanks for your help.

Addresses are 16-bits. Registers are 8-bits. It won't fit.

It might be that its allowing the Zero page one as it might think you can/are using a ZP addressing mode which only needs 8 bits.

Try:

Code: Select all

  lda #<BSSLoc
  sta zpPtr+0
  lda #>BSSLoc
  sta zpPtr+1
then you need to work out the size of the BSS before you can loop to zero it, but if it's 10 bytes:

Code: Select all

  ldy #9
  lda #0
1:
  sta (zpPtr),y
  dey
  bpl :1
and so on.

One thing to note about using sections and initialising them is that you then need a loader to put the resulting object file into memory at the right locations...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
Firefox6502
Posts: 44
Joined: 01 Feb 2021
Location: Sydney, Australia

Re: address-of (&) fragment error (ca65)

Post by Firefox6502 »

Thank you very much leepivonka and Gordon!
8-bit registers and 16-bit addresses ofcourse! I couldn't see the forest from the trees. Learning the hardware is one thing but then applying the hardware knowledge to programming is another (for beginners like me anyway).

And Gordon, thank you for the Initialisation code sample: sta (zpPtr),y
I'm reading up up post-indexed indirect which is only available with the Y-register. I have a lot to learn.

Code: Select all

  ldy #9
  lda #0
1:
  sta (zpPtr),y
  dey
  bpl :1
Finally Gordon (or anyone) could you please explain what this means:
drogon wrote:
One thing to note about using sections and initialising them is that you then need a loader to put the resulting object file into memory at the right locations...
-Gordon
I.e. What is a loader? Are you referring to the ld65 configuration file, if so I have this. It took me a while setup my memory and segments.
If you mean something else, and it's not too much trouble, could you please provide a snippet of code, so I can learn and experiment with it. That would be very helpful.

Thank you.
Greetings Professor Falken.
Sean
Posts: 101
Joined: 15 Feb 2021

Re: address-of (&) fragment error (ca65)

Post by Sean »

Firefox6502 wrote:
I.e. What is a loader? Are you referring to the ld65 configuration file, if so I have this. It took me a while setup my memory and segments.
If you mean something else, and it's not too much trouble, could you please provide a snippet of code, so I can learn and experiment with it. That would be very helpful.

Thank you.
As I understand it, a loader is a piece of code in an operating system or monitor that reads program file (from disk, serial input, whatever) and places it into the correct location in RAM prior to execution. These can vary in sophistication, in relation to the sophistication of the program file format. The Commodore .PRG format is very simple, with a two byte load address prefix before the program content. Some formats that directly support segmentation require a more complex loader, to read metadata on the segments and place different the segments at different locations in memory. A relocatable format like .065 needs even more sophistication.
User avatar
Firefox6502
Posts: 44
Joined: 01 Feb 2021
Location: Sydney, Australia

Re: address-of (&) fragment error (ca65)

Post by Firefox6502 »

Thank you Sean that's very helpful. I understand at a high-level.

I wonder if this is the same thing or same concept as the ld65 config segments: https://www.cc65.org/doc/ld65-5.html
Quote:
For a bss type segment to be useful, it must be cleared somehow by your program (this happens usually in the startup code - for example the startup code for cc65 generated programs takes care about that). But how does your code know, where the segment starts, and how big it is? The linker is able to give that information, but you must request it. This is, what we're doing with the "define = yes" attribute in the BSS definitions. For each segment, where this attribute is true, the linker will export three symbols.

__NAME_LOAD__ This is set to the address where the
segment is loaded.
__NAME_RUN__ This is set to the run address of the
segment. We will cover run addresses
later.
__NAME_SIZE__ This is set to the segment size.
Regardless, I'll get to all this sooner or later.
Greetings Professor Falken.
User avatar
Firefox6502
Posts: 44
Joined: 01 Feb 2021
Location: Sydney, Australia

Re: address-of (&) fragment error (ca65)

Post by Firefox6502 »

drogon wrote:
It might be that its allowing the Zero page one as it might think you can/are using a ZP addressing mode which only needs 8 bits.
According to ca65 documentation I think this is why zero page 8-bit addressing is working here: https://cc65.github.io/doc/ca65.html#ss8.1
Quote:
ca65 assigns each segment and each symbol an address size. This is true, even if the symbol is not used as an address. You may also think of a value range of the symbol instead of an address size.

Possible address sizes are:

Zeropage or direct (8 bits)
Absolute (16 bits)
Far (24 bits)
Long (32 bits)
Greetings Professor Falken.
Post Reply