6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 1:53 am

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Sat Apr 27, 2024 1:51 pm 
Offline
User avatar

Joined: Mon Feb 01, 2021 1:07 am
Posts: 44
Location: Sydney, Australia
Hi Guys, I'm trying to get the address of some of my variables.

Code:
               .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.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 27, 2024 5:27 pm 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 140
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:
  lda #<BSSLoc
  ldy #>BSSLoc

  lda #<DataLoc
  ldy #>DataLoc
  sta ZPLoc+0
  sty ZPLoc+1


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 27, 2024 5:29 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
Firefox6502 wrote:
Hi Guys, I'm trying to get the address of some of my variables.

Code:
               .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:
  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:
  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/


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 29, 2024 5:20 am 
Offline
User avatar

Joined: Mon Feb 01, 2021 1:07 am
Posts: 44
Location: Sydney, Australia
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:
  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.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 29, 2024 4:03 pm 
Offline

Joined: Mon Feb 15, 2021 2:11 am
Posts: 100
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 30, 2024 6:09 am 
Offline
User avatar

Joined: Mon Feb 01, 2021 1:07 am
Posts: 44
Location: Sydney, Australia
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 30, 2024 6:14 am 
Offline
User avatar

Joined: Mon Feb 01, 2021 1:07 am
Posts: 44
Location: Sydney, Australia
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 31 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: