cc65 - C crosscompiler

Jiří Svoboda

Začalo to nevinně. Jednoho dne se v naší prostějovské konferenci objevil e-mail od Radka Štěrby s jedinou krátkou poznámkou ve smyslu "O tomhle jsme se bavili ve ZBAKu" (což už je oficiální termín pro schůzky Atariklubu, konané u Zdeňka Buriana; já tam tentokrát nebyl) a link vedoucí na http://www.cc65.org. Tam jsou domovské stránky programu, nad jehož neexistencí jsem si dříve již několikrát posteskl a protože jsem ani nepředpokládal, že by snad mohl existovat, nikdy mne nenapadlo jej hledat.

O co jde?

Jde o volně šiřitelný křížový kompilátor jazyka C pro stroje postavené na procesorech 6502.

Termín křížový kompilátor - crosscompiler - vyjadřuje, že kompilátor generuje kód pro odlišnou platformu (typicky jiný CPU), než na které sám běží. Pro nás to prakticky znamená možnost programovat v jazyce C pro naše malé Atari, ale využít přitom všech výhod, které skýtají daleko modernější stroje. Píšete svůj program v komfortnějším prostředí modernějšího počítače, přímo tam jej překládáte (je to rychlé, při chybách nemusíte neustále znovu nahrávat jednotlivé části systému - editor, překladač, linker, ... z diskety či ramdisku) a až výsledný kód přenesete na malé Atari, kde jej spustíte. Samozřejmě si jej napřed můžete vyzkoušet v emulátoru.

Můj první pokus

V roce 1994 jsem pro magazín FLOP, přesněji pro kurz jazyka C v tomto magazínu, napsal kratičkou textovku v jazyce C. Jmenovala se DUUM. Byla napsána ve standardním C a díky tomu jsem ji beze změn postupně úspěšně přeložil pro Amigu, Atari ST i PC (OS Microsoftu i Linux). Na malém Atari jsme tehdy používali Deep Blue C, ovšem to na překlad nestačilo. Pokud si dobře pamatuji, problémy tehdy byly s absencí struktur. Se Zdeňkem Burianem jsme tehdy zkoušeli ještě jeden překladač, ten struktury uměl, ale zase nebyl dostatek paměti pro překlad tak "rozsáhlého" programu.

V cc65 se sice první překlad nezdařil (musel jsem odstranit lomítka, která umožňují pokračovaní logického řádku na dalším fyzickém řádku), ale již druhý překlad proběhl bez chyby a získal jsem funkční aplikaci pro malé Atari. Příjemným překvapením bylo, že zatímco zdrojový kód měl cca. 10kB, výsledný kód byla cca. o 1kB menší.

Kde se to vzalo?

cc65 je kompilátor jazyka C, původně přizpůsobený pro počítače Atari Johnem R. Dunningem. Je to následník jazyka Small C s několika rozšířeními a odstraněnými některými limity.

Protože u nás ve ZBAKu vznikly okolo původu tohoto programu drobné nejasnosti, opakuji, že tento kompilátor JE původně program pro malé Atari a JE tak také stále k dispozici. Je to navíc onen tajemný, v předchozím odstavci zmíněný "ještě jeden překladač".

Co to (ne)umí?

Kompilátor je téměř ISO C kompatibilní, z jeho omezení vybírám:

V závislosti na systému, pro který je překlad prováděn, mohou existovat další limity (viz. níže).

Vlastností, se kterou je také nutno počítat, je to, že kompilátor neoptimalizuje. Jako v dávných dobách při programování na PC musí programátor přemýšlet (pokud tedy chce produkovat kvalitní kód), co jak kompilátor přeloží. Prakticky to např. znamená nepoužívat při procházení polem běžný index (který se při každém průchodu znovu počítá), ale využít ukazatele. Rychlost výsledného kódu se tím dramaticky zvýší.

Kompilátor není všechno

To rozhodně ne! Pokud se trošku zabýváte programováním, jistě pochopíte, že by to bylo trošku málo. Takže co všechno se v balíku nachází?

Build (sestavení)

