016
28.08.2021, 14:47 Uhr
Bert
|
@Volker, das ist alles gerade erst im Entstehen. Aber hier mal das, was ich bisher habe:
Das Makefile
Quellcode: | # Makefile PREFIX=WINEARCH=win32 WINEPREFIX=~/.wine32 wine ~/.wine32/drive_c/Z8/bin/
CC=$(PREFIX)z8cc.exe LINK=$(PREFIX)z8link.exe ASM=$(PREFIX)z8asm.exe
all: main.ihx
main.obj: main.c $(CC) -model=S "main.c"
main.ihx: main.obj startup.obj $(LINK) -color @main.lnk
startup.obj: startup.asm $(ASM) startup.asm
|
Der Startup-Code ist wahrscheinlich noch unvollständig, da ich nicht die initialisierten Variablen umkopiere. Außer dem Vorspann passiert da nix:
Quellcode: | ; startup.asm XDEF _c_startup XREF _main:ROM segment CODE _c_startup:
; Tiny-Basic-Token ; to help start the program with '+' (RUN) DB $80, 1, 'C%E010', $0d DB $80, 2, 'E', $0d BLKB 3, 0
CALL _main RET END _c_startup
|
Das Linkerskript ist auf die Adressen vom tiny2k eingestellt:
Quellcode: | -format = INTEL
"main" = "startup","C:\Z8\rtl\crtls.lib","C:\Z8\rtl\fpdumys.obj","main.obj" ORDER FAR_DATA,TEXT CHANGE TEXT = FAR_DATA RANGE ROM $e000 : $e3ff RANGE XDATA $fd80 : $fdff RANGE RDATA $20 : $4f COPY NEAR_DATA ROM COPY FAR_DATA ROM define _low_near_romdata = copy base of NEAR_DATA define _low_neardata = base of NEAR_DATA define _len_neardata = length of NEAR_DATA define _low_far_romdata = copy base of FAR_DATA define _low_fardata = base of FAR_DATA define _len_fardata = length of FAR_DATA define _low_nearbss = base of NEAR_BSS define _len_nearbss = length of NEAR_BSS define _low_farbss = base of FAR_BSS define _len_farbss = length of FAR_BSS define _far_heaptop = top of XDATA define _far_stack = highaddr of XDATA define _near_stack = highaddr of RDATA define _far_heapbot = base of XDATA + length of FAR_BSS + length of FAR_DATA
|
Und dann noch ein kleines Hello-World:
Quellcode: | #include <z8.h> #include <stdio.h>
/* * near -> rdata = register file * far -> edata = external memory */
// no inttype.h, no stdint.h typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; typedef unsigned short uint16_t;
#define TINY_CHR (*(unsigned char near volatile *)0x5a) #define TINY_POS (*(unsigned char near volatile *)0x5b)
void clear_screen( void) { asm( "call %08dd"); // cls, geht }
void cursor_home( void) { TINY_POS = 0; }
void putc( char c) { TINY_CHR = c; asm( "call %0827"); // cbs }
int puts( char near *s) { while( *s) { putc( *s); s++; } }
char key( void) { asm( "call %0c1b"); // tsk return TINY_CHR; }
char digit2hex( uint8_t digit) { char result;
result = digit < 10 ? '0' : 'A' - 10; result += digit; return result; }
void main( void) { far uint8_t * bws = (far uint8_t *) 0xFE00; uint8_t dat;
char str[] = "HALLO JU+TE";
clear_screen(); puts( str);
dat = key(); putc( digit2hex(dat >> 4)); putc( digit2hex(dat & 0xF)); dat = key(); }
|
Die fertige ihx-Datei läßt sich direkt im neuesten JTCEMU laden und mit '+' starten. Bis zum printf bin ich noch nicht gekommen, ich weiß auch noch nicht, ob ich es verwenden will. Je nach Implementierung braucht printf zwischen 2 bis 8 kByte. Das ist auf einem aktuellen STM32 mit 128k Flash natürlich kein Problem. Hier ggf. schon.
@Steffen: Vielen Dank für den Z8CC und die Beispielcodes für das UB88xx-Testboard. Da habe ich mir auch Inspirationen geholt.
Viele Grüße, Bert
@P.S.: Das wäre eigentlich auch gleich eine gute Übung für github... |