32. Prekladač action26

Doteraz si z prekladača používal tri veci: action26 program.act, --sim a --run. Táto kapitola prejde ostatné voľby. Od tejto kapitoly ide o veci, ktoré pôvodný Action! na Atari nemal.

Tvar príkazu

action26 program.act [voľby]

Voľby sa píšu za meno programu, v ľubovoľnom poradí. Úplný zoznam vypíše:

action26 --help

Výstup

VoľbaČo robí
-o súbormeno výsledného súboru; bez nej je to meno programu s príponou .xex
--listing súborvýpis preloženého programu: adresy, bajty a inštrukcie procesora
--asm súborzdroják v assembleri 6502, z ktorého sa dá program zostaviť znova
--map súborzoznam mien s adresami
--lab súborzoznam mien pre ladiace nástroje emulátorov
--memorypo preklade vypíše, koľko pamäte program zaberá a koľko ešte ostáva voľnej, vrátane pamäte pod ROM
--memory-mapto isté, ale s výpisom každého kúska pamäte po adresách
--reserve od-dopamäť, ktorú program používa len za behu a nie je v súbore (napríklad buffer obrázka $A100-$B7BF); dá sa zadať viackrát
--mem-lo adresa, --mem-top adresav akom rozsahu pamäte sa voľné miesto počíta (predvolene $0700 až $BBFF)
--org adresaadresa, od ktorej program v pamäti začína (predvolene $2000)
action26 hello.act -o HELLO.XEX --listing hello.lst

Koľko pamäte ešte ostáva

Pri väčšom programe, napríklad textovke, sa hodí vedieť, či sa ešte zmestí ďalší text. --memory to po preklade napíše:

