SDCC assign memory address to pointer, no effect

172 Views Asked by At

I've been mulling over this for the last couple of days, and i cant see what is wrong with my code. Really just looking to assign two memory addresses to two pointers. ROM at 0x0000 and RAM at 0x7000. The program compiles, but instead of writing 'mydata' to the RAM location 0x7000, it instead writes zeros to the 0x0000 location, the code is below:

    unsigned short *ROM = (unsigned char*)(0x0000);     //these have no effect, always accesses 0x0000, assignment fails
    unsigned short *RAM = (unsigned char*)(0x7000);     //these have no effect, always accesses 0x0000, assignment fails

    //__at (0x0000) unsigned char *ROM;     //these have no effect, always accesses 0x0000, assignment fails
   //__at (0x7000) unsigned char *RAM;      //these have no effect, always accesses 0x0000, assignment fails
    
    unsigned char mydata[]={0xFF, 0xFE,0xCE,0xD1,0xFF, 0x1E,0x2E,0x31,0x4F, 0x5E,0x6E,0xD7,0x8F, 0xF9,0xAE,0x11};
    int main(){
        
    unsigned char bytecount=0;
    int n=0;
    for(n=0;n<16;n++)RAM[n]=mydata[n];
            
    return 0;
    }

Wondering if anyone has experienced this or a similar problem and has any ideas what could be wrong. I considered the compiler options where the code is placed at 0x0100 and the data at 0xA000. However it shouldnt affect the outcome though. This is a z80 compile.

interestingly, note that i have unsigned short, the erasing with zeros happens in pairs then after a cycle, the next pair of bytes are erased, and so on.. changing this to unsigned char results in single bytes being erased.

within the assembled output, there is a load HL register pair with the address A003, which I can't seem to attribute to any kind of variable in my program. there is no definition at A003 yet the compiled program is accessing it.

  000000                        232 __xinit__ROM:
  000000 00 00                  233     .dw #0x0000
  000002                        234 __xinit__RAM:
  000002 00 70                  235     .dw #0x7000

  000004                        236 __xinit__mydata:
 

the result

ld hl, 0A003 (results in value 0x0000)
...
ld (hl),a (a is always 0, this is written to location 0x0000, 0x0001, and so on).

Thanks in advance.

1

There are 1 best solutions below

1
eJm On

I'd posted a follow up comment earlier this morning but it doesnt seem to appear. I've got the program working by moving the initialisation of the RAM and ROM pointers to within the main program, instead of globally. Also I'd changed the unsigned char mydata to a const (but this aspect wasnt the issue i'd posted about, but still necessary).

unsigned char *ROM;  //initialisation moved to main
unsigned char *RAM;  //initialisation moved to main

const unsigned char mydata[16]={0xFF, 0xFE,0xCE,0xD1,0xFF, 0x1E,0x2E,0x31,0x4F, 0x5E,0x6E,0xD7,0x8F, 0xF9,0xAE,0x11};
int main(){
    
    ROM = (unsigned char*)(0x0000);
    RAM = (unsigned char*)(0x7000);
    __asm
    DI
    ;;puts the stackpointer at the top of the 8k ram area (ram starts at 0xA000 and 8191 bytes later is 0xBFFF)
    ld  sp,#0xBFFF
    __endasm;
    
    
    unsigned char n=0;

    for(n=0;n<16;n++)RAM[n]=mydata[n];

    return 0;
}

looking at the compiled assembly code in each case here is the working based on above:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 4.1.0 #12072 (MINGW64)
;--------------------------------------------------------
    .module test
    .optsdcc -mz80
    
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
    .globl _main
    .globl _RAM
    .globl _ROM
    .globl _mydata
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
    .area _DATA
                                                         
          
                                                         
                   
_ROM::
    .ds 2
_RAM::
    .ds 2
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
    .area _INITIALIZED
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
    .area _DABS (ABS)
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
    .area _HOME
    .area _GSINIT
    .area _GSFINAL
    .area _GSINIT
;--------------------------------------------------------
; Home
;--------------------------------------------------------
    .area _HOME
    .area _HOME
;--------------------------------------------------------
; code
;--------------------------------------------------------
    .area _CODE
;test.c:17: int main(){
;   ---------------------------------
; Function main
; ---------------------------------
_main::
;test.c:19: ROM = (unsigned char*)(0x0000);
    ld  hl, #0x0000
    ld  (_ROM), hl
;test.c:20: RAM = (unsigned char*)(0x7000);
    ld  h, #0x70
    ld  (_RAM), hl
;test.c:25: __endasm;
    DI
;;puts  the stackpointer at the top of the 8k ram area (ram starts at 0xA000 and 8191 bytes later is 0xBFFF)
    ld  sp,#0xBFFF
;test.c:43: for(n=0;n<16;n++)RAM[n]=mydata[n];
    ld  c, #0x00
00102$:
    ld  hl, (_RAM)
    ld  b, #0x00
    add hl, bc
    ld  a, #<(_mydata)
    add a, c
    ld  e, a
    ld  a, #>(_mydata)
    adc a, #0x00
    ld  d, a
    ld  a, (de)
    ld  (hl), a
    inc c
    ld  a, c
    sub a, #0x10
    jr  C, 00102$
;test.c:52: return 0;
    ld  hl, #0x0000
;test.c:53: }
    ret
