I have two files, crt0 and test. There might be more files. crt0 is the first one given to the linker.
In crt0, I want to have an area HOME at fixed address 0x0000, as well as some stuff that goes into areas _CODE and _GSINIT. In test, I want to have an area IIVT at fixed address 0x0200, as well as some stuff that goes into areas _CODE and _GSINIT. The other files might have stuff in that goes into areas _CODE and _GSINIT.
So I want HOME at 0x0000, IIVT at 0x0200 (both via .org assembler directives). _CODE and _GSINIT should go after the end of IIVT (well, if the gap between HOME and IIVT is big enough, it would be better for one or both of them to be placed in that gap, but that is not my priority for now).
I'm struggling to get this to work. Everything I try ends up placing _CODE and _GSINIT in the "same" location as HOME or IIVT, with IIVT not placed where it should be, or the binary mixing the bytes from HOME or IIVT with _CODE or _GSINIT.
What works is placing _CODE at fixed 0x0400 via --code-loc. That way everything looks fine (_GSINIT after _CODE thanks to ordering in c), sine IIVT never gets big enough to overlap with _CODE. But this wastes a lot of space if IIVT is small.
If I understand correctly, the current (SD) version of the linker is simply unable to figure out "where to start" with non-absolute areas. That means that the start of the first non-absolute area has to be passed to the linker as an actual value, in your case
--code-locwhich is then-b _CODE=0x400in the current link file. The following non-absolute areas, when their address is not specified, will appear after the first, following the order specified in the first linked file. That means that you can achieve the layout where the rest of the code goes after "the conceptual IIVT" at 0x200 by having the content of your expected IIVT as the first content in your actual_CODE(!) Then you fix the begin of the code as 0x200, and all other areas will be packed like they "should be". With this crt0and this .lk file
I eventually get in the resulting binary:
where I've placed 'IIVT' code in the test.s (in the
_CODEsection!), the 'CODE and DATA content' in the test2, and, to demonstrate that the order is followed, the "initialized" content was already in crt0.Btw, when you do just a minimal command line like
sdcc -mz80 t.cthe way the linker (currently) "knows" where the code starts is that it actually gets this in its .lk file:These are written using WRITE_SEG_LOC macro in SDCCmain.c:
https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/src/SDCCmain.c#l1889
Last edit: Janko Stamenović 2025-09-13
Maybe then, if
_IIVThas to have its own name, and if the goal is for the following segments to follow, for the Rabbit cases, a new default value for_IIVTcould be added to SDCC, the value for the_CODEshould be 0 or undefined, which means that it will follow the first seen by the linker, and the non-absolute_IIVThas to be the first of all in the crt0 source.Non-absolute
_IIVTwould mean that I can't use.orgin there, though, and would have to pad withnopor so manually. Should be worth it, though._IIVTat fixed 0x200 is good enough for me for now (it wastes 256B of Flash on Rabbit 2000 if no external interrupt table is needed, and makes some external interrupts on Rabbit 6000 unavailable, but neither is a real problem for now). A command-line option for the interrupt vector table location could be added later.Even after reading the most recent version of the upstream documentation, the semantic of absolute areas in asxxxx context is always that they are overlaid (so I imagine them as always being "see-through", like they are written on the transparent slides, in the whole address space). In "1.4.23 .area Directive":
That means that it's not supposed, by design, to use absolute areas to "move" or influence the position of the relocatable areas.
But there is good news too:
In the latest upstream, there is a mechanism to specify the expected layout inside of the crt0.asm, which then both makes unnecessary to pass the values from compiler, and allows for every custom crt0.asm to also direct the rest of its code.
It is, I think, much better mechanism, with which I can create this:
crt0.asm
and test.asm
and after linking without specifying any addresses in the .lk file the resulting binary will be exactly what we'd like:
Note also that I avoided both
_CODEand_DATA. The reason for this is that both of these two are in the asxxxx predefined, so had I used:The error would have been:
Per manual:
so redefining these to belong to some bank fails.
(Edited to add the longer MyBank name (instead of B, previously) to make it more obvious. Also edited the error part to clearly be consistent with
_CODE(REL,CON,CSEG,BANK=MyBank)).Last edit: Janko Stamenović 2025-09-16
That approach would have to rely on no
_CODEbeing in crt0, and the "IIVT"_CODEbeing the second file (i.e. before any other files containing_CODE, though)? I can't guarantee that - crt0 being first is fine, but the order of the rest dpeends on whatever the user chooses, and the interrupt vector table goes into the same files asmain.