action26: memory [######################--------] 76 % full
  used by the program:   35121 bytes
  still free:            11215 bytes
  biggest free piece:     5826 bytes  (a new text or routine has to fit into one piece)
  free under the ROM:     1380 bytes  (biggest piece 1060)

Voľná pamäť je rozdelená na kúsky. Nový text alebo rutina sa musí zmestiť do jedného, preto je dôležité hlavne číslo „biggest free piece“. Počíta sa po preklade, takže pamäť, ktorú program alokuje až za behu, v ňom nie je. Polia deklarované na pevnej adrese (ARRAY a(256)=$0700) sa započítajú samé. Buffery, ktoré program používa len za behu a nemá ich ako polia, povedz cez --reserve, napríklad --reserve $A100-$B7BF; inak by sa počítali ako voľné. Rozsah, v ktorom sa počíta, zúž cez --mem-lo a --mem-top.

Pamäť pod ROM ($C000–$CFFF a $D800–$FFF9) a v bankách program zvyčajne využíva na texty a tabuľky; jej voľné miesto je v prehľade na samostatnom riadku, lebo je to iný kus pamäte ako hlavná RAM.

Chceš vidieť, kde presne sú voľné kúsky, použi --memory-map. Každý kúsok je na vlastnom riadku, s adresou od–do:

action26: memory $0700-$BBFF
action26:   program $0700-$09F3    756 bytes
action26:   free    $09F4-$0C57    612 bytes
action26:   program $0C58-$0CE3    140 bytes
...
action26:   free    $9433-$9F5F   2861 bytes

Pri väčšom programe si podľa toho nájdeš diery, ktoré sa dajú vyplniť, a vidíš aj hranicu, od ktorej voľné miesto pokračuje až po koniec pamäte (tam sa dá umiestniť halda pre Alloc/Free).

Čo je v listingu

Listing ukazuje, na čo sa program preložil. Pre hello.act z kapitoly 2 začína takto:

; org $2000
2000                  Main:
2000  A2 20                   LDX #>__L2
2002  A9 0E                   LDA #<__L2
2004  4C 1C 20                JMP PrintE
2007                  __start:
2007  A9 00                   LDA #$00
2009  85 B7                   STA $B7
200B  4C 00 20                JMP Main
200E                  __L2:
200E  0D 48 65 6C 6C 6F 2C 20         .BYTE ...
2016  41 74 61 72 69 21
; runtime: print
201C                  PrintE:

Vľavo je adresa, za ňou bajty v pamäti a vpravo inštrukcia procesora. Vidno tri veci:

Listing nemusíš vedieť čítať. Je užitočný, keď chceš vedieť, koľko miesta čo zaberá, alebo keď sa učíš assembler.

Spúšťanie

VoľbaČo robí
--simspustí program vo vstavanom simulátore; klávesnica je klávesnica tvojho počítača
--sim-statsako --sim, na konci vypíše počet vykonaných inštrukcií
--sim-limit nsimulátor skončí najneskôr po n miliónoch inštrukcií (predvolene 10)
--sim-mem druhakú pamäť má simulovaný počítač: 64, 130xe a väčšie (kapitola 38)
--runspustí program v emulátore atari800
--emulator súborkde je atari800.exe, ak nie je v priečinku atari800 vedľa prekladača

Čo simulátor vie a čo nie:

VieNevie
výpis textu a vstup z klávesnicekresliť obrazovku, farby, grafické režimy
súbory na D: (len v pamäti, počas behu)zvuk
výpočty, polia, reťazce, ukazovatelejoystick a paddle
rozšírenú pamäť (--sim-mem)náhodné čísla (Rand vracia stále to isté)
časovač na adrese 20

Simulátor je rýchly spôsob, ako skúšať logiku programu. Na všetko, čo má byť vidieť a počuť, je emulátor.

--sim-stats sa hodí na porovnanie dvoch verzií programu – ktorá je rýchlejšia:

action26 for.act --sim-stats
action26: 6900 instruction(s) executed

Program, ktorý beží dlhšie ako desať miliónov inštrukcií, simulátor zastaví hlásením instruction limit reached. Ak to nie je nekonečná slučka, limit zväčši: --sim-limit 100.

Zdrojový text

VoľbaČo robí
-I priečinokkde hľadať súbory z INCLUDE (kapitola 23)
-D meno=textzavedie DEFINE meno="text" pred začiatkom programu
--case-sensitiverozlišuje veľké a malé písmená v menách
--modernzapne rozšírenia jazyka (kapitoly 35 až 39)
--no-configignoruje nastavenia napísané v zdrojáku (kapitola 33)

-D: meno z príkazového riadka

Súbor examples/stars-count.act používa meno COUNT, ktoré v programe nikto nedeklaroval:

Action!
; A name given on the command line: action26 stars-count.act -D COUNT=7

PROC Main()
  BYTE i

  FOR i=1 TO COUNT
  DO
    Put('*)
  OD
  PutE()
RETURN
action26 stars-count.act -D COUNT=7 --sim
*******

Bez -D prekladač ohlási error ACT008: undeclared name 'COUNT'. Hodí sa to, keď z jedného zdrojáka robíš viac verzií programu – skúšobnú a ostrú, anglickú a slovenskú.

Optimalizácia

VoľbaČo robí
-O2najmenší a najrýchlejší kód – predvolené
-O1menej úprav
-O0kód v takom tvare, aký by dal pôvodný Action!

Program sa správa vo všetkých troch prípadoch rovnako, líši sa veľkosť a rýchlosť. Pre for.act z kapitoly 13: 665 bajtov s -O0, 612 s -O1 a 589 s -O2.

-O0 má zmysel, keď porovnávaš výsledok s pôvodným prekladačom alebo keď program obsahuje strojový kód, ktorý sa spolieha na presný tvar okolitého kódu.

Nečitateľný súbor

VoľbaČo robí
--scramblezakóduje výsledný súbor, aby sa v ňom nedalo nič prečítať
--scramble-fx menoto isté, a kým sa program po nahratí dekóduje, na obrazovke beží efekt
--scramble-level čísloto isté, s úrovňou zakódovania: 1 (predvolená) alebo silnejšia 2
--scramble-key číslokľúč, od ktorého sa kóduje (napríklad $3A7F); s ním dá každý preklad rovnaký súbor

Texty, ktoré program vypisuje, ležia v súbore XEX tak, ako si ich napísal. Kto súbor otvorí v editore, prečíta si ich – pri textovej hre aj riešenie. Súbor examples/secret.act:

Action!
; A file nobody can read: action26 secret.act --scramble

PROC Main()
  PrintE("The password is SESAME.")
RETURN

Prelož ho najprv obyčajne a nechaj Windows pohľadať v súbore slovo SESAME:

action26 secret.act
findstr /m SESAME secret.xex
secret.xex

findstr /m vypíše meno súboru, v ktorom slovo našiel. Teraz to isté s --scramble:

action26 secret.act --scramble
findstr /m SESAME secret.xex

Tentoraz nevypíše nič – slovo v súbore nie je. Program pritom robí presne to isté:

action26 secret.act --scramble --sim
The password is SESAME.

Čo prekladač urobil

Hotový program prekódoval bajt po bajte a pridal k nemu krátky dekodér. Ten sa po nahratí súboru spustí ako prvý, vráti pamäť do pôvodného stavu a až potom spustí tvoj program. V zdrojáku nemeníš nič a program o dekodéri nevie. Aj samotný dekodér je v súbore zakódovaný: pred ním leží krátky prvý stupeň (24 bajtov), ktorý ho pri prvom zavolaní rozkóduje na mieste. Zo súboru sa tak nedá prečítať ani kód dekodéra, ani jeho kľúč.

Čo to stojí, povie --verbose:

action26: scrambled 275 bytes (level 1, key $A7), decoder at $0600 (108 bytes), file 112 bytes longer

Nie je to ochrana. Kto program spustí v emulátore, vidí v jeho pamäti všetko už dekódované. Zakódovanie bráni len tomu, aby si texty niekto prečítal priamo zo súboru.

Silnejšie zakódovanie: --scramble-level 2

Bežné --scramble kóduje každý bajt pomocou bajtu pred ním. Je to rýchle a dekodér je krátky, no kto ten postup pozná, napíše si program, ktorý súbor rozkóduje bez spúšťania. Voľba --scramble-level vyberá úroveň zakódovania:

ÚroveňAko kódujeDekodér26 KB trvá
1každý bajt XOR bajt pred ním (predvolená, to isté ako --scramble)108 bajtov0,50 s
2každý bajt XOR číslo z 16-bitového generátora pseudonáhodných čísel (LFSR)+12asi 0,9 s
action26 secret.act --scramble-level 2

--scramble-level už znamená --scramble, oboje písať netreba. Efekty fungujú rovnako, napríklad --scramble-level 2 --scramble-fx bars.

Pri úrovni 2 čísla, ktorými sa bajty kódujú, vôbec nezávisia od programu a generátor beží bez prerušenia cez celý súbor – v súbore do 64 KB sa teda nikde neopakujú. Kto ich chce odstrániť, musí generátor napodobniť a poznať číslo, od ktorého začína – kľúč. Bez voľby --scramble-key si prekladač pri každom preklade vyberie nový náhodný kľúč, takže ten istý zdroják dá zakaždým iný súbor. Ak chceš, aby bol súbor pri každom preklade rovnaký (napríklad na porovnanie dvoch verzií), kľúč zadaj sám:

action26 secret.act --scramble-level 2 --scramble-key $3A7F --verbose
action26: scrambled 275 bytes (level 2, key $3A7F), decoder at $0600 (120 bytes), file 124 bytes longer

Kľúč je číslo od $0001 do $FFFF; nula nejde, generátor by z nej vyrábal len nuly. Pri úrovni 1 je kľúč jeden bajt od $01 do $FF, bez voľby platí $A7.

Kľúč ani tu nie je v súbore čitateľne, dekodér je zakódovaný rovnako ako pri úrovni 1. Čitateľný ostane len prvý stupeň a tabuľka, ktoré úseky pamäte sa majú dekódovať.

Ani úroveň 2 nie je ochrana: emulátor ukáže pamäť už dekódovanú a kto prvý stupeň pochopí, dostane sa ďalej. Len to dá podstatne viac práce.

Efekty: --scramble-fx

Pol sekundy, počas ktorej sa na obrazovke nič nedeje, vyzerá ako zaseknutý počítač. Staré programy na Atari preto pri rozbaľovaní kreslili pruhy. --scramble-fx meno zakóduje súbor rovnako ako --scramble a pridá do dekodéra efekt:

action26 secret.act --scramble-fx bars --run

Efekt uvidíš len v emulátore (--run) alebo na skutočnom Atari – simulátor (--sim) obrazovku nekreslí. Pri takom malom programe iba preblikne; poriadne ho vidno pri programe s desiatkami kilobajtov.

MenoČo je na obrazovkeDekodér26 KB trvá
nonenič – to isté ako --scramble+0 bajtov0,50 s
barsfarebné pásy cez celú obrazovku+60,68 s
bars-borderfarebné pásy len na okrajoch+30,58 s
monočiernobiele pásy cez celú obrazovku+80,72 s
mono-borderčiernobiele pásy na okrajoch+50,64 s
rainbowpravidelná dúha cez celú obrazovku+60,68 s
rainbow-borderdúha na okrajoch+30,58 s
slowširoké pomalé pásy cez celú obrazovku+60,50 s
slow-borderširoké pomalé pásy na okrajoch+30,50 s
dotsbodky po celej obrazovke – znaky sa zmenia na zrnenie+30,58 s
dots-barsbodky a farebné pásy naraz+90,76 s
blankobrazovka zhasne, nič sa nekreslí+200,36 s
bars-blankobrazovka zhasne, farebné pásy cez celú plochu+230,42 s
incobrazovka zhasne, biele čiarky na tmavočervenej ploche+280,48 s
inc-borderbiele čiarky na tmavočervených okrajoch+80,66 s

Ako si vybrať:

Tri veci, ktoré je dobré vedieť:

Voľbu si program môže niesť v sebe, riadkom ;@compile --scramble-fx bars na začiatku zdrojáka (kapitola 33). Rovnako ;@compile --scramble-level 2 --scramble-key $3A7F.

Časté chyby

HláseniePríčina
error ACT200: invalid effect for --scramble-fx: stars (none, bars, …)efekt s takým menom nie je; v zátvorke sú všetky, ktoré prekladač pozná
error ACT200: missing effect after --scramble-fx (none, bars, …)za --scramble-fx chýba meno efektu; bez efektu stačí --scramble
warning ACT232: --scramble-fx inc on the command line overrides bars in the sourcezdroják si pýta jeden efekt a príkazový riadok iný; platí príkazový riadok
error ACT200: invalid level for --scramble-level: 3 (1, 2)takú úroveň prekladač nepozná; sú len 1 a 2
error ACT200: invalid value for --scramble-key: $1FFFF (a number up to $FFFF, e.g. $3A7F)kľúč je 16-bitové číslo, najviac $FFFF
error ACT200: --scramble-key for --scramble-level 1 is a byte from $01 to $FFúroveň 1 má kľúč len jeden bajt; dlhší kľúč patrí k úrovni 2
error ACT200: --scramble-key must not be 0 with --scramble-level 2generátor úrovne 2 nemôže začínať od nuly; zvoľ iný kľúč

Zbalený súbor

VoľbaČo robí
--pack-xexzbalí výsledný súbor; Atari si ho počas nahrávania samo rozbalí

Disketová mechanika Atari je pomalá. Kratší súbor sa preto nahrá rýchlejšie a na disketu sa ich zmestí viac. Starí programátori na to mali programy ako Super Packer; v Action26 stačí voľba. Program pm-lanes.act z kapitoly 42:

action26 pm-lanes.act --pack-xex --verbose
action26: packed 1 segments, loader at $0600 (180 bytes), buffer at $294D, file 2393 -> 1959 bytes

Súbor sa skrátil z 2393 bajtov na 1959. Spúšťa sa rovnako ako predtým (--run, z DOS-u, z diskety s autorunom) a program o zbalení nevie.

Čo prekladač urobil

Každý kus programu zbalil (formátom ZX02, ktorý poznáš z PACK ZX02 v kapitole 39) a pridal krátky rozbaľovač so 180 bajtmi. DOS najprv nahrá rozbaľovač, potom zbalený kus a hneď ho zavolá; rozbaľovač kus rozbalí na jeho miesto. Až keď je všetko rozbalené, spustí sa tvoj program.

Voľbu si program môže niesť v sebe riadkom ;@compile --pack-xex (kapitola 33).

Zbalený a zakódovaný

Zbalený súbor sa v editore číta horšie, no texty z neho nezmiznú. Kus, ktorý sa v programe neopakuje, si zbaľovač uloží tak, ako je:

action26 secret.act --pack-xex
findstr /m SESAME secret.xex
secret.xex

Ak sa texty nemajú dať prečítať, pridaj --scramble:

action26 secret.act --pack-xex --scramble
findstr /m SESAME secret.xex

Teraz findstr nenájde nič. Prekladač najprv zbalí a potom zakóduje zbalené dáta; rozbaľovač ich pri nahrávaní najprv rozkóduje a potom rozbalí. Funguje to s oboma úrovňami aj s kľúčom (--scramble-level 2, --scramble-key), len efekty --scramble-fx so zbalením nejdú. Rozbaľovač narastie na 231 bajtov (s úrovňou 2 na 245).

Zakódujú sa všetky kusy programu, ktoré sa dajú zbaliť, aj keď sa zbalením neskrátia. Čitateľné ostanú len drobnosti: adresa štartu a nastavenia pod adresou $0400, napríklad farby.

Časté chyby

HláseniePríčina
error ACT200: --pack-xex cannot show an effect: --scramble-fx bars only without --pack-xex (…)zbalený súbor sa dá zakódovať, ale bez efektu; nechaj --scramble alebo --scramble-level
error ACT200: --pack-xex: no segment gets shorterprogram je taký malý, že by sa zbalením len predĺžil; prelož ho bez --pack-xex

Upozornenia a chyby

VoľbaČo robí
--strictupozorní na všetko, čo by pôvodný Action! odmietol
--quirksnapodobní aj známe chyby pôvodného prekladača
--wextraďalšie upozornenia – napríklad volanie s menším počtom argumentov
--werrorupozornenia sú chyby: program s varovaním sa nepreloží
--max-errors npo koľkých chybách prestať (predvolene 20)
--verbosevypíše, čo prekladač robí: veľkosť, adresy

Návratová hodnota

Pre toho, kto prekladač volá zo skriptu: 0 znamená úspech, 1 chyby v programe, 2 chybu v príkazovom riadku.

Zhrnutie

Späť: 31. Bloky pamäte a chyby · Ďalej: 33. Nastavenia v zdrojáku