Tajemnice ATARI

APPEND

Po cóż ?

   Podczas intensywnej pracy ze znakomitym narzędziem jakim jest Quick Assembler łatwo odczuć ograniczenia narzucane przez skromny sprzęt. Małe ATARI wyposażono tylko w 64 KB pamięci operacyjnej, co w czasie kiedy komputer projektowano, mogło wydawać się całkiem sporo. Niestety, wiele czasu upłynęło od tych chwil i wymagania nowoczesnego oprogramowania stały się zupełnie inne. Nowoczesne programy narzędziowe potrafią wiele (o wiele, wiele więcej niż ich prymitywni poprzednicy), jednakże dzieje się to kosztem wielkości tych programów i, co jest tego konsekwencją, zajmują odpowiednio duże obszary pamięci operacyjnej. Podczas pisania większego programu przy użyciu QA dość szybko zaczynamy mieć kłopoty z pomieszczeniem w pamięci tekstu źródłowego, wynikowego kodu i samego assemblera. Trzymanie tego wszystkiego w pamięci bardzo usprawnia pracę, gdyż standardowe pamięci masowe ATARI są bardzo wolne (nawet stacje dysków, nie mówiąc o magnetofonie).

   Istnieje parę metod walki z tym problemem. Najprostszą z nich, ale niezbyt efektywną jest metoda dzielenia tekstu źródłowego na mniejsze części i dołączanie ich w czasie assemblacji przy pomocy pseudorozkazu ICL. Wadami tej metody są: ciągła współpraca z wolną stacją dysków w czasie assemblacji i przedłużający się proces generowania kodu wynikowego wymagający dwukrotnego odczytania plików z dalszymi częściami tekstu. Druga, efektywniejsza metoda to dzielenie programu na osobne, oddzielnie assemblowane moduły. Znanym powszechnie faktem jest to, że z całkiem sporego tekstu źródłowego powstaje dość mało kodu. Pozwala to umieszczać takie małe porcje kodu w pamięci i zostaje jeszcze dość dużo miejsca na poprawiany aktualnie tekst. Podzielenie programu na moduły i zapewnienie komunikacji między nimi nie jest rzeczą prostą, ale bardziej zaawansowany programista potrafi sobie z tym poradzić. Jedną godną polecenia metodą jest stworzenie pliku zawierającego definicje zmiennych na stronie zerowej, wspólnych adresów systemowych i etykiet określających położenie poszczególnych modułów w pamięci. Plik ten dołączany jest pseudorozkazem ICL na początku assemblacji każdego modułu i zapewnia, że wszystkie części programu będą korzystać z tych samych zmiennych i adresów. Druga metoda to wstawianie na początku kodu każdego modułu tabeli skoków do procedur tego modułu. Inne części muszą znać (np. poprzez opisywany powyżej plik) tylko położenie w pamięci tej tabeli i kolejność skoków. Ułatwia to zmiany w modułach bez konieczności zmian i assemblacji innych części. Tak podzielone moduły assemblujemy na dysk i otrzymujemy pliki binarne gotowe do załadowania z poziomu DOS-u. Przed pracą ładujemy potrzebne pliki, potem assembler i przystępujemy do pracy nad częścią wymagającą poprawek.

   Gdy program jest gotów powstaje problem połączenia tej mnogości plików w jedną całość. Trudno wymagać od użytkownika naszego programu aby znał i pamiętał kolejność wczytywania części programu. Wypada aby całość była w postaci jednego pliku gotowego do załadowania do pamięci. Co prawda QA umożliwia podczas assemblacji dołączenie kodu do istniejącego już pliku binarnego, ale zakłada to, że całość pliku binarnego zostanie wygenerowana przy pomocy QA i przed wyprodukowaniem gotowego programu jesteśmy zmuszeni assemblować wszystkie jego części. A jak dołączyć definicje znaków, muzyczki i inne dane? Można się w tym celu posłużyć programem DUP.SYS i jego opcją COPY/APPEND, ale niewygoda tego programu jest powszechnie znana. Na dyskietce dystrybucyjnej QA został on zastąpiony interpreterem poleceń CP.SYS i nie bardzo pasuje on do tego zestawu. Aby umożliwić użytkownikom kopiowanie plików i scalanie plików binarnych w jeden plik docelowy powstał program (komenda zewnętrzna CP) kopiujący i scalający APPEND.