_mydata:
    .db #0xff   ; 255
    .db #0xfe   ; 254
    .db #0xce   ; 206
    .db #0xd1   ; 209
    .db #0xff   ; 255
    .db #0x1e   ; 30
    .db #0x2e   ; 46
    .db #0x31   ; 49    '1'
    .db #0x4f   ; 79    'O'
    .db #0x5e   ; 94
    .db #0x6e   ; 110   'n'
    .db #0xd7   ; 215
    .db #0x8f   ; 143
    .db #0xf9   ; 249
    .db #0xae   ; 174
    .db #0x11   ; 17
    .area _CODE
    .area _INITIALIZER
             
            
             
            
    .area _CABS (ABS)

and here is the non-working assembly previously where attempted global initialize of pointers:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 4.1.0 #12072 (MINGW64)
;--------------------------------------------------------
    .module test
    .optsdcc -mz80
    
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
    .globl _main
    .globl _RAM
    .globl _ROM
    .globl _mydata
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
    .area _DATA
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
    .area _INITIALIZED
_ROM::
    .ds 2
_RAM::
    .ds 2
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
    .area _DABS (ABS)
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
    .area _HOME
    .area _GSINIT
    .area _GSFINAL
    .area _GSINIT
;--------------------------------------------------------
; Home
;--------------------------------------------------------
    .area _HOME
    .area _HOME
;--------------------------------------------------------
; code
;--------------------------------------------------------
    .area _CODE
;test.c:17: int main(){
;   ---------------------------------
; Function main
; ---------------------------------
_main::
;test.c:25: __endasm;
    DI
;;puts  the stackpointer at the top of the 8k ram area (ram starts at 0xA000 and 8191 bytes later is 0xBFFF)
    ld  sp,#0xBFFF
;test.c:43: for(n=0;n<16;n++)RAM[n]=mydata[n];
    ld  c, #0x00
00102$:
    ld  hl, (_RAM)
    ld  b, #0x00
    add hl, bc
    ld  a, #<(_mydata)
    add a, c
    ld  e, a
    ld  a, #>(_mydata)
    adc a, #0x00
    ld  d, a
    ld  a, (de)
    ld  (hl), a
    inc c
    ld  a, c
    sub a, #0x10
    jr  C, 00102$
;test.c:52: return 0;
    ld  hl, #0x0000
;test.c:53: }
    ret
_mydata:
    .db #0xff   ; 255
    .db #0xfe   ; 254
    .db #0xce   ; 206
    .db #0xd1   ; 209
    .db #0xff   ; 255
    .db #0x1e   ; 30
    .db #0x2e   ; 46
    .db #0x31   ; 49    '1'
    .db #0x4f   ; 79    'O'
    .db #0x5e   ; 94
    .db #0x6e   ; 110   'n'
    .db #0xd7   ; 215
    .db #0x8f   ; 143
    .db #0xf9   ; 249
    .db #0xae   ; 174
    .db #0x11   ; 17
    .area _CODE
    .area _INITIALIZER
__xinit__ROM:
    .dw #0x0000
__xinit__RAM:
    .dw #0x7000
    .area _CABS (ABS)

Apologies for the lengthy code, but to highlight the differences between the two: in the 'working' version, the text .area _INITIALIZED is moved away from the .area_data where the _rom and _ram are defined as .ds 2.

line 59 shows these then being initialised which is within the main program:

main::
;test.c:19: ROM = (unsigned char*)(0x0000);
    ld  hl, #0x0000
    ld  (_ROM), hl
;test.c:20: RAM = (unsigned char*)(0x7000);
    ld  h, #0x70
    ld  (_RAM), hl

However if you look at the non working code, there is no such initialisation, as it is assumed globally. instead there is a bit of code in the .area _INITIALIZER which looks like

.area _INITIALIZER
__xinit__ROM:
    .dw #0x0000
__xinit__RAM:
    .dw #0x7000

This may not translate into any kind of binary, thus it doesnt initialise on the z80. Also for reference my compiler line is :

sdcc -mz80 --code-loc 0x0000 --no-std-crt0 --data-loc 0xA000 test.c

I'd wondered perhaps if the insertion of --no-std-crt0 might have prevented the init, but switching this out makes the program fail completely.

Regards