How does C programming work with no headers?

293 views Asked by At

I'm familiar with the C programming language and z80 assembly and I have made a simple z80 "computer" with just the cpu with 32k of ram, 32k of rom, and an 8255 pia for io control. I have gotten the 8255 to bling an LED with my system through an assembly language subroutine.

So the question is: If there is the SDCC(Small Device C compiler) that can compile a C program into assembly for various small CPUs including the z80, How do you create a C program if there are no stdio libraries or any libraries of any kind because of how custom this system is. Am i forced to use assembly first then make and call a function as an ASM routine? Am I misunderstanding some sort of key idea? Im quite confused on how this works. I cant just printf() on a system with no output. Not to mention printf() is under the assumption that a terminal is connected of some kind.

2

There are 2 answers

0
Clifford On

You would write a platform specific I/O library that utilises whatever I/O capability your platform has available. On many embedded systems a minimal standard I/O is implemented on a UART serial port so your "console" can be a terminal emulator on a host PC.

Your I/O API need not be as sophisticated as the standard library's stdio. It also need not be written in assembler, register-level access of memory-mapped peripherals is possible (in fact normal) in C - it is a systems level language after all.

All that said, SDCC already includes a standard library subset that includes a subset stdio. So it is not clear why you think you lack that support. You do have to provide low level platform specific support, but to support printf you need only implement putchar() to emit a character on your chosen stdout device. For unbuffered serial output that is rather trivial. A more sophisticated implementation might use interrupt driven, buffered serial output. The porting of the library is described in the SDCC manual.

0
Stefan Paul Noack On

You are right. An assembly routine contains the actual entry point, where memory initialization is done, and that routine then calls main().

sdcc/device/lib/z80/crt0.s contains the default startup code provided by SDCC.

If your system needs more stuff to be done than that provides, refer to section 3.12.3 of the SDCC manual on how to supply your own.

As for printf(), you just need to supply putchar() somehow. If it's simply an out instruction to some device, you can just chuck it in the crt0.s as well, like this:

    .area   _CODE
init:
    call    0x01B0 ; ROM_CLEAR_SCREEN    
    ;; Initialise global variables
    call    gsinit
    call    _main
_exit:
    call    0x0200 ; ROM_GET_KEY
    jr      z, _exit
    call    0x01B0 ; ROM_CLEAR_SCREEN
    ret
_putchar:
    ld      hl, #2
    add     hl, sp
    ld      a, (hl)
    out     (0xBC), a
    ld      hl, #0
    ret