Vlastní sestavení výsledného spustitelného programu probíhá minimálně ve třech krocích. V prvním kroku překladač cc65 přeloží zdrojový kód jazyka C (soubor.c) do zdrojového kódu assembleru (soubor.s), v druhém assembler tento soubor přeloží do binární podoby (soubor.o). V posledním kroku linker připojí k výslednému kódu na platformě závislý spouštěcí kód (v našem případě atari.o) a knihovny (základ je atari.lib, ale můžete mít i svoje). Tím je sestavení hotovo a získáváme na Atari spustitelný kód.

V grafickém znázornění by to vypadalo takto (kompilujeme soubor "hello.c"):

+---------+
| hello.c |
+---------+
     |
    cc65
     |
+---------+
| hello.s |
+---------+
     |
    ca65
     |
+---------+  +---------+  +---------+
| hello.o |  | atari.o |  |atari.lib|
+---------+  +---------+  +---------+
     |            |            |
    ld65----------+------------+
     |
+---------+
|  hello  |
+---------+

Samozřejmě je možné vytvořit si vlastní .o soubory (třeba s obrázky, texty atp.) a připojit je k programu také. Z více souborů .o si můžete vytvořit vlastní knihovnu (.lib). Není to zbytečně složité?

Možná to tak vypadá, ale nikdo po vás nechce, abyste všechny kroky prováděli ručně. Zjednodušující možnosti jsou hned dvě. První spočívá v použití frontendu, programu cl65, kterým můžete všechny potřebné kroky udělat jedním povelem. A druhá? Ti z vás, kteří nezůstali pouze ve světě osmibitů, určitě zavýsknou. Příkaz "make" a jeho "Makefile". Děsící se uživatele musím uklidnit, že příslušné "Makefile" je o poznání jednodušší než třeba u zdrojáků Linuxového kernelu...

Jenom Atari?

Ne, Atari není jediný počítač s CPU řady 65xx. Kód tedy můžeme kromě Atari překládat i pro několik počítačů Commodore a počítač Apple . I když však byl crosskompiler z původního překladače přepracováván pro použití s Commodore 64, tak díky tradičně skvělé práci Atari programátorů je podpora File I/O dostupná pouze pro Atari systémy. Prakticky to pro ostatní systémy znamená nedostupnost spousty klíčových funkcí (např. printf) a nutnost obcházení této slabiny (pro všechny systémy alespoň existuje knihovna conio, která řeší vstup z klávesnice a výstup na obrazovku). To výrazně snižuje použitelnost překladače. Pro méně zasvěcené zde doplňuji, že to není vlastnost či chyba překladače ale jde jen o (ne)dostupnost příslušných knihoven. Naštěstí se to nás, ataristů, netýká.

Na čem můžu kompilovat?

Určitě na strojích s operačními systémy Linux, DOS, Windows, OS/2, FreeBSD, BeOS a Irix. Protože je však celý projekt dostupný i ve zdrojových kódech, neměl by být problém zkompilovat crosscompiler i pro jiné platformy (Atari ST). Autor (autoři) sám uvádí, že celý kód je s jedinou výjimkou (funkce access()) čisté ISO C.

Já sám jsem crosscompiler kompiloval ze zdrojových kódů na svém oblíbeném OS Linux, redakční kolega Robert Petružela zkoušel hotové binárky pro Windows.

Na co jsme přišli při "hraní"

Crosscompiler sám nepřekládá přímo do spustitelného kódu, ale jeho výstupem je zdrojový kód pro assembler (jak bylo zmíněno výše). Je zajímavé sledovat, jak jsou C konstrukce překládány, pokud se vám je podaří v kódu nalézt. Nic pro normální lidi. :-)

Tisk znaku "b" (backspace) funkcí printf() není korektní, místo vymazání znaku je vytištěn jeden z grafických symbolů.

Není ošetřen stisk klávesy BREAK. Prakticky to znamená, že po jejím stisku procesor někam "zabloudí" a to je konec korektního běhu aplikace. Teoreticky by to mělo jít obejít nastavením vektorů klávesy BREAK. Při nejbližší příležitosti to hodlám vyzkoušet.

Závěr? Nemám rád závěry.

Skvělá věcička! Opravdu jsem jí nadšen! Škoda jen, že mě nenapadá, co bych mohl na Atari naprogramovat... Ale někteří z Vás ji určitě využijí. Takže hurá na http://www.cc65.org...