Istnieje niekomercyjny pakiet oprogramowania pozwalający na tworzenie programów między innymi dla mikrokontrolerów Z80. Jest to pakiet SDCC (ang Small Device C Compiler) i pozwala na tworzenie kodu binarnego dla kilku mikroprocesorów oraz mikrokontrolerów. Pakiet ten (plik o nazwie sdcc-3.6.0-setup.exe) można pobrać ze strony http://sdcc.sourceforge.net/snap.php. Instalacja pakietu pod windozą nie sprawia żadnych problemów. Jest tylko jedna sugestia: warto przy instalacji określić inne miejsce docelowe niż jest proponowany (przy instalacji proponowany jest katalog c:\Program files\sdcc). Ja podałem następujące miejsce docelowe: e:\sdcc (wynika to z tego, że w pakiecie nie ma elementu typu IDE i, w fazie eksperymentów posługiwałem się plikami typu BAT do uruchamiania kompilatora; w przyszłości trzeba będzie pochylić się nad systemem MAKEFILE lub czymś podobnym, obecnie w fazie eksperymentów posługuję się plikami typu BAT a spacja w nazwie kartoteki C:\Program Files znaczące w tym przeszkadza). Po instalacji w e:\sdcc\doc znajduje się elementarna dokumentacja sdccman.pdf.
O liście dostępnych procków można przekonać się realizując „zapytanie do pakietu”: sdcc –version.
Na liście znajduje się między innymi Z80 → główny powód zainteresowania pakietem.
Pierwszy program dla proca Z80. Za pomocą dowolnego edytora plików tekstowych utworzony zostaje plik o nazwie test1.c o następującej zawartości.
Kod: Zaznacz cały
int GloblVar ;
main ( )
{
unsigned short j ;
unsigned short n ;
/*---------------------------------------------------*/
while ( 1 )
{
n = 1 ;
for ( j = 0 ; j < 4 ; j++ )
{
GloblVar = n ;
n <<= 1 ;
} /* for */ ;
n = 0x80 ;
for ( j = 0 ; j < 4 ; j++ )
{
GloblVar = n ;
n >>= 1 ;
} /* for */ ;
} /* while */ ;
} /* main */
Nie jest istotne co program robi, im jest prostszy, tym łatwiej poznać filozofię pakietu. Głównym celem takiego program jest poznanie co i jak zostało zrobione.
Do kompilacji utworzony jest plik o nazwie cc.bat o następującej zawartości:
Kod: Zaznacz cały
e:\sdcc\bin\sdcc -mz80 --data-loc 0x8000 test1.c
Polecenie to nakazuje wygenerować binarną wersję program dla mikroprocesora z80 (parametr: -mz80), w którym pamięć ram znajduje się w przestrzeni adresowej od adresu 8000H do adresu FFFFH → będziemy udawać, że w systemie z Z80 znajduje się RAM typu 62256 (Static RAM o wielkości 32kB), tekst programu znajduje się w pliku o nazwie test1.c. Ponieważ Z80 po resecie rusza od wykonania instrukcji spod adresu 0000H, w domyśle z przestrzeni od adresu 0000H do adresu 7FFFH znajduje się pamięć EPROM przeznaczona na kod programu. By uruchomić kompilację, należy uruchomić w kartotece program cmd.exe (gdzie znajduje się program źródłowy test1.c). Tam należy uruchomić makropolecenie cc.bat.
Po pierwszej kompilacji widać, że pakiet działa w ten sposób, że przetwarza program napisany w języku C na program napisany w języku assebler i ten docelowo jest kompilowany i linkowany (do programu jest dolinkowana część rozruchowa o nazwie crt0.rel, którą można odnaleźć w strukturze kartoteki e:\sdcc.
W wyniku działania kompilatora powstają między innymi pliki:
- test1.asm – przetłumaczony na asembler program w języku C,
- test1.ihx – wynikowy program w zapisie intel-hex (pliki o rozszerzeniu IHX zawierają wygenerowany kod w zapisie intel-hex),
- test1.lst – listing z kompilacji programu asemblerowego,
- test1.map – wydruk zawierający informacje o przydzielonych adresach dla poszczególnych elementów programu (w sensie nazw segmentów),
- test1.rel – wynik kompilacji (jako półkompilat), który jest „obrabiany” przez linker (pliki o rozszerzeniu REL są wynikiem kompilacji i są w formacie tekstowym i można je sobie przeglądać).
Kod: Zaznacz cały
ASxxxx Linker V03.00 + NoICE + sdld, page 1.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ------------
. .ABS. 00000000 00000000 = 0. bytes (ABS,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
00000000 .__.ABS. test1
00000000 l__BSEG
00000000 l__BSS
00000000 l__CABS
00000000 l__DABS
00000000 l__HEADER
00000000 l__HEAP
00000000 l__HOME
00000000 l__INITIALIZED
00000000 l__INITIALIZER
00000000 s__CABS
00000000 s__DABS
00000000 s__HEADER
00000000 s__HEADER0
00000000 s__HEADER1
00000000 s__HEADER2
00000000 s__HEADER3
00000000 s__HEADER4
00000000 s__HEADER5
00000000 s__HEADER6
00000000 s__HEADER7
00000000 s__HEADER8
00000001 l__GSFINAL
00000002 l__DATA <<< wielkość segmentu DATA (obszaru zmiennych globalnych)
00000002 l__HEADER1
00000002 l__HEADER2
00000002 l__HEADER3
00000002 l__HEADER4
00000002 l__HEADER5
00000002 l__HEADER6
00000002 l__HEADER7
00000003 l__HEADER0
0000000C l__HEADER8
0000000F l__GSINIT
00000032 l__CODE
00000200 s__CODE
00000232 s__GSINIT
00000232 s__HOME
00000232 s__INITIALIZER
00000241 s__GSFINAL
00008000 s__DATA <<< początek segmentu DATA (adres w przestrzeni adresowej)
00008002 s__BSEG
00008002 s__BSS
00008002 s__HEAP
00008002 s__INITIALIZED
ASxxxx Linker V03.00 + NoICE + sdld, page 2.
Hexadecimal [32-Bits]
Area Addr Size Decimal Bytes (Attributes)
-------------------------------- ---- ---- ------- ----- ----------
_CODE 00000200 00000032 = 50. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
00000200 __clock crt0
00000204 _exit crt0
0000020A _main test1
(…)
User Base Address Definitions
_CODE = 0x0200
_DATA = 0x8000
Z grubsza wszystko się zgadza. Pozostało sprawdzić działanie programu. W tym celu został użyty pakiet AVSIMZ80. W okienku program cmd.exe uruchomiony zostaje program avsimz80.exe.
Do symulacji należy wybrać wariant A (sam procesor, bez urządzeń peryferalnych). W pierwszej kolejności należy załadować symulowany program L [od Load] P (od Program) i podać nazwę pliku test1.ihx. Później „podłączyć” pamięć RAM: S [od Set], M [od Memory-map], A [od random-Access] i wpisać: m:8000h <enter> oraz później m:ffffh <enter>). To spowoduje utworzenie przestrzeni pamięci RAM od adresu 8000 hex do FFFF hex. Program gotowy jest do symulacji.
Jak widać, po resecie, procesor Z80 ma do wykonania instrukcję bezwarunkowego skoku pod adres 100 hex. Klawiszem F10 można wykonać pojedynczą instrukcję symulowanego programu.
Kolejną instrukcją jest załadowanie wskaźnika SP stałą o wartości 0. Tutaj sięgam do opisu instrukcji mikroprocesora Z80. W dokumentacji jest napisane, że instrukcja CALL (również wszelkie instrukcje PUSH) najpierw dekrementują wskaźnik stosu a następnie realizują zapis odpowiednich danych na stosie. Implikuje to, że to rozwiązanie zadziała poprawnie w każdym przypadku, gdzie pamięć RAM kończy się na adresie FFFF hex, czyli standardowa część rozruchowa (crt0.rel) jest właściwa w takich przypadkach. Kolejna instrukcja (CALL 232 hex) ma za zadanie zainicjowanie stałych obszarów zmiennych (w tym konkretnym przypadku nie ma inicjowanego obszaru, więc następuje szybki powrót). Kolejna instrukcja CALL 20A hex jest wywołaniem funkcji main. Rzeczywiście, program zrobił 4 obroty pierwszej pętli i 4 obroty drugiej pętli. Zadziałał, jak było napisane.
Załącznik: test1.zip