I've found a bug that I traced back to the crt0.s having .area _GSINIT before gsinit::. This means that any code created in the _GSINIT area will be omitted.
Example code:
#include "stdio.h" #include "stdint.h" #include "string.h" uint8_t query[255]; void dosomething () { static unsigned char endquery[] = {0,0,1,0,1}; memcpy(query, endquery, 5); } /*---------------------------------------------------------------------------*/ int main(char *argv[], int argc) { dosomething (); printf ("%d,%d,%d,%d,%d",query[0],query[1],query[2],query[3],query[4]); return 0; }
This code emits 255,255,255,255,255 on my system. But it should emit 0,0,1,0,1.
The static unsigned char buffer is not being initialised allthough the compiler does generate code in the _GSINIT section.
Tracked it down here:
.area _GSINIT gsinit:: ld bc, #l__INITIALIZER ld a, b or a, c jr Z, gsinit_next ld de, #s__INITIALIZED ld hl, #s__INITIALIZER ldir gsinit_next:
If you change it to:
gsinit:: .area _GSINIT ld bc, #l__INITIALIZER ld a, b or a, c jr Z, gsinit_next ld de, #s__INITIALIZED ld hl, #s__INITIALIZER ldir gsinit_next:
The code is generated after the gsinit:: label instead of before it. This way the code behaves as expected.
no, that is incorrect. sections are concatenated in the order of appearance to the linker. and your patch will result gsinit point to some random code defined in the same section you put label in. probably that is HEADER.
ps: maybe that will work because header is ABS, but anyway, it is not a good idea. you can specify the base addresses for _GSINIT and _GSFINAL via commandline arguments for some reason and everything breaks then.