!!!!!!! Sa czytelnia Try2emu

Sa

Dziś kontynuujemy nasze rozważania o translacji na język maszynowy programów napisanych w językach wysokiego poziomu.
 

Z samej zasady interpretacji wynika, że poprawność każdej instrukcji programu źródłowego jest badana dopiero gdy przyszła kolej na wykonanie tej instrukcji. Tak więc może się zdarzyć, że dopiero po wykonaniu znacznej części programu dowiemy się, że mamy błąd w jednej z ostatnich instrukcji. (Będzie to szczególnie niemiłe gdy pro gram wykonuje się naprawdę długo.) Natomiast dobry kompilator nie przerywa tłumaczenia po napotkaniu błędu w programie źródłowym, tylko stara się za jednym prze biegiem wykryć również wszystkie pozo stałe błędy.

Czasami zaletą kompilatora jest również to, że otrzymany kod wynikowy jest prawie zupełnie nieczytelny dla człowieka, a więc wprowadzanie w nim zmian może być bardzo trudne. Tak więc gotowy do pracy, w pełni działający program możemy rozpowszechniać bez obawy, że ktoś niepowołany w ciągu godziny może zmienić w nim to co zechce, jak to ma miejsce w przypadku programów źródłowych*).

Teraz wróćmy jeszcze do opisu kompilatora. Wiele działających systemów pozwala wyłączyć z programu głównego używane w nim procedury (podprogramy) i kompilować je oddzielnie. Jest to poważna zaleta, gdyż w przypadku dużych programów, składających się z wielu podprogramów, i zawierających w sumie tysiące instrukcji nie musi my po wprowadzeniu jednej poprawki kompilować ponownie całości — wystarczy kompilacja tej jednej, zmienionej procedury. Bardzo to miłe i wygodne, ale w tej chwili widać już, że pisząc krótko: „po zakończeniu kompilacji można wykonać otrzymany kod wynikowy" popełniłem drobne nadużycie, polegające na zbytnim uproszczeniu. Otóż kod wynikowy otrzymany po kompilacji na ogół nie jest jeszcze gotowy do wykonania, ostatecznym produktem. (Gdy by tak było, to kiedy byśmy dołączali niezależnie skompilowane procedury?) Niezbędny jest jeszcze jeden etap, który scali wszystkie utworzone niezależnie od siebie kawałki kodu w jedną całość — gotów do wykonania program. Jest to potrzebne nawet jeśli nie tworzyliśmy podprogramów, gdyż zawsze trzeba dołączać standardowe, dostarczane przez kompilator, procedury, np. wejścia, wyjścia.

Omówiony etap nazywany bywa różnie: scalanie, ładowanie**), linkowanie, konsolidacja, i jak nietrudno zgadnąć, wykonywany jest przez specjalny program. Oczywiście, utworzony po tym etapie program maszynowy (tym razem już na szczęście ostateczny) można także zapisać w pamięci zewnętrznej i wielokrotnie go używać bez potrzeby ponownej konsolidacji.

Skoro mamy możliwość dołączania kodu ze skompilowanych wcześniej procedur, to nieważne, czy te procedury były napisane wczoraj, czy rok temu, czy przez nas, czy przez kogoś innego. Krótko mówiąc, doszliśmy do szeroko stosowanej koncepcji bibliotek podprogramów (ang. library). Taka biblioteka to nic innego jak specjalnie zorganizowany zbiór, zawierający skompilowaną postać pewnej liczby procedur, np. do rozwiązywania jednej klasy zadań — mate matycznych, ekonomicznych, statystycznych itd. Biblioteka matematyczna może np. zawierać gotowe procedury rozwiązywania układów równań, czy znajdowania miejsc zerowych funkcji. Taki zbiór procedur, wraz ze szczegółową specyfikacją tego co robią poszczególne procedury i jak wywołać je w programie, może być dostarczany wraz z kompilatorem lub sprzedawany jako dodatkowe udogodnienie. Korzystanie z bibliotek to po prostu umieszczanie w programie wywołań procedur, których treści nie musimy pisać — na etapie scalania właściwe moduły zostaną wybrane z biblioteki i dołączone do ostatecznego programu.

Następne rozszerzenie możliwości programisty wynika z faktu, że skoro scalamy moduły wynikowe, pochodzące z kompilacji, to przecież nie musi być ważne w jakim języku poszczególne programy były napisane przed skompilowaniem. Jeśli tylko za chowana będzie standardowa postać kodu wynikowego, to możemy łączyć ze sobą podprogramy pisane w różnych językach programowania, a to czasami bywa bardzo wygodne.

