beethead wrote:
One part of the linking process that has me concerned is in regards to code/data being placed in zero or direct page.
I have limited experience with this, but here's how it works with ASxxxx, or at least how I do it. (There are more details in my
personal notes on ASxxxx which may be faster to read than going into the actual documentation.)
Code and data can be in separate areas; same-named areas from different files are considered all part of one area by the linker. The default area is _CODE which is relocatable and and concatenated (i.e., each _CODE area from each object file will be placed in memory after the previous one).
I add an area called ZP which is absoute and has the PAG attribute set to give me a warning if the size at link time exceeds 256 bytes.
Code:
.area ZP (abs,pag)
.area _CODE
At whatever points in the file are convenient I can then declare further storage in the zero page:
Code:
tripleA: sta *temp ; "*" indicates direct (ZP) addressing mode
clc
adc *temp
adc *temp
rts
.area ZP
temp: .ds 1
.area _CODE
When linking, I tell the linker to locate the ZP area at $0000. Thus, everything declared to be in the ZP area will be in the zero page (or the linker will find more than 256 bytes of storage allocated in the ZP area and halt with an error).
For processors like the 6809 and 65816 where the direct page can be anywhere in memory there's a
.setdp [BASE[,AREA]] directive to tell the assembler at what address the direct page is placed, though of course the programmer is still responsible for writing whatever code is necessary to put it there at run time.
Code that accesses
temp with absolute (2-byte) addressing is fine regardless of whether
temp is in the zero page or not. Code that accesses it with direct (1-byte) addressing will be flagged by the linker as an error if
temp is assigned to an address >$FF during the link.
The AS6502 assembler currently isn't (in most cases) able to figure out automatically whether an access should be able to use direct rather than absolute addressing, so you need to mark those manually as above. Even if it did do this it would be rather hit-or-miss because there's no way (that I can see) to tell the assembler that you expect a global from another (separately-assembled) file to be located at a zero-page address. The linker definitely doesn't change the opcodes after assembly; that would kinda make it an assembler, too. I suppose it would be possible to do this, but I've never seen anything that does. (This kind of thing is actually one reason why I'm looking at moving away from separate-assembly/link to whole-program assembly.)