2

(Non-native speaker here, I apologize for the vague title)

I am using the compiler suite sdcc (3.7.0) to compile C code for the TI-82 STATS calculator. Its processor is a Z80. The OS provides several functions to interact with the device, for example ClrLcdScreen() at memory address 0x4755, which takes no arguments and returns nothing.

To "declare" and call that function in assembly, I can do the following:

ClrLcdScreen    equ     0x4755  ; Assembly equivalent of '#define ClrLcdScreen 0x4755'

        call    ClrLcdScreen    ; Call the function at memory address 0x4755

Now I am not sure how I can tell SDCC that there is a function at memory address 0x4755 that I want to call. How can I write just the declaration and have SDCC know where the definition can be found at runtime?

This is how I could imagine a solution to look like (Following code is not real, it is just made-up to demonstrate what I need):

__at__ 0x4755 void ClrLcdScreen(); // Function declaration

int main() {
    ClrLcdScreen();
}

I have tried calling the function using inline assembly:

#define ClrLcdFull() __asm__("call 0x4755")

int main() {
    ClrLcdFull();
}

That works, but is not what I want. With that code, I am managing the calling myself and SDCC does not know at all that I am calling a function.

kangalio
  • 652
  • 8
  • 16

1 Answers1

4

You can use function pointers. There are three things you need to do

  • create a typedef for the function pointer with correct return type and arguments
  • declare a pointer using that typedef and assign an address to the pointer
  • call the function like you would any other function

For example:

typedef void (*funcptr)(void);

int main(void)
{
    static const funcptr ClrLcdScreen = (funcptr)0x4755;

    ClrLcdScreen();
}

Here's an alternative that doesn't involve declaring a pointer variable. It just casts the address to a function pointer, and calls it.

typedef void (*funcptr)(void);
#define ClrLcdScreen ((funcptr)0x4755)

int main(void)
{
    ClrLcdScreen();
}
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • If I create a file with function pointers to all OS functions and include it, will the function pointers that I don't use in my program occupy space in my executable as well? – kangalio Jun 29 '18 at 15:55
  • 1
    @kangalioo That depends on the compiler and the optimization level. In theory, it doesn't have to occupy any space. But it might occupy space for the pointer. Using the `static` and `const` keywords might change how the compiler treats the pointer. You'll need to experiment. I've added those to the answer to demonstrate. – user3386109 Jun 29 '18 at 16:02
  • Your solution works, but I don't like one aspect about it. When I compile code calling a function pointer, the resulting binary doesn't call the function directly, but loads the address from memory into a register and then executes the function. This is a part from the disassembly: `ld hl, (_clr_lcd_full)` `call ___sdcc_call_hl` Is it possible to avoid this, so that the function is called like any other, directly? Ideally the disassembly would look like following: `call 0x4755` – kangalio Jun 29 '18 at 17:46
  • 1
    @kangalioo That's disappointing. Maybe a `#define` can be used instead of a pointer variable. I'll update the answer. – user3386109 Jun 29 '18 at 18:17
  • 1
    @kangalioo If that still doesn't call the function directly, then all that's left is to turn up the optimization level. But I'm not familiar with SDCC, so I can't offer any help on how to do that. In fact, I don't even know if SDCC *has* different optimization levels. – user3386109 Jun 29 '18 at 18:23