;; ---------------------------------------------------------------------- ;; crt0_minimal.s — Sprinter ESTEX C runtime startup, no argv parsing. ;; ;; This is the opt-out variant for programs where every byte counts. ;; The DEFAULT runtime is runtime/crt0.s which also parses argv from the ;; ESTEX command line and passes argc/argv to main(). ;; ;; To use this instead of the default: ;; crt0.rel: $(PROJ_ROOT)/runtime/crt0_minimal.s ;; $(SDASZ80) -o $@ $< ;; ;; Otherwise identical to crt0.s — saves IX, calls gsinit, calls main ;; with no arguments, then EXIT via ESTEX $41. ;; ---------------------------------------------------------------------- .module crt0_minimal .globl _main ;; Linker-emitted symbols for areas (resolved at link time). .globl s__INITIALIZER .globl l__INITIALIZER .globl s__INITIALIZED .globl s__BSS .globl l__BSS ;; ========================================================================= ;; AREA ORDERING — emitted up-front so the linker walks them in this order. ;; ========================================================================= .area _HOME .area _CODE .area _INITIALIZER .area _GSINIT .area _GSFINAL .area _DATA .area _INITIALIZED .area _BSEG .area _BSS .area _HEAP ;; ========================================================================= ;; Entry point — first instruction in _CODE, hence at --code-loc (0x4100). ;; ========================================================================= .area _CODE _start:: ;; ESTEX already set SP from the EXE header, but make it explicit. ld sp, #0xBFFE ;; Save startup prefix (IX) for argv/exit-code helpers. ld (_estex_startup_ix), ix ;; Run SDCC global initialisers (concatenated into _GSINIT). call gsinit ;; Hand off to user main. call _main ;; SDCC 4.5 __sdcccall(1): int return is in DE, so low byte of main()'s ;; return is in E. (See memory/sdcc_z80_abi.md.) ;; main returned — terminate via ESTEX EXIT directly. We do NOT ;; expose a _exit symbol; programs that need exit() / atexit() must ;; link libc/io/atexit.c. ld a, e ld b, a ld c, #0x41 ; ESTEX EXIT rst #0x10 1$: halt jr 1$ ;; ========================================================================= ;; Runtime data ;; ========================================================================= .area _DATA _estex_startup_ix:: .ds 2 ;; ========================================================================= ;; gsinit — copy _INITIALIZER -> _INITIALIZED, then zero _BSS. ;; SDCC appends per-unit init code between this label and the ret in _GSFINAL. ;; ========================================================================= .area _GSINIT gsinit:: ;; --- Copy _INITIALIZER -> _INITIALIZED if non-empty --- ld bc, #l__INITIALIZER ld a, b or a, c jr Z, gsinit_bss ld de, #s__INITIALIZED ld hl, #s__INITIALIZER ldir gsinit_bss: ;; --- Zero _BSS if non-empty --- ld bc, #l__BSS ld a, b or a, c jr Z, gsinit_done ld hl, #s__BSS ld (hl), #0 dec bc ld a, b or a, c jr Z, gsinit_done ld d, h ld e, l inc de ldir gsinit_done: .area _GSFINAL ret