Obsługa programu APPEND.

   Gdy chcemy skopiować plik lub połączyć kilka plików binarnych w jedną całość wystarczy, w odpowiedzi na znak zachęty "D1:" procesora komend napisać "APPEND", a wcześniej należy zadbać aby w aktualnym napędzie była dyskietka z programem APPEND. Program przedstawia się po polsku i pokrótce podpowiada jak go użyć. Następnie wyświetla informacje statystyczne o ilości wczytanych bajtów w buforze i ilości wolnych bajtów jeszcze w nim pozostałych. Na początku pierwsza wartość to 0 a druga to około 37 kilobajtów. Teraz program oczekuje na nazwę pliku do załadowania do bufora (lub dołączenia do wczytanej poprzednio zawartości). Możemy podać pełną specyfikację pliku obejmującą także nazwę urządzenia, ale gdy ją opuścimy program domyślnie przyjmie "D1:". Jeśli specyfikacja będzie tzw. szablonem, czyli będzie zawierać znaki "*" lub "?" to APPEND odczyta katalog wg. tego szablonu. Aby zobaczyć kompletny spis dyskietki w stacji 1 należy wprowadzić "*.*", a jeśli interesują nas pliki binarne w stacji 2 należy napisać "D2:*.OBJ". Gdy zdecydowaliśmy się pożegnać z programem APPEND to wystarczy wprowadzić "." (kropkę). Po wczytaniu jednego lub więcej plików do bufora zmieniamy tryb pracy z odczytu na zapis wprowadzając pustą linę, czyli po prostu naciskając klawisz RETURN. Teraz program oczekuje na specyfikację pliku docelowego, w którym znajdzie się zawartość bufora. W tym miejscu zachowanie się programu jest identyczne jak w trybie odczytu. Zawartość bufora możemy zachować dowolną ilość razy w różnych (a nawet tych samych) plikach i wprowadzając pustą linię wracamy do trybu odczytu (wprowadzenie kropki uwolni nas od bojów z APPEND-em). Jak łatwo wydedukować można w analogiczny sposób kopiować pojedyncze pliki, po prostu po załadowaniu jednego pliku do bufora od razu przechodząc w tryb zapisu. Ponieważ program porozumiewa się z użytkownikiem po polsku nie powinno być kłopotów ze zrozumieniem wyświetlanych przez niego komunikatów. Zakłada również, że użytkownik jest fachowcem i wie czego chce, więc nie pyta go o potwierdzenie przy zapisie na istniejący już plik lub przy wyjściu z programu.

W praktyce.

   Oprócz funkcji kopiowania plików, która przyda się każdemu, APPEND posiada możliwość scalania plików w buforze w jedną całość. Można nim scalać pliki różnego rodzaju (np. tekstowe z binarnymi), ale tylko przemyślane działanie może przynieść oczekiwane efekty. Teraz nastąpi praktyczny opis wykorzystania programu APPEND w pracy z Quick Assemblerem.

   Aby wytworzyć gotowy program w postaci pliku dającego się załadować z poziomu DOS-u należy scalać tylko pliki binarne. Te pliki zawierają nagłówki bloków z informacjami o adresach pod jakimi ma znaleźć się zawartość danego bloku. QA przy assemblacji na dysk z ustawionym bitem 5 i skasowanym 6 opcji (np. OPT %0100101) generuje plik binarny, w którym bloki mają odpowiednie nagłówki. Scalanie takich modułów nie nastręcza żadnych trudności, o ile nie nastąpi konflikt adresów. Co jednak mamy począć w przypadku gdy dysponujemy plikiem danych (np. definicje znaków), który nie posiada odpowiednich informacji? Jeśli ten plik zawiera dane, które mają znaleźć się w ciągłym obszarze pamięci zaczynającym się od pewnego adresu, musimy stworzyć mu specjalny nagłówek. W tym celu musimy poznać dokładną (co do 1 bajtu) długość tego pliku (zakładamy, że całość pliku zawiera dane i tylko dane, bez żadnych informacji dodatkowych). Bardzo pomocny będzie do tego zadania nasz APPEND. Wystarczy go załadować i wczytać do bufora interesujący nas plik. Z informacji statystycznych możemy teraz odczytać jego długość (np. W buforze: 1024). Opuszczamy APPEND, uruchamiamy QA i piszemy mały tekst nazywając go HEADER.ASM, którego zadaniem będzie wygenerowanie nagłówka dla naszego pliku danych. W przykładzie będzie to plik ZNAKI.FNT zawierający nowy, stworzony przez nas zbiór definicji znaków. Pisany przez nas w QA program spodziewa się, że te definicje znajdą się pod adresem, powiedzmy, $8000. HEADER.ASM powinien wyglądać tak:
     OPT %1100101
