Připomněl bych jen, že data display listu nesmí křižovat hranici jednoho kilobajtu a obrazová paměť nesmí křižovat hranici čtyř kilobajtů.
U jednoduchého demonstračního příkladu, který začíná na adrese $2000 se to samozřejmě nestane. U složitějších programů je vhodné mít jak obrazovou paměť tak display list v samostatných segmentech. V konfiguračním souboru linkeru se pak pro segmenty nastaví vhodné zarovnání. Stačí zarovnávat na nejbližší mocninu dvou, která je vyšší než délka DL nebo obrazové paměti.
Přesně tak - tam pak vyjde najevo, že na každý ohejbák je narovnávák :) U grafické paměti se limit obchází novou instrukcí LMS, u Display Listu je to myslím instrukce JMP, nepletu se?
Jinak nemáte prosím lepší zdroj dokumentace toho asembleru než je jeho dokumentační balíček? Resp. kde je popsáno, jak se právě takovéto podmínky alokace zadávají? V tom dokumentačním balíčku jsem právě nic takového nenašel. Ani jaké jsou všechny druhy těch segmentů, natož jak se zadávají podmínky apod.
Tohle má na starosti linker ld65 a vše potřebné je uvedeno k jeho dokumentaci. ca65 je assembler podporujíci oddělený překlad a proto je jeho výstupem pouze meziprodukt, který pak linker přemění na výslednou spustitelnou binárku. Binárkou se rozumí .xex soubor, může to být ale i obraz disku nebo obraz cartridge. cfg soubor je pak předpis pro to jak má binárka vypadat. Tam se uvádí i to zarovnání, výplňové byty apod. Naučit se ld65 není jednoduché, ale pořád je to selanka oproti třeba GNU LD.
To je velký rozdíl oproti ostatním cross-assemblerům jako třeba ATASM, XASM nebo MADS. Ty vyrobí binárku rovnou, bez meziproduktu. Ale zase nepodporují oddělený překlad.
Díky, to je ono, co jsem hledal. Ale ačkoliv oproti gnu ld je to určitě selanka (na 64 kB bych teda nečekal opak :) ), tak pořád je to teda dost komplikované. Ten "kompresní poměr" velikosti a složitosti souborů na vstupu oproti výslednému XEX (v prvním příkladu to je cca 60 bajtů) je doslova ohromující :) Zajímalo by mě, u jak složitých programů se tak komplikovaný asembler a linker vyplatí. Jestli třeba jde svůj kód rozdělit na výpočetní část a část ovládající proprietární HW a překládat pak třeba hru pro Atari i C64?
Ale hlavní je, že teď už líp rozumím příkladům v článku, díky za správný pointer na doc!
Celé je to hlavně kvůli překladači cc65 z toolkitu. U překladačů jazyka C se prostě s odděleným překladem od začátku počítá, tak je tak nějak potřeba i ten linker.
Zase s ld65 je to podobné třeba jako s jazykem C++. Nabízí nepřeberně možností jak programovat (a tím si zjednodušit nebo zkomplikovat život), ale stačí se naučit jen to co je vhodné a nutné pro daný projekt.
Síla ld65 se ukáže zejména v následujících případech:
1. Vysoce modularizovaný projekt buď v assembleru nebo C, případně kombinace obou jazyků
2. Projekt, do kterého je nutné včlenit různorodá data s rozličnými nároky na rozmístění v paměti. Příkladem jsou třeba hry pro Atari. display list, obrazová paměť, rutina pro přehrávání zvuků, znakové sady, oblasti pro PMG.
3. Projekt velké cartridge s přepínáním bank, kde se kód a data zavádějí na jiné adresy než kde se pak používají.
Jako ukázku bych nabídnul Train 3 OSE. A to není ještě moc komplikovaný projekt.
Pro 8bitové počítače Atari (a jiné) existuje i protivarianta. Linker nijak složitě nepoužívat, data do programu připojit jako další sekce v .xex souboru programem COPY a vazbu na kód a data v dodaných sekcích zajistit pomocí symbolů preprocesoru.
Díky vám oběma za otevření nových obzorů. Já docela koukal, jak složitě vypadá ta konfigurace linkeru. Jenže, jestli tomu dobře rozumím, tak to se udělá jen jednou po danou platformu a pak se používá v asembleru jen jednoduché označení bloku jako BSS apod. - je to tak?
Jinak se přiznám, že když jsem tuhle složítost viděl poprvé, tak jsem to nejdřív vzdal. Napsal jsem svou verzi prvního příkladu z tohoto článku do monitoru paměti v emulátoru, zapsal na disk XEX soubor o velikosti 56 znaků a měl hotovo. A až pak jsem začal koumat nad těmi sáhodlouhými konfiguracemi zde a snažil se je pochopit :)
Na to abych ověřil svůj dojem, že to jde napsat rychješí a jen s jedním registrem mi to stačilo - chtěl jsem jen krátké mentální cvičení před spaním :D :D
Já to nikdy moc nepochopil, jak to má fungovat. Třeba jsem chtěl segment se zarovnáním na kilobajt pro sprity nebo pro fonty (tam je možná jen zarovnání na půl kilobajtu, ale to je jedno).
Takže jsem si udělal segment SPRITE align=1024 optional=no, type=ro. Jenže to natáhlo výsledný .xex soubor právě o ten align (se to vyplnilo nulami, asi nechápu koncept segmentů a sekcí) a navíc si nejsem jistý, jak v assemberu získat adresu toho segmentu. Dával jsem (v assembleru) hned za segment nějaký label, třeba sprites: ale mám pocit, že potom adresa přes <sprites a >sprites stejně haprovala.
Nakonec jsem skončil s kopií po spuštění někam do paměti (třeba jsem si řekl, ok sprity budou od stránky 150, a tam jsem to copy smyčkou zkopíroval). To je asi dost blbě že?
Je to opravdu složitější. Segmenty ld65 nejsou totéž co sekce v .xex souborech. Segmenty ld65 jsou na vyšší urovni abstrakce. Musí se nejprve namapovat do paměťových oblastí ld65. Teprve z paměťových oblastí se vyrábí sekce .xex souborů. A to taky dost krkolomně. Kdysi jsem měl o tom přednášku na Atariádě. Ale vzhledem k mým tehdy ještě málo rozvinutým prezentačním schopnostem neměla velký dopad.
ona se 6502ka používala i v herních konzolích a různých zařízených se "šílenými" konfiguracemi paměti. Takže je nutné nějakým způsobem určit "toto patří do program RAM", "toto jsou sprity (NES)", "toto je tile memory", tady je paleta (C64) atd.
Pro atárko se to vlastně fakt dá skoro zapomenout a jet všechno v CODE a BSS segmentech. A nebo se i vykašlat na BSS a prostě akceptovat delší .xex i s neinicializovanými daty (to mi ovšem připadne hodné tak pojídačů koláčů :-).