Niestety nie wszystkie języki programowania wysokiego poziomu pozwalają na realizację tej możliwości.

To co powiedzieliśmy do tej pory o translacji można potraktować jako pewien ogól ny schemat, którego fazy występują w róż nych translatorach w sposób nie zawsze wyraźnie widoczny dla użytkownika. W pro duktach różnych firm można spotkać wiele szczegółowych rozwiązań technicznych różniących się między sobą, ale zasada jest zawsze taka sama. Przy tej okazji jeszcze trochę terminologii związanej z kompilacją. Niektóre kompilatory wykonują więcej niż jeden przebieg (ang. pass). Oznacza to, że najpierw czytany jest cały program i przetwarzany do postaci pośredniej. Następnie, (w drugim przebiegu) przetwarzana jest ta postać pośrednia itd. W niektórych podręcznikach określa się proces scalania jako kolejny (ostatni) przebieg kompilatora.

Spróbujmy teraz porównać obie metody translacji. Zastępując interpreter kompilatorem zyskujemy nie tylko większą prędkość działania programów ale i wiele innych dodatkowych możliwości. Niemniej jednak, w sytuacjach, w których przebiegi programów nie są długie, za to często wprowadzamy zmiany i program musi być tłumaczony na nowo, łatwość korzystania z interpretera może być przeważającą zaletą. Taką właś nie sytuację mamy podczas pisania i uruchamiania programów, i wtedy użycie interpretera na ogół jest opłacalne. Natomiast program, który został ukończony i będzie już wprowadzony do eksploatacji warto skompilować***). Oczywiście, oprócz ko du wynikowego należy przechowywać zawsze wersję źródłową, co umożliwi wprowadzanie poprawek lub modyfikacji w przyszłości.

Języków programowania jest bardzo wie le, wiele z nich doczekało się realizacji na kilku różnych komputerach. Bywa nawet tak, że ten sam język ma kilka różnych translatorów na te| same] maszynie. W tej sytuacji nasuwa się pytanie, który z nich wybrać (jeśli oczywiście mamy wybór, a do tego należy dążyć)? Niestety me ma tu jedno znacznej odpowiedzi, gdyż w zależności od problemu różne cechy dostępnych języków będą miały decydujące znaczenie. W informatyce profesjonalnej dla każdego poważnego zadania dobiera się język, w którym można je najskuteczniej zaprogramować — wybór języka jest po prostu jednym z elementów procesu rozwiązania zadania. Istnieje nawet wiele języków tzw. problemowe zorientowanych, to znaczy zaprojektowanych z myślą o programowaniu tylko pewnej szczególnej klasy zadań, np. do symulacji lub zastosowań ekonomicznych.

Amator jest tu w gorszej sytuacji niż informatycy zawodowi. Na mikrokomputerach domowych nie ma do dyspozycji tylu translatorów co na sprzęcie profesjonalnym jego możliwości uczenia się nowych języków są także ograniczone. Co radzić w tej sytuacji? Po pierwsze pamiętajmy, że BASIC jest językiem bardzo przestarzałym zdecydowanie nie zalecanym jako język do nauki programowania. Był on już prawie zapomniany, gdy nagle okazało się, że jest o-1 na tyle prosty (czytaj prymitywny), że da się dla niego zrobić interpreter, który zmieści się w ROM-ie domowego mikrokomputera. W tej chwili walczyć z BASIC-iem nie ma sensu — akceptujemy go jako zło konieczne. Natomiast językiem, który warto polecić jest niewątpliwie PASCAL. Język ten (opi sywany szczegółowo w „Bajtku") daje programiście bardzo duże możliwości, a równocześnie jego struktury ułatwiają wyrobie nie sobie właściwego stylu programowania — bez nadużywania instrukcji skoku.

(dokończenie za miesiąc)

 

*) nie jest to na pewno zabezpieczenie absolutne, kod wynikowy też można rozszyfrować i zmienić, ale wymaga to naprawdę dużego nakładu pracy, więc większość potencjalnych piratów to odstrasza.

**) termin ładowania używany bywa w najróżniejszych znaczeniach, zwykle gdy wpisujemy cokolwiek do pamięci operacyjnej. Użycie tutaj wy wodzi się z faktu, że często scalanie modułów wynikowych odbywa się podczas wpisywania (właśnie „ładowania") tych modułów do PaO.

***) w tym celu musimy dysponować interpreterem i kompilatorem rozpoznającym dokładnie tę samą wersję języka źródłowego, gdyż poszczególne realizacje tego samego języka programowania, np. przygotowane przez różne firmy, zwykle różnią się trochę między sobą.

Andrzej Pilaszek