* generowanie czystego (bez
* nagłówków) kodu na dysk

DATA EQU $8000 tu podajemy
* adres gdzie mają znaleźć
* się dane z pliku

DLEN EQU 1024 tu podajemy
* długość danych w pliku

DEND EQU DATA+DLEN-1
* tu następuje obliczenie
* końca danych

* teraz konstruujemy nagłówek
* dla naszego pliku

     DTA A($FFFF)
* nagłówek pliku binarnego

     DTA A(DATA)
* adres początku danych w pamięci
     DTA A(DEND)
* adres końca danych w pamięci

     END
   Po bezbłędnej assemblacji powinniśmy otrzymać plik HEADER.OBJ zawierający potrzebny nam nagłówek. Teraz z pliku z definicjami i z pliku z nagłówkiem stworzymy binarny, dający załadować się z poziomu DOS-u plik z definicjami znaków. Uruchamiamy APPEND i wprowadzamy HEADER.OBJ, następnie ZNAKI.FNT. Kolejność wczytywania plików jest bardzo istotna, inna nie miałaby specjalnego sensu. Przechodzimy, naciskając RETURN, w tryb zapisu i wprowadzamy nazwę pliku docelowego np. ZNAKI.OBJ. W efekcie tych działań plik ZNAKI.OBJ możemy załadować wydając interpreterowi polecenie CP komendę ZNAKI.OBJ (możemy ten plik nazwać ZNAKI.COM i wydawać polecenie ZNAKI, ale nie jest to zbyt eleganckie, gdyż wypada, aby zewnętrzne polecenia CP coś robiły, a nie ładowały tylko dane do pamięci). Po wydaniu tego polecenia w pamięci od adresu $8000 do $83FF znajdą się pożądane przez nas definicje znaków. Teraz nic nie stoi na przeszkodzie, by wczytać Quick Assembler i przystąpić do pracy nad programem. Musimy tylko uważać, by w wyniku pracy pisanego przez nas programu jak i assemblera nie zniszczyć znajdujących się w pamięci danych (w tym przypadku definicji znaków). Należy generować w odpowiednie miejsce kod programu i ustawić odpowiednio obszary pracy QA (patrz jego podręcznik).

   Gdy wszystkie części naszego programu są już bezbłędne, a pliki danych zostały zamienione na pliki binarne (np. opisaną wyżej metodą) możemy przystąpić do scalenia ich w gotowy program. Uruchamiamy APPEND i wczytujemy po kolei do bufora wszystkie części naszego programu (zarówno kod jak i dane). Przechodzimy w tryb zapisu i podajemy docelową nazwę naszego programu (teraz możemy dodać rozszerzenie .COM, gdyż mamy już gotową działającą samodzielnie zewnętrzną komendę systemu operacyjnego). W czasie ładowania kod i dane naszego programu znajdą się w odpowiednich miejscach pamięci i uruchomi się on, o ile wygenerowaliśmy mu odpowiedni blok z adresem startu. Jeśli uszło to naszej uwadze to należy w programie umieścić następujące linie:

   W wybranym miejscu naszego programu, czyli tam gdzie chcemy aby zaczął się wykonywać deklarujemy np. taką etykietę
START EQU *
Następnie w dogodnym miejscu piszemy
      ORG $2EO
      DTA A(START)
   To powinno nam zapewnić pomyślny start programu po jego załadowaniu.

   Opisane powyżej metody nie wyczerpują wszystkich możliwych przypadków. Dzielenie programu na części i posługiwanie się plikami binarnymi wymaga pewnej wprawy i wiedzy. Często trzeba będzie sięgnąć po monitor dyskowy, aby pliki z danymi pozbawić dodatkowych, zbędnych dla nas informacji. Trzeba znać rozmieszczenie w pamięci Quick Assemblera, jego bufora, ekranu, DOS-u itd., gdyż konflikty adresów w pamięci mogą doprowadzić do tragicznych załamań się systemu i utraty efektów często wielogodzinnej pracy. Jednak wieloletnia praktyka wielu programistów korzystających z tej metody wykazała jej przydatność oraz najlepszą efektywność przy pracy ze standardowym, pozbawionym rozszerzeń sprzętem.

