Menu

#207 Areas from two files placed at fixed locations with other areas following?

open
nobody
None
5
2025-09-14
2025-09-13
No

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.

Discussion

  • Janko Stamenović

    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-loc which is then -b _CODE=0x400 in 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 crt0

            .module crt0
    
            .area _HOME(ABS)
            .org    0
            ld      a, #'H'
            ld      a, #'O'
            ld      a, #'M'
            ld      a, #'E'
            ret
    
            ;;      this, first file the linker sees 
            ;;      enforces the order of area definitions
            .area   _CODE
            .area   _INITIALIZED
            .ascii   "initialized"
            .area   _DATA
            .area   _BSS
            .area   _HEAP
    

    and this .lk file

    -mjwx
    -i build/bin.ihx
    -b _CODE=0x200
    build/crt0.rel
    build/test.rel
    build/test2.rel
    
    -e
    

    I eventually get in the resulting binary:

    00000000: 3e 48 3e 4f 3e 4d 3e 45 c9 00 00 00 00 00 00 00  >H>O>M>E........
    ...
    00000200: 3e 49 3e 49 3e 56 3e 54 c9 c9 c9 3e 43 3e 4f 3e  >I>I>V>T...>C>O>
    00000210: 44 3e 45 c9 69 6e 69 74 69 61 6c 69 7a 65 64 44  D>E.initializedD
    00000220: 41 54 41                                         ATA
    

    where I've placed 'IIVT' code in the test.s (in the _CODE section!), the 'CODE and DATA content' in the test2, and, to demonstrate that the order is followed, the "initialized" content was already in crt0.

     
    • Janko Stamenović

      Btw, when you do just a minimal command line like sdcc -mz80 t.c the way the linker (currently) "knows" where the code starts is that it actually gets this in its .lk file:

      -b _CODE = 0x0200
      -b _DATA = 0x8000
      

      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
      • Janko Stamenović

        Maybe then, if _IIVT has 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 _IIVT could be added to SDCC, the value for the _CODE should be 0 or undefined, which means that it will follow the first seen by the linker, and the non-absolute _IIVT has to be the first of all in the crt0 source.

         
        • Philipp Klaus Krause

          Non-absolute _IIVT would mean that I can't use .org in there, though, and would have to pad with nop or so manually. Should be worth it, though.
          _IIVT at 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.

           
          • Janko Stamenović

            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":

            options specify the type of program or data area
            
            ABS     absolute (automatically invokes OVR)
            REL     relocatable
            OVR     overlay
            CON     concatenate
            
             .area  TEST  (REL,CON)  ;This section is relocatable
                   ;and concatenated with other
                   ;sections of this program area."
            
            area  SYS   (ABS,OVR)  ;(CON not allowed with ABS)
                   ;This section is defined as
                   ;absolute. Absolute sections
                   ;are always overlaid with
                   ;other sections of this program
                   ;area
            

            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

                    .module crt0
            
                     ;; THE DEFINITIONS
                    ;;
                    .bank   MyBank(BASE=0x200)
                    .area   HEADER(ABS,CSEG)
                    .area   IIVT(REL,CON,CSEG,BANK=MyBank)
                    .area   CODE(REL,CON,CSEG,BANK=MyBank)
                    .area   INITIALIZED(REL,CON,CSEG,BANK=MyBank)
                    .area   DATA(REL,CON,DSEG,BANK=MyBank)
                    .area   BSS(REL,CON,DSEG,BANK=MyBank)
                    .area   HEAP(REL,CON,DSEG,BANK=MyBank)
                    ;;
                    ;; END OF DEFINITIONS
            
                    .area HEADER
                    .org    0
                    .area HEADER
                    .org    0
                    ld a, #72 ; H
                    ld a, #79 ; O
                    ld a, #77 ; M
                    ld a, #69 ; E
                    ret
            
            
                    .area CODE
                    ld a, #67 ; C
                    ld a, #79 ; O
                    ld a, #68 ; D
                    ld a, #69 ; E
                    ret
            
                    .area   INITIALIZED
                    .ascii   "initialized"
            

            and test.asm

                    .module test
            
                    .area IIVT
                    ld a, #73 ; I
                    ld a, #73 ; I
                    ld a, #86 ; V
                    ld a, #84 ; T
                    ret
            
                    .area  CODE
                    ld a, #67 ; C
                    ld a, #79 ; O
                    ld a, #68 ; D
                    ld a, #69 ; E
                    ld a, #50 ; 2
                    ret
            
                    .area  DATA
                    .ascii "DATA"
            

            and after linking without specifying any addresses in the .lk file the resulting binary will be exactly what we'd like:

            00000000: 3e48 3e4f 3e4d 3e45 c900 0000 0000 0000  >H>O>M>E........
            00000200: 3e49 3e49 3e56 3e54 c93e 433e 4f3e 443e  >I>I>V>T.>C>O>D>
            00000210: 45c9 3e43 3e4f 3e44 3e45 3e32 c969 6e69  E.>C>O>D>E>2.ini
            00000220: 7469 616c 697a 6564 4441 5441            tializedDATA
            

            Note also that I avoided both _CODE and _DATA. The reason for this is that both of these two are in the asxxxx predefined, so had I used:

                    .area   _CODE(REL,CON,CSEG,BANK=MyBank)
            

            The error would have been:

            ?ASxxxx-Error-<m> in line 8 of crt0.s
                          <m> '8         .area   _CODE(REL,CON,CSEG,BANK=MyBank)'
                          <m> multiple definitions error or macro recursion error
            

            Per manual:

            The   ASxxxx   assemblers   automatically  provide  two  program
            sections:
            
            '_CODE'         This  is  the  default  code/data  area.
                            This   program   area   is    of    type
                            (REL,CON,CSEG).
            
            '_DATA'         This  is the default optional data area.
                            This   program   area   is    of    type
                            (REL,CON,DSEG).
            

            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
    • Philipp Klaus Krause

      That approach would have to rely on no _CODE being in crt0, and the "IIVT" _CODE being 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 as main.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.