3

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.

eJm
  • 109
  • 2
  • 9
  • try with `volatile`. – KamilCuk Aug 31 '23 at 18:10
  • Thank you Kamil, I tried adding volatile but unfortunately same result. – eJm Aug 31 '23 at 19:08
  • 1
    Does `*(volatile unsigned short *)(0x7000) = 0xFFu;` work? – pmacfarlane Aug 31 '23 at 19:21
  • 2
    Your `ROM` and `RAM` variables presumably live in ... RAM. Are you overwriting them? – pmacfarlane Aug 31 '23 at 19:28
  • Hi, unfortunately no luck. i get a Initializer element is not a constant expression. and i've tried moving it to main to see if it changes anything but to no avail. – eJm Aug 31 '23 at 19:28
  • Yes, it would have to be in `main()`, clearly. I'd be interested to see the disassembly of that. (Not that I understand Z80 assembler...) – pmacfarlane Aug 31 '23 at 19:29
  • See: https://sourceforge.net/p/sdcc/wiki/z80/ Where do you put the stack and how? Can you get `printf` working for a hello world program? Can you get the linker to output a map? – Craig Estey Sep 01 '23 at 01:26
  • 1
    Please [edit] your question and add the linker map and the complete disassembly or listing. The snippets do not prove anything. (I understand Z80 assembler. ;-) Which system do you target? If it is not a commonly known system, please add links to its documentation. – the busybee Sep 01 '23 at 06:56
  • @thebusybee I found about z80 at https://www.zilog.com/docs/z80/um0080.pdf – Tom Sep 01 '23 at 07:23
  • @Tom I have that document on disk "since ever". ;-) And by my "socialization" I can still read a lot of hex code... All Z80 users are aware of the required information and so I left them out: memory map, specific hardware beside the CPU, ... – the busybee Sep 01 '23 at 07:27

1 Answers1

0

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

eJm
  • 109
  • 2
  • 9
  • Nice. Glad to see that "unsigned char *" in both the declaration and cast were at least part of the fix. Thanks for you post. I learned more about the Z80 architecture and it brought back a lot of fond memories... writing directly to video and BIOS memory, and such. I miss it a lot! So fast... – greg spears Sep 03 '23 at 04:36