1000 REM ---------------------------
1001 REM :         APPEND          :
1002 REM :  autor:  Maciej Miasik  :
1003 REM : (c)1991 Tajemnice Atari :
1004 REM ---------------------------
1010 DATA ffffe002e102008000806c8738
1020 DATA a56a85e0e904856a2901f002c6
1030 DATA 6a2094efa200a56a85f386f2a9
1040 DATA e085f186f0a204a000b1f091f2
1050 DATA 88d0f9e6f1e6f3cad0f0a90885
1060 DATA e3a200a56a85f386f2a9e085f1
1070 DATA 86f0a6e318bdb88065f085f0a9
1080 DATA 0365f185f118bdc18065f285f2
1090 DATA a90265f385f3a007b1f091f288
1100 DATA 10f918bdca8065f285f28a0aaa
1110 DATA a001bdd38011f291f2e88810f5
1120 DATA c6e310afa56a8df402a90b8d42
1130 DATA 03a9e58d4403a9808d4503a949
1140 DATA 8d4803a9018d4903a2002056e4
1150 DATA a9008de0028de10220b0866ce7
1160 DATA 0208182860707898d0d0081828
1170 DATA 60707898c0d006000603000000
1180 DATA 00000300080c06002004080c08
1190 DATA 0c080c080c00189b506f677261
1200 DATA 6d207363616c616a0163792041
1210 DATA 5050454e4420776572736a6120
1220 DATA 342e309b646c612054414a454d
1230 DATA 4e4943204154415249206e6170
1240 DATA 6973610c204d2e4d690173696b
1250 DATA 2e9b9b506f64616a206e617a77
1260 DATA 0520706c696b7520646f20646f
1270 DATA 0c01637a656e6961206c75629b
1280 DATA 737a61626c6f6e20286e702e20
1290 DATA 2a2e2a2920772063656c75206f
1300 DATA 64637a7974759b6b6174616c6f
1310 DATA 67752077672e207465676f2073
1320 DATA 7a61626c6f6e75206c75629b77
1330 DATA 70726f77616418207075737401
1340 DATA 206c696e690520772063656c75
1350 DATA 207a6d69616e799b7472796275
1360 DATA 207072616379207a206f64637a
1370 DATA 797475206e61207a617069739b
1380 DATA 69207a207a6170697375206e61
1390 DATA 206f64637a7974206c75629b77
1400 DATA 70726f776164182074796c6b6f
1410 DATA 206b726f706b0520282e292077
1420 DATA 2063656c75209b6f7075737a63
1430 DATA 7a656e69612070726f6772616d
1440 DATA 7520415050454e442e9b9bad95
1450 DATA 8585f4ad968585f518ade50269
1460 DATA 0185f6ade602690085f7a5f485
1470 DATA f8a5f585f9a56a8df402200185
1480 DATA 20de82ae8d85ac8e8520138520
1490 DATA 0185ae8f85ac9085201385202b
1500 DATA 85301cad5f86c99bf015c92ef0
1510 DATA 55207f8390062097834c4f8220
1520 DATA dc834c4f82a56a8df402200185
1530 DATA 206083ae9185ac928520138520
1540 DATA 0185ae9385ac9485201385202b
1550 DATA 8530dbad5f86c99bd0034c2e82
1560 DATA c92ef011207f8390062097834c
1570 DATA 90822039844c9082a5e0856a20
1580 DATA 94ef6c0a0038a5f8e5f485d3a5
1590 DATA f9e5f585d4206485ad8d8585fa
1600 DATA ad8e8585fba00b200f8338a5f6
1610 DATA e5f885d3a5f7e5f985d4206485
1620 DATA a01a84e1a205a92091fac8cad0
1630 DATA faa4e1a98085e1a5d220508320
1640 DATA 5285a5d1205b83205083205285
1650 DATA a5d1205083205285a5d0205b83
1660 DATA 205083205285a90085e1a5d04c
1670 DATA 528548c900f004a90085e16860
1680 DATA 4a4a4a4a6038a5f8e5f485d3a5
1690 DATA f9e5f585d4206485ad918585fa
1700 DATA ad928585fba00b4c0f83a200bd
1710 DATA 5f86c99bf00dc93ff007c92af0
1720 DATA 03e8d0ee38601860a90620b584
1730 DATA 10034c8184200185a9058d5203
1740 DATA ad9b858d5403ad9c858d5503a9
1750 DATA 288d5803a9008d5903a2102056
1760 DATA e41007c088f00f4c8184ae9b85
1770 DATA ac9c852013854ca4834cf784a9
1780 DATA 0420b58410034c8184a5f88d54
1790 DATA 03a5f98d550338a5f6e5f88d58
1800 DATA 03a5f7e5f98d5903a9078d5203
1810 DATA 2056e4c088f019c003f015c001
1820 DATA f002d06c200185ae8985ac8a85
1830 DATA 2013854c338418a5f86d580385
1840 DATA f8a5f96d590385f920f7843049
1850 DATA 60a5f8c5f4d012a5f9c5f5d00c
1860 DATA 200185ae8785ac88854c1385a9
1870 DATA 0820b5843029a5f48d5403a5f5
1880 DATA 8d550338a5f8e5f48d5803a5f9
1890 DATA e5f58d5903a90b8d52032056e4
1900 DATA 300620f78430016084e2a56a8d
1910 DATA f40220f784a5e2205e85ad8b85
1920 DATA 85faad8c8585fba011a5d12052
1930 DATA 85a5d0204985200185ae8b85ac
1940 DATA 8c85201385a4e2608d5a03a900
1950 DATA 8d5b03a9038d5203ad6086c93a
1960 DATA d00ead5f86c943d016a9808d5b
1970 DATA 03d00fad6186c93af008ae9985
1980 DATA ac9a85d006ae9785ac98858e54
1990 DATA 038c5503a2104c56e4a90c8d52
2000 DATA 03a2104c56e4a90b8d4203a200
2010 DATA 8e48038e4903a99b4c56e48e44
2020 DATA 038c4503a9098d4203a9ff8d48
2030 DATA 038d4903a2004c56e4a9058d42
2040 DATA 03ad97858d4403ad98858d4503
2050 DATA a2008e4903a9288d48034c56e4
2060 DATA 484a4a4a4a20528568290f0930
2070 DATA 24e1300391fac86085d3a90085
2080 DATA d4a90085d085d185d2a20ff806
2090 DATA d326d4a5d065d085d0a5d165d1
2100 DATA 85d126d2ca10ebd860009f85b3
2110 DATA 85d485ec850c862d863e86af86
2120 DATA 5f865c86878600004275666f72
2130 DATA 206a6573742070757374792021
2140 DATA fd9b506c696b206e6965206d69
2150 DATA 65136369207369052077206361
2160 DATA 0c6f1363692021fd9b57797374
2170 DATA 0170690c20620c0164206e7220
2180 DATA 2e2e2e2021fd9b57206275666f
2190 DATA 727a653a20313233343520776f
2200 DATA 6c6e7963683a2031323334359b
2210 DATA 506f64616a206e617a77052070
2220 DATA 6c696b7520646f20646f0c0163
2230 DATA 7a656e69613a9b57206275666f
2240 DATA 727a653a2020202020209b506f
2250 DATA 64616a206e617a770520706c69
2260 DATA 6b7520646f63656c6f7765676f
2270 DATA 3a9b44313a2020202020202020
2280 DATA 20202020202020202020202020
2290 DATA 20202020202020202020202020
2300 DATA 20202020202020202020202020
2310 DATA 20202020202020202020202020
2320 DATA 20202020202020202020202020
2330 DATA 2020202020202020a9608db086
2340 DATA a90085cfa92e85d2a98285d3ad
2350 DATA e70285d4ade80285d538a5d2e5
2360 DATA d485d0a5d3e5d585d1a000f003
2370 DATA 3866cfa5d2c9b0a5d3e9869001
2380 DATA 6024cf70683027b1d285ce91d4
2390 DATA 206087aaf0e0c920f017c940f0
2400 DATA dbc960f0d7290dc908f0d19046
2410 DATA 8a291fc909f03fb1d2c8c92eb1
2420 DATA d288e9829012b1d2c8c9b0b1d2
2430 DATA 88e986b006a5d0a6d1900724cf
2440 DATA 30a3a900aa85d686d738b1d2e5
2450 DATA d691d4206087b1d2e5d791d420
2460 DATA 60874cdf86b1d291d42060874c
2470 DATA df86e6d2d002e6d3e6d4d002e6
2480 DATA d560

Maciej Miąsik



Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001