12. 10. 2015

Hrátky s Pascalem

Jakkoli nespravedlivým se nám to může jevit, životnost programovacího jazyka nemá žádnou korelaci s jeho kvalitou. Stařičcí FORTRAN a COBOL žijí dodnes, kdežto jejich ambiciosnější následovník Algol byl pohřben již někdy v 80. letech a co byla Simula, se dočteme nejvýš v knihách o historii počítačů. Mrtev je dnes i Pascal, a je určitou kuriositou, že známý sarkastický text Real Programmers Don't Use Pascal samotný jazyk patrně přežije.

Při emulaci osmibitů jsme ovšem v polovině 80. let a tehdy bylo vše jinak, proto jsme chtě-nechtě nuceni Pascal do emulátoru pojmout. U PMD 85 měl jeho kompilátor podobu zásuvného ROM-modulu, a jeho autorem byl bratislavský programátor Peter Tomcsányi.

Stejně jako v případě Basicu potřebujeme mít možnost nahrávat programy z textových souborů v hostitelském počítači a zpětně je do textového souboru ukládat, včetně konverse tehdejšího kódování (což byl v případě PMD 85 upravený kód KOI8-čs; takto jsem to pojal v Javě); jinak bychom při praktickém používání emulátoru patrně zešíleli, protože bychom byli odkázáni na možnosti editace mírně řečeno nebohaté.

Tuto funkci jsem u Basicu i Pascalu implementoval jako jeden z pluginů modulu Memory. U Basicu jsem vyšel z toho, že vnitřní (tokenisovaná) representace programu v paměti je relativně jednoduchá, a podobně snadné je vytvořit datovou strukturu. Program se proto generuje/rekonstruuje (tokenisuje/detokenisuje) přímo v Javě a z Basicu se volá pouze jediná rutina, která zajistí vymazání proměnných a správné nastavení všech ukazatelů.

U Pascalu jsem zvolil jiný přístup a rozhodl se nechat pracovat kompilátor. To ovšem předpokládalo porozumět tomu, jak kompilátor funguje, která interní proměnná má jaký význam a který podprogram co dělá.

To je, s úvahou velikosti kompilátoru 20 KiB v jednodušší versi, úkol dimense mírně sisyfovské. Naštěstí k tomu máme dnes mocné nástroje. Jedním z nich je debugger, umožňující kompilátor trasovat a krokovat a sledovat průběžně stav registrů i paměti.

Druhým, neméně významným, je funkce emulátoru dovolující zapsat stav celé paměti do jednoho binárního souboru. Chtěl-li jsem vědět, jaké změny v paměti provede např. tokenisační rutina (v Pascalu V1.02 na adrese 0x4780, ve versi V2.2 na 0x30f4), prostě jsem si na její volání nastavil breakpoint, uložil obraz paměti RAM do souboru, podprogram nechal provést a znovu uložil celou paměť. Poté už stačilo triviálně použít linuxové nástroje hexdump a diff a měl jsem výsledek v dokonale přehledné, elegantní podobě. Vidíme, že rutina zapsala tokenisovaný obraz řádku – v daném případě komentáře – od adresy 0x254 (a pracovala se zásobníkem, což nás arci nezajímá); další rutina pak tento obraz přesune na konečné místo určení, které závisí na modelu PMD.

Třetí nástroj, bez kterého by se podobné hrátky vůbec nedaly praktikovat, je disassembler. Nepoučený laik by řekl, že lidé zvyklí na open-source projekty nikdy nedisassemblují, ale tak tomu není: právě schopnost efektivně pracovat s disassemblery je jednou z nejdůležitějších dovedností každého hackera.

Podstatou disassemblingu je postupná analysa kodu, probíhající v řadě kroků – iterací. První výstup disassembleru je dokonale nesrozumitelný, je to změť operací s paměťovými místy, jejichž význam neznáme, a volání podprogramů, o kterých nevíme, k čemu slouží a co dělají. Tím, jak postupně pronikáme do smyslu kodu, získáváme více a více informací, které vyjadřujeme průběžně doplňovanou, rozšiřovanou a upřesňovanou tabulkou bloků a tabulkou symbolů, jimž přiřazujeme smysluplné identifikátory, a v postupných iteracích tak dospějeme do stavu, že kodu porozumíme buď zcela, nebo minimálně v těch částech, které jsou pro daný účel relevantní. Například tedy, jak a kam se ukládá soukromý klíč, anebo, v našem případě, jak fungují rutiny pro tisk programu a pro jeho čtení z magnetofonové kasety, neboť právě ty potřebujeme nalézt a v modifikované podobě v emulátoru využít.

Pro Pascal jsem použil nástroj z80dasm a obě verse kompilátoru jsem pomocí něj analysoval. Zhruba po dvou dnech práce jsem získal výsledek, který mi dovolil naprogramovat oba směry konverse tak, že v Javě se provede pouze konverse znaků z/do Unicodu a vše ostatní dělá kompilátor.

Nyní tedy mohu pascalový modul využívat a psát v něm, budu-li mít potřebu, programy, řádově rychlejší než ty basicové.

3 komentáře:

  1. Dobrý nápad.
    Export a Import sme v našom emulátore riešili iba pre BASIC a iba na úrovni Prieskumníka pásky. Pascal vôbec nieje v pláne.
    Naviac, v emulátore je možnosť vložiť text zo schránky, takže tá možnosť importu "plain" textu do BASICu, či Pascalu máme, aj keď je to pomerne pomalé, pretože sa simuluje vstup z klávesnice, keďže sme to chceli univerzálne, aby ten vstup bol možný kdekoľvek.

    Pri prezeraní Vami linkovaných zdrojových textov som si v Basic.java všimol, že je chybne uvedený názov posledného príkazu. Má to byť REN - RENumber.

    OdpovědětVymazat
    Odpovědi
    1. Naviac, v emulátore je možnosť vložiť text zo schránky, takže tá možnosť importu "plain" textu do BASICu, či Pascalu máme, aj keď je to pomerne pomalé, pretože sa simuluje vstup z klávesnice, keďže sme to chceli univerzálne, aby ten vstup bol možný kdekoľvek.

      To plánuji, nejspíš jako jeden z Load pluginů, ale předtím musím vyřešit problémy se znaky, které se realisují dvojhmaty, např. čeština/slovenština; něco mi tam pořád "hapruje".

      Import a export se touto funkcí ale plnohodnotně nenahradí: nízká rychlost je jeden problém, druhý je nepraktičnost při ladění. Každou změnu musíte buď provést dvakrát, jednou na PMD, jednou na hostitelském stroji, anebo pokaždé znovu program zavést přes emulovaný vstup z klávesnice.

      Pri prezeraní Vami linkovaných zdrojových textov som si v Basic.java všimol, že je chybne uvedený názov posledného príkazu. Má to byť REN - RENumber.

      Ovšem! Díky, opravil jsem.

      Vymazat
  2. Cobol stale ide na Mainframe, v USA udajne 80% bussinesu. Fortran je napr. vypuzivany v CERNe. Naco menit overeny, spolahlivy software?

    OdpovědětVymazat