Compile and link data to a predetermined address

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Compile and link data to a predetermined address

Post by jorgegv »

Hi people,

I need to compile a C data-only block to a fixed address, but I'm having some trouble. This is my code:

Code: Select all

// Compile with:
//
//   zcc +zx -vn -SO3 -m -compiler=sdcc -clib=sdcc_iy --max-allocs-per-node200000 --no-crt -zorg 0x5b00 data.c -o data.bin
//
// Dump binary in hex with:
//
//   od -tx1 data.bin
//
// This data should be compiled to base address 5B00, so that when it's
// decompressed to that address everything works OK

#include <stdint.h>

struct my_data {
    uint8_t	f1,f2;
    uint16_t	f3;
};
extern struct my_data d1, d2;

struct my_data *my_data_ptr	= &d1;	// this should contain 0x5B02
struct my_data d1		= { 1, 2, 0x3456 };	
struct my_data d2		= { 7, 8, 0x9012 };
struct my_data *my_data_ptr2	= &d2;	// this should contain 0x5B06

// binary dump of the generated data file should be these 12 bytes, in order:
// 02 5B 01 02 56 34 07 08 12 90 06 5B
The dump of the data.bin I get is this:

Code: Select all

[jorgegv@endor banked_data]$ od -tx1 data.bin
0000000 02 00 01 02 56 34 07 08 12 90 06 00
As you see, the data.bin output is being generated with 0x0000 base address and not 0x5b00.

Any ideas on how to get zcc to correctly link to the desired address? Isn't the -zorg directive supposed to do this?

My B-plan is to generate my data in ASM, where I can output an ORG directive and just get what I want, but I'd prefer to stick to C if possible.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Compile and link data to a predetermined address

Post by jorgegv »

A simpler C-plan would involve generating relocation data with -Cl -reloc-info, parsing the generated .reloc file and patching the binary file: just adding the 0x5b00 base address to the value found at each relocation address extracted from the relocation file. Some kind of poor-man's linking.

The format for the .reloc file seems the simplest: just 2-byte records indicating relocation addresses inside the binary.

This solution would also be OK for me, since it would link the binary at build time, which is what I want.

But as I said, I'd prefer the elegant solution, so any hints for it are welcome ;-)
andydansby
Member
Posts: 51
Joined: Fri May 27, 2016 8:58 pm

Re: Compile and link data to a predetermined address

Post by andydansby »

jorgegv wrote: Sun Aug 15, 2021 12:22 pm A simpler C-plan would involve generating relocation data with -Cl -reloc-info, parsing the generated .reloc file and patching the binary file: just adding the 0x5b00 base address to the value found at each relocation address extracted from the relocation file. Some kind of poor-man's linking.

The format for the .reloc file seems the simplest: just 2-byte records indicating relocation addresses inside the binary.

This solution would also be OK for me, since it would link the binary at build time, which is what I want.

But as I said, I'd prefer the elegant solution, so any hints for it are welcome ;-)
That seems to be horribly complex with the patching. I don't use the SDCC compiler much at all, but using SCCZ80, I would create a section in the mmap.inc

Code: Select all

SECTION structStuff
org 0x8000      ;	32768
then in variables.h, I would place.

Code: Select all

void anchorsAway(void)
{
    __asm
    SECTION structStuff
    PUBLIC _anchor
    _anchor:
    defb 0
    __endasm
}
struct my_data {
    uint8_t	f1,f2;
    uint16_t	f3;
};
extern struct my_data d1, d2;
You'll probably have to tweak this a bit, but at least in SCCZ80 if you lead with an assembly variable before the actual code, it will place the compiled code right afterwards. Hoping that this might work for you in SDCC. I'm going to actually do a write up about this in a few weeks with some sample code in SCCZ80.

Andy
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Compile and link data to a predetermined address

Post by jorgegv »

andydansby wrote: Sun Aug 15, 2021 1:45 pm
You'll probably have to tweak this a bit, but at least in SCCZ80 if you lead with an assembly variable before the actual code, it will place the compiled code right afterwards. Hoping that this might work for you in SDCC. I'm going to actually do a write up about this in a few weeks with some sample code in SCCZ80.

Andy
Mmm.... but this involves mixing asm and C which makes my C code less portable between SDCC and SCCZ80... If I were to do this, I think I'd just rather switch to full ASM data generation.

Besides, the patching is not really difficult at all, the relocation format is dead simple, and so are the operations to do for the relocations themselves. And I'd prefer that my source code not depend on too specific tweaks. I prefer to do the tweaks outside the regular toolchain, i.e. with specific tools that I can distribute with my library (did I say this mangling is related to my RAGE1 engine? :-) )

And as I said, isn't the -zorg CLI directive for ZCC supposed to do what I need?
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Re: Compile and link data to a predetermined address

Post by stefano »

Zorg provides a way to set a start address to the linker, it is meant to locate a monolithic program at a certain position.
On sccz80 you can specify the data position for a specific pointer, eg with the '@' operator
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Compile and link data to a predetermined address

Post by jorgegv »

stefano wrote: Sun Aug 15, 2021 4:59 pm Zorg provides a way to set a start address to the linker, it is meant to locate a monolithic program at a certain position.
I understood this, but it seems it is not doing its work in my example.
stefano wrote: Sun Aug 15, 2021 4:59 pm On sccz80 you can specify the data position for a specific pointer, eg with the '@' operator
I'm using SDCC, but I have tried with SCCZ80 and ZORG doesn't work either. ABout using '@', it seems cumbersome and I'd need to manually keep track of every object, not just the base address.

Maybe the problem is related to the --no-crt option? Perhaps the ZORG and related pragmas need a working (albeit minimal) CRT and do not work otherwise?

I have it already working with my C-plan (i.e. parsing relocation data and linking manually - a 112-line Perl script did the trick ;-) ), but I'd like to do it the elegant way.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: Compile and link data to a predetermined address

Post by dom »

So -zorg/pragma-define:CRT_ORG_CODE is understood by the crt0 file.

If you want a raw binary file then you'll need to create a stub crt file that reads in zcc_opt.def, sets org and then defines the sections that are used. Or just bodge it like this:

Code: Select all

static void orgit() __naked {
__asm
        org     0x5b00
__endasm;
}

struct my_data {
    uint8_t     f1,f2;
    uint16_t    f3;
};
....
I'm sure there's a crt option in newlib that does this, but I'm not sure what it would be. There are some cleaner methods in classic than the above, but that's no use to you.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Compile and link data to a predetermined address

Post by jorgegv »

dom wrote: Sun Aug 15, 2021 9:12 pm

Code: Select all

static void orgit() __naked {
__asm
        org     0x5b00
__endasm;
}
...
That did the trick, and it feels (to me) not too much intrusive or specific. Thanks!
fraespre
Member
Posts: 56
Joined: Mon Aug 19, 2019 8:08 pm

Re: Compile and link data to a predetermined address

Post by fraespre »

Maybe it's related with:
viewtopic.php?f=2&t=11596
Post Reply