1

I am working on coding a driver of sorts for a Z80 based computer I am making. I am compiling with SDCC and I have been getting the following?

ASlink-Warning-Undefined Global 'data' referenced by module 'main'

I am essentially trying to access a c variable (function parameter) through inline assembly without messing with the stack (I would prefer solutions that don't involve the stack, but if that is the only way I would greatly appreciate you explaining how to do this and how it works with as much detail as possible and do an example for me). I am currently trying to use something like this: ld A, (varname) and it is throwing the error above.

I appreciate your help in advance :)

Edit: A bit more info: I am compiling for the Z80 Processor and I am using the SDCC compiler on MacOS. The command I am using is: sdcc -mz80 --no-std-crt0 --vc --code-loc 0x0 src/main.c

And here is the code that is causing the error. It is in a file called pio.c and is connected to pio.h which I have attached to my main code by an include statement.

Pio.c:

#include "../../include/stdint.h"
#include "pio.h"

typedef struct pio
{
    uint8_t portA;
    uint8_t portB;
    void (*init)(char reg, uint8_t control);
    void (*load)(char reg, uint8_t data);
} PIO;
void init(char reg, uint8_t control){
    switch(reg){
        case 'A':
            __asm
                LD iy,#2
                ADD iy,sp
                LD A, 1(iy)
                OUT (0x13), A /*Output register a to the address 0000000000010011 */
            __endasm;
            break;
        case 'B':
            __asm
                OUT (0x9), A  /*Output register a to the address 000000000001001*/
            __endasm;
            break;
    }
}
void load(char reg, uint8_t data){
    switch(reg){
        case 'A':
             __asm
                mov A, data
                OUT (0x12), A /*Output register a to the address 0000000000010010*/
            __endasm;
            break;
        case 'B':
             __asm
                LD A, (IX)
                OUT (0x8), A /*Output register a to the address 0000000000010000*/
            __endasm;
            break;
    }
}

And here is Pio.h

/*
 * pio.h
 *
 *  Created on: 2020. 7. 28.
 *      Author: me
 *      LIB_PIO_PIO_H_
 */

#ifndef PIO_H
#define PIO_H
#include "pio.c"

extern void init(char reg, uint8_t control);
extern void load(char reg, uint8_t control);

#endif /* LIB_PIO_PIO_H_ */

An additional note, I know my first line of pio.c is for stdint in a higher folder. For some reason, the compiler won't see it if I just do a normal include, so I decided to copy all of the include files into my project directory. It is not great practice, but I just want it to work at this point.

  • 2
    I think this is easier to answer if you supply more information, like: exact code that is failing, what command line are you using and maybe what system are you compiling for. – UncleBod Jul 30 at 13:10
  • Hello there, I updated the post to include my code and a bit more information. Hopefully it helps :) – benjamin black Jul 30 at 13:18
  • 1
    Which line is line 74? This: mov A, data? There is no 'mov' instruction on Z80. – tum_ Jul 30 at 13:26
  • Ok, so I went and switched it to LD A, (data) and it says, "Global 'data' referenced by module 'main'". I will update that in the post! I have been using a lot of different sources and just trying to see what works. I wasn't aware of that fact about the Z80. Anyways, the LD method is still not working and I updated the post to reflect that. – benjamin black Jul 30 at 13:49
5

The problem is that you're trying to access the function parameter data, but the compiler does not expose that as a symbol to the internal assembler, so it's looking in the public, global namespace for it -- and can't find it.

According to SDCC - Interfacing with Z80 assembler code, you do indeed need to access the parameters from the stack. I don't know if there are options to the compiler to not push the function parameter on to the stack.

Parameters for the function are pushed to the stack before the function is called. They are pushed from right to left, so the leftmost parameter is the first one found when going up in the stack:

char SumTwoChars(char x, char y) __naked
{
    __asm
    ld iy,#2
    add iy,sp ;Bypass the return address of the function 

    ld l,(iy)   ;x
    ld a,1(iy)  ;y

    add l
    ld l,a      ;return value

    ret
    __endasm;
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.