CC65

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 19:24, 13 paź 2005
Jellonek (Dyskusja | wkład)

← Previous diff
Wersja z dnia 19:26, 13 paź 2005
Jellonek (Dyskusja | wkład)
(@!#@ niedopatrzenie...)
Next diff →
Linia 117: Linia 117:
Kompilator '''cc65''' tworzy z pliku '''hello.c''' plik '''hello.s''', Kompilator '''cc65''' tworzy z pliku '''hello.c''' plik '''hello.s''',
-następnie makro assembler '''ca65</b> z pliku '''hello.s''' tworzy '''hello.o''' i ostatecznie linker '''ld65''' z pliku '''hello.o''' i przy pomocy biblioteki '''atari.lib''' i '''atari.o''' oraz pliku konfiguracyjnego '''atari.cfg''' tworzy wykonywalny plik Atari '''hello.xex'''.+następnie makro assembler '''ca65''' z pliku '''hello.s''' tworzy '''hello.o''' i ostatecznie linker '''ld65''' z pliku '''hello.o''' i przy pomocy biblioteki '''atari.lib''' i '''atari.o''' oraz pliku konfiguracyjnego '''atari.cfg''' tworzy wykonywalny plik Atari '''hello.xex'''.
Jeśli chcemy aby kod programu był wykonywany na 65816, zmieniamy zapis Jeśli chcemy aby kod programu był wykonywany na 65816, zmieniamy zapis

Wersja z dnia 19:26, 13 paź 2005

The 6502 C compiler

CC65 jest pakietem kompilatora języka C, assemblera (CA65), librariana, oraz linkera. Pierwotnie napisany przez Johna R. Dunninga na małe Atari. Obecnie rozwijana wersja potrafi kompilować pod różne mikrokomputery oparte o procesor 6502, jak i 65816 (np. rózne odmiany Atari 8-bit, Commodore C64/C128/C16/C116 i inne, Apple II, Nintendo NES...), ale tylko jako tzw. cross kompilacja - z komputerów udostępniających większe zasoby pamięci, mocniejsze procesory.

Poniżej znajduje się nieco kulawy wstęp (w głównej mierze autorstwa Tebe-go) do używania tego cross kompilatora z platformy PC, spod dowolnego systemu postdosowego.




Sam program piszemy na PC w dowolnym edytorze tekstu jak Notatnik czy CodeGenie itp, a kompilator C czyli cc65 zamieni nam go na kod maszynowy 6502. Cały pakiet programów do tworzenia w C znajdziemy na stronie domowej projektu CC65

Możemy też od razu wpaść na ftp-a ftp.musoftware.de/pub/uz/cc65/ i pobrać plik z bibliotekami dla Atari XE/XL cc65-atari-WERSJA.zip oraz plik z kompilatorem przeznaczonym dla konkretnej platformy OS/2, Dos, Windows, np. cc65-win32-WERSJA.zip czyli Windows, bądź, dla platform unixowych, plik ze źródłami (cc65-sources-WERSJA.tar.bz2), kompilowalnymi z użyciem standardowych autotools.

Jeśli mamy już ściągnięte oba pliki, znajdujemy dla nich miejsce na którejś z partycji (np. C) i rozpakowujemy je do np. katalogu C:\CC65

Teraz musimy jeszcze ustawić troche zmiennych środowiskowych, aby kompilator, linker wiedział gdzie co jest. W przypadku rodziny Windows 9x, dopisujemy w pliku AUTOEXEC.BAT:

PATH=%PATH%;C:\CC65\BIN

SET CC65_INC=C:\CC65\INCLUDE
SET CC65_LIB=C:\CC65\LIB
SET LD65_CFG=C:\CC65\DOC

W przypadku Windows 2000, XP, robimy to następująco:

Mój Komputer -> Właściwości -> Zaawansowane -> Zmienne środowiskowe -> dopisujemy w oknie Zmienne systemowe, czyli klikamy "Nowa" i uzupełniamy oba pola "Nazwa zmiennej" i "Wartość zmiennej" podobnie jak ma to miejsce w AUTOEXEC-u.

Teraz resetujemy komputer, bądź przelogowujemy się i możemy zacząć bawić się CC65 pod Windowsem. (Zamiast ustawiać te zmienne na stałe, można również utworzyć plik wsadowy (.bat) uruchamiany z wiersza poleceń i ustawiający je tylko dla danej sesji tegoż wiersza poleceń)

W katalogu C:\CC65\BIN znajdują się wszystkie pliki wykonywalne pakietu cc65:

   ar65 - program do tworzenia bibliotek *.lib i operacji na nich, np. ar65 l atari.lib
          wyswietli nam listę modułów wchodzących w skład bibioteki atari.lib

   ca65 - makro assembler dla procesorów 6502, 65C02 i 65816

   cc65 - kompilator języka C przeznaczony dla rodziny procesorów 6502

   cl65 - program nażędziowy służący jako nakładka na kompilator i linker w jednym

   co65 - programik do konwersji skompilowanych plikaów objektowych do postaci źródeł assemblerowych

   od65 - object dumper - pokazuje zawartość plików obiektowych (symbole, eksporty, importy, segmenty)

   da65 - disassemler, stosuje zapis strawny na makro assemblera ca65

   grc  - to się Atarowcom nie przyda, bo jest to kompilator dla systemu GEOS z C64

   ld65 - linker, czyli programik który składa do kupy wszystko i tworzy plik wykonywalny

Teraz wypadałoby coś skompilować, czas więc na nieśmiertelny przykład, pewnie w BASIC-u też to pisaliście.

Przykład 1:

#include < stdio.h >

int main (void)
{
 printf("Hello, world!\n");
 return 0;
}

Nasz program zapiszemy do pliku np. "hello.c", aby go skompilować piszemy "cl65 -O -t atari hello.c -o hello.xex" i to wszystko, powstał plik HELLO.XEX który możemy już wczytać spod DOS-a. Uruchomienie go bezpośrednio nic nie da, musi być uruchomiony spod DOS-a.


Parametry które przekazaliśmy kompilatorowi cl65 oznaczają (wielkość liter jest rozróżniana):

   -O        optymalizacja kodu, tworzy optymalniejszy kod maszynowy
   -t sys    docelowy system, domyślnie jest to C64 :P
   -o plik   nazwa pliku wyjściowego

Wywołanie cl65 to najszybszy i najprostszy sposób kompilacji. Skompilowany program domyślnie ładuje się od $2E00, startuje od $2E01, maksymalna długość skompilowanego programu może wynieść $8E20 bajtów. Stos programowy liczy $0800 bajtów pamięci. Strona zerowa używana jest od bajtu $82-$FF.

Domyślne ustawienia dla linkera (plik ATARI.CFG):

MEMORY {
    ZP: start = $82, size = $7E, type = rw, define = yes;
    HEADER: start = $0000, size = $6, file = %O;
    RAM: start = $2E00, size = $8E20, file = %O;    # $8E1F: matches upper bound $BC1F
}
SEGMENTS {
    EXEHDR: load = HEADER, type = wprot;
    CODE: load = RAM, type = wprot, define = yes;
    RODATA: load = RAM, type = wprot;
    DATA: load = RAM, type = rw;
    BSS: load = RAM, type = bss, define = yes;
    ZEROPAGE: load = ZP, type = zp;
    AUTOSTRT: load = RAM, type = wprot;
}
FEATURES {
    CONDES: segment = RODATA,
            type = constructor,
            label = __CONSTRUCTOR_TABLE__,
            count = __CONSTRUCTOR_COUNT__;
    CONDES: segment = RODATA,
            type = destructor,
            label = __DESTRUCTOR_TABLE__,
            count = __DESTRUCTOR_COUNT__;
}
SYMBOLS {
    __STACKSIZE__ = $800;	# 2K stack
}

Jednak jakiekolwiek zmiany w pliku *.CFG nie zostaną zauważone jeśli będziemy kompilować używając komendy "-t atari", trzeba ją zastąpić przez "-C atari.cfg". Jeśli chcemy mieć też wpływ na typ CPU dla którego będzie generowany kod, lepiej jeśli rozbijemy proces generowania pliku wyjściowego na kompilację, asemblację i linkowanie, wtedy wszystko będzie pod kontrolą.

   cc65 -O --cpu 6502 -t atari hello.c -o hello.s
   ca65 -t atari hello.s -o hello.o
   ld65 -C atari.cfg -o hello.xex atari.o hello.o atari.lib

Kompilator cc65 tworzy z pliku hello.c plik hello.s, następnie makro assembler ca65 z pliku hello.s tworzy hello.o i ostatecznie linker ld65 z pliku hello.o i przy pomocy biblioteki atari.lib i atari.o oraz pliku konfiguracyjnego atari.cfg tworzy wykonywalny plik Atari hello.xex.

Jeśli chcemy aby kod programu był wykonywany na 65816, zmieniamy zapis --cpu 6502 na --cpu 65816. Czyż nie jest to cudownie proste :).

Przykład 2:

#include < stdio.h >

int main (void)
{
 char str1[30],str2[30];
 int i;

 puts("wprowadz lancuch 1"),gets(str1);
 puts("wprowadz lancuch 2"),gets(str2);

 for (i=0; str1[i]==str2[i]; i++)
 {
 }

 if (str1[i]==0)       // standard ansi, ciag znakow zakonczony zerem
 {
  puts("oba lancuchy sa identyczne");
  return 0;
 }

  puts("lancuchy sa rozne");

 return 0;
}

Progamik pyta się o dwa łańcuchy znaków, potem je porównuje i informuje czy łańcuchy są identyczne, czy też różne. Jest jeszcze biblioteczna funkcja C -> "strcmp" która porówna ciągi, ale przecież jej użycie byłoby zbyt proste :)

Przykład 3:

/* clock example: countdown */
#include < stdio.h >
#include < time.h >

void wait ( int seconds )
{
  clock_t endwait;
  endwait = clock () + seconds * CLK_TCK ;
  while (clock() < endwait) {}
}

int main ()
{
  int n;
  printf ("Starting countdown...\n");
  for (n=10; n>0; n--)
  {
    printf ("%d\n",n);
    wait (1);
  }
  printf ("FIRE!!!\n");
  return 0;
}

Programik zlicza od 10 do 0, wypisując stosowny komunikat na ekranie. Jest to też przykład wykonania opóźnienie z użyciem "time.h"

Nie ma jednak róży bez kolców. Wstawianie wstawek assemblerowych musi odbywać się poprzez pliki z rozszerzeniem *.s, bądź mało czytelne wywołanie ASM("kod"). Przydzialana programowi pamięć w zasadzie mieści się w granicy $2000-$BFFF, troche mało jeśli ktoś myśli o większym projekcie. Problem z pamięcią miał też autor atarowskiej wersji systemu Contiki, który posłużył się specjalnie okrojoną wersją DOS - PicoDos aby tylko wcisnąć więcej kodu poniżej adresu $2000.


Ten artykuł to tylko zalążek. Możesz pomóc rozwojowi Atariki poprzez rozszerzenie go o więcej informacji.

Personal tools