11 lutego 2019

Konieczność TRYBU-B


Jeżeli śledzisz moje konta na twitterze, facebooku czy githubie, mogłeś zauważyć, że piszę emulator PDP-8 na iPada.
Oto screenshot:


Poniższy tekst jest luźnym tłumaczeniem wpisu bloga Roberta Cecila "Wujka Boba" Martina z dnia 21 lutego 2015 ze strony:


Proszę o komentarze, jeżeli ta luźność jest zbyt daleko posunięta.


Moim celem napisania tego emulatora (poza zwykłą nostalgią) jest wykorzystanie go jako narzędzia szkoleniowego dla nowych programistów. Myślę, że każdy świeżo upieczony programista powinien spędzić tydzień lub dwa programując na jednej z tych starych maszyn. Wydaje mi się, że nie ma lepszego sposobu, aby zrozumieć, czym komputer tak naprawdę jest, jak tylko móc dotknąć prawdziwego komputera i móc zaprogramować go na poziomie bitów, w języku maszynowym. Jak tylko to zrobisz, cała magia zniknie i zostanie zastąpiona przez twardą, brutalną rzeczywistość. I, coś Ci powiem, programowanie PDP-8 jest twardą, brutalną, rzeczywistością. A niech mnie, jak cholera!
Chciałem być wierny maszynie i jej środowisku. Panel przedni jest przyzwoitą abstrakcyjną reprezentacją oryginalnego PDP-8, i światełka zapalają się odpowiednio, i z prawidłowymi danymi (chociaż nie mogłem się oprzeć i zrobiłem światełka wrażliwe na dotyk, tak jak w ECP-18).

Papierowe taśmy w czytniku i dziurkacz poruszają się z odpowiednimi prędkościami i dziurki reprezentują prawdziwe dane. Wydają one także odpowiednie rodzaje dźwięków. Dalekopis drukuje z odpowiednią prędkością (chociaż możesz go przyspieszyć, jeśli chcesz (będziesz chciał)) i zachowuje się mniej więcej jak ASR-33, wydając odpowiednie dźwięki, i reagując odpowiednio na znaki powrotu karetki i wysuwu wiersza itd. (Tak, możesz naddrukować!)
Znalazłem jakieś binarne obrazy starego PDP-8 tutaj, i udało mi się wrzucić je do mojego emulatora, miażdżąc ich format przy użyciu małego programu w C, i wrzucając je na iPada, używając Dropboxa. Wynik tych działań był zarówno satysfakcjonujący, jak i łapiący za serce. Starożytny kod działa!
Usiadłem przy bezprzewodowej klawiaturze mojego 600-dolarowego, ćwierćkilogramowego, obudowanego w fajny pokrowiec iPada, otoczony podręcznikami programowania i poznaczonymi listingami programu, nad którym pracowałem. Uświadomiłem sobie wtedy, że pracuję nad kodem napisanym pół wieku temu, stworzonym przez mężczyzn i kobiety (prawdopodobnie w większości przez kobiety w tamtych czasach), którzy zakasywali rękawy, aby sprawić, żeby ich śmieszna maszyna działała. Maszyna, która ważyła 225 kg, była rozmiaru lodówki i kosztowała 20'000$ w roku 1967.
Czy ktokolwiek z tych ludzi mógłby kiedykolwiek przypuszczać, że ich kod będzie odpalany na podręcznym tablecie i będzie używany do szkolenia programistów w dwudziestym pierwszym wieku? Niektórzy - wielu - mogą jeszcze żyć. Ciekawe co pomyśleliby, gdyby wiedzieli.
Mój emulator napisany jest w Lua, przy użyciu frameworku Codea dla iPada. Lua to niezwykle wygodny język dla developmentu na iPada. Jest (wystarczająco) szybki, i Codea zawiera wspaniałe kontrolki graficzne, i prosty, acz nadal bardzo skuteczny framework do tworzenia wysoce interaktywnych programów pełnych animacji.
To załatwiło animację (i generowanie dźwięku) na przednim panelu, dalekopis, i czytnik/dziurkacz papieru za jednym zamachem.
Emulowanie bebechów PDP-8 staje się niezłym wyzwaniem odkąd Lua ma tylko jeden typ numeryczny: zmiennoprzecinkowy. Tworzenie 12-bitowej logiki przy użyciu li tylko matematyki zmiennoprzecinkowej, jest, hmmm, interesujące. Z drugiej strony, miałem niezłą frajdę z oglądania FOCAL(FORmula CALculator: języka podobnego do Basica) odpalonego na moim PDP-8, dokonującego obliczeń zmiennoprzecinkowych, używając operacji logicznych, które to z kolei wymyśliłem przy użyciu matematyki zmiennoprzecinkowej LUA. &ltuśmiech&gt Powinieneś był zobaczyć, jak te światełka mrugały!
Prędkość uruchomieniowa to około 4000 instrukcji na sekundę. Mimo że to tylko 1/7 prędkości PDP-8/S, było to całkiem imponujące jak na iPada wykonywującego język "interpretowanego byte-codu" taki jak Lua, emulującego 12-bitową logikę przy użyciu obliczeń zmiennoprzecinkowych! Nie spodziewałem się takiej szybkości. W zasadzie odpala cały ten stary software firmy DEC z sensowną prędkością. Nawet FOCAL działa wystarczająco szybko do obliczania pierwiastków kwadratowych w coś koło pół sekundy.
I, znowu, te mruganie światełek podczas kompilacji jest bardzo przyjemne. Tylko popatrz, a od razu odkryjesz, czym były inspirowane filmy science-fiction z lat 50-tych XX. wieku.

TRYB-B

Sprawienie, aby kompilator działał, było naprawdę bardzo łatwe. Prawdopodobnie spędziłem nad tym w całości 30 godzin; i to włącznie z uczeniem się Codea i Lua.
Proces developmentu pędził jak szalony. Edytor Lua w Codea dla iPada jest potężyny i intuicyjny (chociaż nie ma refaktoringów &ltchlip&gt). Pętla edycji/testowania trwała, może, 10 sekund. Mogłem dodać linie, czy dwie, odpalić appkę, zobaczyć efekt, wskoczyć z powrotem do edytora ot tak. To była przyjemne udogodnienie i miałem przy tym niezłą zabawę.
Oczywiście napisałem testy do trudniejszych kawałków. Napisałem mały framework testowy, tylko do tego celu, i dodałem przycisk TEST na panelu przednim emulatora, aby ułatwić sobie odpalanie tych testów. Kod emulacji sam w sobie byłby prawie niemożliwy do napisania, gdybym nie miał tych testów. I, oczywiście, korzystałem z dyscypliny TDD przy pisaniu tego kodu. Koniec końców powstało ponad 100 testów dla najróżniejszych instrukcji i zachowań komputera PDP-8.
Dla GUI, z drugiej strony (i było tam mnóstwo kodu GUI), testy były niepotrzebne (&ltoch&gt). Moje oczy były testami. Wiedziałem, co chcę zobaczyć, więc rozkręciłem 10-sekundową pętlę edytuj/testuj. Pisanie testów w stylu TDD byłoby okropnie trudne, i stałoby się całkowitą stratą czasu.
Z drugiej strony, to był nadal rytm TDD. Wiedziałem, co chcę zobaczyć na ekranie. To był mój test. Po prostu zmodyfikowałem kod, zanim test został spełniony. A więc nawet jeśli nie pisałem testów, czułem się tak, jakbym pisał - czułem się, jak podczas TDD.
Oczywiście to prawda, że nie miałem zautomatyzowanych testów regresji dla mojego GUI. Z drugiej strony upewnienie się, czy wszystko działa było absurdalnie proste. W ten sposób brak zautomatyzowanych testów GUI nie wpłynął na czas trwania mojej pętli.
Oczywiście, bez narzędzi do refaktoringu kod zrobił się trochę zabałaganiony. Zrefaktorowałem to, czego nie mogłem znieść; ale rozmiar zabałagacenia jest większy, niżbym chciał. Uda mi się później posprzątać ten kod; ale dużo wolniej pracuje się bez dobrych narzędzi do refaktoringu.
Tym nie mniej, na potrzeby tego artykułu, nazwijmy ten styl programowania: TRYB-B. TRYB-B jest stylem, który pozwala Ci jednocześnie edytować coś na ekranie i widzieć na tym ekranie skutki, lub test, który przechodzi, w ciągu kilku sekund. To development o prędkości światła, który nie wymaga listingów, ołówków, czasu kompilacji, czasu poświęconego na ustawienie, lub żadnego innego utrudnienia. Czas pomiędzy edytowaniem kodu a oglądaniem go działającym jest dużo mniejszy niż jedna minuta.

TRYB-A

Mając działający Emulator PDP-8, i mając te wszystkie stare narzędzia takie, jak edytor taśmy papierowej, i działający assembler PAL-III, zabrałem się za pisanie prostego programu. Ten program pozwoliłby użytkownikowi wpisać prostą formułę na klawiaturze, i wtedy wyświetliłby wynik. Dla przykładu, jeśli użytkownik wpisałby: 25+32, komputer wyświetliłby 57.
Na PDP-8 nie jest to trywialny program. Zamieściłem go poniżej dla tych z Was, którzy chcieliby zobaczyć, jak biedni programiści PDP-8 musieli to pisać.
Proces był taki sam, jak proces, którego używałem w późnych latach 70-tych XX. wieku, kiedy pracowałem nad assemblerowymi programami na Teradyne M365 (18-bitowy kuzyn PDP-8). Mieliśmy taśmę magnetyczną, zamiast taśmy papierowej; i komputer był troszkę potężniejszy obliczeniowo niż PDP-8. Ale proces pozostawał taki sam. A leciało to tak:
Załóżmy, że jesteś w środku pisania tego programu z samego dołu. Już trochę napisałeś, i chcesz coś jeszcze dodać. Pamiętaj, ten komputer posiada słowa o długości tylko 4K. Nie może przechowywać wiele w swojej pamięci. Pamiętaj o tym, że jedynym magazynem pamięci masowej, którym dysponujesz, jest papierowa taśma. Także twój kod źródłowy jest na tym samym długim pasku tej samej papierowej taśmy.
  1. Zapisujesz zmiany, jakie chcesz wprowadzić do programu na aktualnym listingu. Będziesz miał zmiany na wielu stronach, więc wepnij spinacze biurowe na każdą ze stron, jeśli listing jest długi.
  2. Załaduj edytor z taśmy papierowej. To zajmie kilka minut, więc zrób sobie kawę.
  3. Ustaw przełączniki na panelu przednim na 6003: dla kompresji spacji, i użyj czytnika/dziurkacza wysokiej prędkości. Uruchom edytor (poprzez ustawienie 0200 na rejestrach PC i naciśnięcie klawisza RUN)
  4. Włóż papierową taśmę z twoim kodem źródłowym do czytnika
  5. Wczytaj jedną "stronę" kodu z papierowej taśmy używając komendy R. (50 linii lub mniej. 1 minuta lub więcej).
  6. Idź do tej strony w twoim listingu i nanieś poprawki, używając komend I, C i D. Pamiętaj, że nie masz ekranu, więc edytujesz linia po linii, używając numerów linii. Zaplanuj spędzić nad tym trochę czasu.
  7. Wydrukuj aktualną stronę, używając komendy L. Upewnij się, że wszystkie zmiany są poprawne.
  8. Wydziurkuj aktualną stronę na papierowej taśmie, używając komendy P. (minuta lub więcej).
  9. Wydziurkuj aktualną stronę i następnie ją wczytaj, używając komendy N i jeżeli to nie była ostatnia strona, idź do punktu 6.
  10. Wyjmij nową taśmę z kodem źródłowym z dziurkacza i oznacz ją tytułem i numerem wersji. Nigdy nie zapomnij o numerze wersji!
  11. Załaduj assembler do pamięci z papierowej taśmy (10 minut lub więcej).
  12. Ustaw przełącznik na panelu przednim na 2002: to konfiguracja "przejście pierwsze, wyjście na drukarkę".
  13. Załaduj źródłową taśmę do czytnika.
  14. Załaduj 0200 do rejestru PC, i wciśnij RUN.
  15. Kompilacja przejście pierwsze wczyta całą taśmę z kodem źródłowym i wydrukuje tablicę symboli. (10 minut albo więcej).
  16. Gdy komputer się zatrzyma, ustaw na panelu przednim przełączniki na 4003: konfiguracja "przejście drugie, wyjście na dziurkacz".
  17. Załaduj twój kod źródłowy do czytnika.
  18. Wciśnij RUN. Kompilacja przejście drugie wczyta całą twoją taśmę źródłową i wydziurkuje twoją binarną papierową taśmę. (15 minut albo więcej). Błędy w kodzie źródłowym wydrukują się podczas tego przejścia.
  19. Gdy komputer się zatrzyma, jeśli były jakieś błędy, wyrzuć papierową taśmę, która była przed chwilą dziurkowana i przejdź do punktu 1. Jeśli nie było, wyjmij taśmę binarną z dziurkacza i oznacz ją tytułem i numerem wersji. (Nie muszę Ci już przypominać o numerze wersji, prawda?)
  20. Ustaw przełączniki na panelu przednim na 6002: to konfiguracja "przejście trzecie, wyjście na drukarkę".
  21. Włóż twoją źródłową taśmę do czytnika.
  22. Wciśnij RUN. Kompilacja przejścia trzeciego wczyta całą taśmę z kodem źródłowym i wydrukuje listing programu. Będziesz potrzebował jej do debbugowania, więc nie zlekceważ tego. (30 minut albo więcej, ponieważ drukarka jest bardzo wolna). Upewnij się, że masz wystarczająco dużo papieru w drukarce!
  23. Oderwij listing i go sprawdź.
  24. Włóż swoją taśmę binarną do czytnika.
  25. Ustaw rejestry PC na 7777 (adres ładowarki binarnej, która zwykle jest przechowywana w pamięci rdzenia) i naciśnij RUN. Jeżeli w pamięci, z jakiegoś powodu, nie ma ładowarki binarnej, musisz przestawić się w tryb ładowarki RIM i wczytać ładowarkę binarną z papierowej taśmy przed tym krokiem.
  26. Gdy komputer się zatrzyma, twój program jest wczytany do pamięci. Uruchom go i zobacz, jak działa.
Ten proces jest bardzo skrócony. Jest tam jeszcze mnóstwo drobniejszych kroków, ale myślę, że masz już pełny obraz.
To jest TRYB-A. To jest bardzo delikatny, podatny na błędy proces, którego przeprowadzenie zajmuje godzinę lub więcej. Może być jeszcze dłużej dla większych programów. Bardzo mały program robi z tej pętli około 15 minut. Program, który pisałem, urósł do około 20-30 minut lub więcej, i oszukiwałem, pozwalając mojemu dalekopisowi działać z prędkością 10 razy większą niż normalna prędkość.
Żeby zmusić mój mały, śmieszny program do działania, szedłem tą pętlą siedem razy. Zajęło mi to około tydzień, i łącznie około pięć godzin. Wiele z tego było pisaniem kodu z użyciem ołówka, ponieważ bez edytora na ekranie, nie było możliwości ominąć ręcznego pisania, i używania gumki do ścierania bez przerwy.
W latach 70-tych spędzałem dni, tygodnie, i lata na pracy w TRYBIE-A. Wszyscy programiści spędzali. Tak właśnie wtedy wyglądało programowanie.
Jest jedna sprawa, jeśli chodzi o TRYB-A: MUSISZ BYĆ OSTROŻNY. Każdy błąd kosztuje cię godzinę lub więcej. Więc spędzasz mnóstwo czasu, ogarniając szczegóły, upewniając się, że kod jest dobry; że wyedytowałeś go odpowiednio; że przełączniki są ustawione właściwie; że taśmy są opisane poprawnie; etc
W TRYBIE-A nie bierzesz niczego za pewnik. Robisz wszystko rozmyślnie i ostrożnie. Ponieważ to jedyna droga, abyś robił to szybko. (Jeśli "szybko" jest w tym przypadku dobrym słowem.)
Nazwijmy tę rozwagę i ostrożność: zachowanie w TRYBIE-A.

TRYB-A kontra TRYB-B

TRYB-A jest o wiele wolniejszy niż TRYB-B. Czas pętli jest niemożliwie długi, zakres funkcjonalności, którą udaje Ci się stworzyć w ciągu każdej pętli, jest śmiesznie mały. Dla przykładu, podczas mojej pierwszej pętli w tym procesie napisałem i zdebbugowałem podprogram, który wczytywał linię tekstu z klawiatury, zakończonej znakiem CR ( Carriage Return - Powrót Karetki... Tak, dalekopis miał "karetkę", lub raczej "głowicę drukującą", którą można było zmusić do "powrotu".)
TRYB-B z kolei jest szybki! Naprawdę, naprawdę szybki. Czas pętli jest bardzo krótki, i możesz zrobić o wiele więcej w każdej pętli. Dla przykładu zajęło mi tylko kilka pętli, żeby zrobić poprawnie animację przechodzenia papierowej taśmy przez czytnik i dziurkacz. Każda maszynowa instrukcja PDP-8 zajęła mi pętlę lub dwie. Sprawienie, aby przesuwał się papier w TTY, zajęło mi dwie lub trzy pętle.
No i, oczywiście, nie używałem listingów. Nie pisałem kodu najpierw na papierze. Mogłem pójść gdziekolwiek, gdzie chciałem w programie i wyedytować dowolną linię, jaką chciałem w mgnieniu oka. Miałem podświetlanie składni, automatyczne wcięcia, znajdź i zamień, scrollowanie, zakładki, i dokumentację na Internecie.
Tryb-B jest szybki!

Konieczność TRYBU-B

Więc dlaczego jeszcze tak wielu programistów wciąż pracuje w TRYBIE-A? Robią to, wiecie. Wrzucają jedną kupę śmieci na drugą, i framework na framework, aż ich czas pętli rośnie z sekund do minut i dłużej. Wstrzykują tak wiele zależności, że ich buildy stają się kruche i podatne na błędy. Tworzą tak wiele niewyizolowanych zewnętrznych zależności, że mogliby równie dobrze używać papierowej taśmy. Jak ktokolwiek może robić cokolwiek, co może zwiększyć czas trwania tej pętli? Dlaczego nikt nie broni czasu swoich pętli z narażeniem życia?
Czy unikanie TRYBU-A nie jest naszą moralną powinnością? Czy nie powinniśmy robić wszystkiego, co tylko możliwe, aby utrzymać nasze cykle rozwoju oprogramowania w TRYBIE-B? Czy TRYB-B nie jest koniecznością?
Czy chcesz poznać sekret pozostawania w TRYBIE-B? Wiem, co to jest. Powiem Ci.
Sekretem pozostawania w TRYBIE-B jest wykorzystanie zachowania w TRYBIE-A.

A NIECH MNIE KULE METODOLOGII STRUKTURALNEJ BIJĄ!

Właśnie odkryłem, kto napisał assembler PAL-III na PDP-8. Czapki z głów. Był to Ed Yourdon.
Program dla PDP-8, który przyjmuje dwie liczby rozdzielone pojedynczym operatorem i wyświetla wynik:

           *20
0020  7563  MCR,    -215
0021  0212  KLF,    212
0022  7540  MSPC,   -240
0023  7520  MZERO,  -260
0024  7766  M10,    -12
0025  0276  PROMPT, 276 />
0026  0215  KCR,    215
0027  7525  MPLUS,  -253
0030  7523  MMINUS, -255
0031  0277  QMARK,  277
0032  0260  KZERO,  260

            /WORKING STORAGE
0033  0000  REM,    0

            /CALL SUBROUTINE IN ARG
0034  0000  CALL,   0
0035  3046          DCA AC
0036  1434          TAD I CALL
0037  3047          DCA CALLEE
0040  1034          TAD CALL
0041  7001          IAC
0042  3447          DCA I CALLEE
0043  2047          ISZ CALLEE
0044  1046          TAD AC
0045  5447          JMP I CALLEE
0046  0000  AC,     0
0047  0000  CALLEE, 0

----------------

            *200
            /CALC A+B OR A-B
            /MAIN LOOP: PROMPT, GET CMD, PRINT RESLT

0200  6046          TLS
0201  7200  IDLE,   CLA
0202  1026          TAD KCR
0203  4034          JMS CALL
0204  0425          PRTCHAR
0205  7200          CLA
0206  1025          TAD PROMPT
0207  4034          JMS CALL
0210  0425          PRTCHAR
0211  4034          JMS CALL
0212  0400          RDBUF
0213  2000          BUF
0214  4034          JMS CALL
0215  0462          SKPSPC
0216  2000          BUF
0217  3222          DCA .+3
0220  4034          JMS CALL
0221  0477          GETNUM
0222  0000          0
0223  3261          DCA A
0224  1622          TAD I .-2
0225  3263          DCA OP
0226  1222          TAD .-4
0227  7001          IAC
0230  3233          DCA .+3
0231  4034          JMS CALL
0232  0477          GETNUM
0233  0000          0
0234  3262          DCA B
0235  1263          TAD OP
0236  1027          TAD MPLUS
0237  7650          SNA CLA
0240  5254          JMP ADD
0241  1263          TAD OP
0242  1030          TAD MMINUS
0243  7650          SNA CLA
0244  5251          JMP SUB
0245  1031          TAD QMARK
0246  4034          JMS CALL
0247  0425          PRTCHAR
0250  5201          JMP IDLE

0251  1262  SUB,    TAD B
0252  7041          CIA
0253  7410          SKP
0254  1262  ADD,    TAD B
0255  1261          TAD A
0256  4034          JMS CALL
0257  0600          PRTNUM
0260  5201          JMP IDLE

0261  0000  A,      0
0262  0000  B,      0
0263  0000  OP,     0

----------------

            *400
            /READ A BUFFER UP TO A CR
0400  0000  RDBUF,  0
0401  7200          CLA
0402  1600          TAD I RDBUF
0403  2200          ISZ RDBUF
0404  3215          DCA BUFPTR
0405  4216  RDNXT,  JMS RDCHAR
0406  3615          DCA I BUFPTR
0407  1615          TAD I BUFPTR
0410  1020          TAD MCR
0411  7450          SNA
0412  5600          JMP I RDBUF
0413  2215          ISZ BUFPTR
0414  5205          JMP RDNXT
0415  0000  BUFPTR, 0

            /READ ONE CHAR
0416  0000  RDCHAR, 0
0417  7200          CLA
0420  6031          KSF
0421  5220          JMP .-1
0422  6036          KRB
0423  4225          JMS PRTCHAR
0424  5616          JMP     I RDCHAR

            /PRINT ONE CHAR
0425  0000  PRTCHAR,0
0426  6041          TSF
0427  5226          JMP .-1
0430  6046          TLS
0431  3245          DCA CH
0432  1245          TAD CH
0433  1020          TAD MCR
0434  7440          SZA
0435  5242          JMP RETCHR
0436  1021          TAD KLF
0437  6041          TSF
0440  5237          JMP .-1
0441  6046          TLS
0442  7200  RETCHR, CLA
0443  1245          TAD CH
0444  5625          JMP I PRTCHAR
0445  0000  CH,     0


            /PRT A BUFFER
0446  0000  PRTBUF, 0
0447  7200          CLA
0450  1646          TAD I PRTBUF
0451  2246          ISZ PRTBUF
0452  3215          DCA BUFPTR
0453  1615  PRTNXT, TAD I BUFPTR
0454  4225          JMS PRTCHAR
0455  2215          ISZ BUFPTR
0456  1020          TAD MCR
0457  7640          SZA CLA
0460  5253          JMP PRTNXT
0461  5646          JMP I PRTBUF

----------------

            /SKIP SPACES AC= FIRST NON-SPACE
0462  0000  SKPSPC, 0
0463  7200          CLA
0464  1662          TAD I SKPSPC
0465  2262          ISZ SKPSPC
0466  3215          DCA BUFPTR

0467  1615  NXTCHR, TAD I BUFPTR
0470  2215          ISZ BUFPTR
0471  1022          TAD MSPC
0472  7650          SNA CLA
0473  5267          JMP NXTCHR
0474  7240          CLA CMA
0475  1215          TAD BUFPTR
0476  5662          JMP I SKPSPC

            /GET DECIMAL NUMBER
0477  0000  GETNUM, 0
0500  7200          CLA
0501  3335          DCA NUMBER
0502  1677          TAD I GETNUM
0503  3215          DCA BUFPTR

0504  1615  NXTDIG, TAD I BUFPTR
0505  1023          TAD MZERO
0506  3334          DCA DIGIT
0507  1334          TAD DIGIT
0510  7710          SPA CLA
0511  5327          JMP NONUM
0512  1024          TAD M10
0513  1334          TAD DIGIT
0514  7700          SMA CLA
0515  5327          JMP NONUM
0516  1335          TAD NUMBER
0517  7100          CLL
0520  7006          RTL
0521  1335          TAD NUMBER
0522  7004          RAL
0523  1334          TAD DIGIT
0524  3335          DCA NUMBER
0525  2215          ISZ BUFPTR
0526  5304          JMP NXTDIG
0527  1215  NONUM,  TAD BUFPTR
0530  3677          DCA I GETNUM
0531  2277          ISZ GETNUM
0532  1335          TAD NUMBER
0533  5677          JMP I GETNUM
0534  0000  DIGIT,  0
0535  0000  NUMBER, 0

----------------

            /DIVIDE AC BY ARG
            /Q IN AC, R IN REM
0536  0000  DIV,    0
0537  3033          DCA REM
0540  1736          TAD I DIV
0541  2336          ISZ DIV
0542  7041          CIA
0543  3361          DCA MDVSOR
0544  3362          DCA QUOTNT
0545  1033          TAD REM
0546  1361  DIVLUP, TAD MDVSOR
0547  7510          SPA
0550  5353          JMP DIVDUN
0551  2362          ISZ QUOTNT
0552  5346          JMP DIVLUP
0553  7041  DIVDUN, CIA
0554  1361          TAD MDVSOR
0555  7041          CIA
0556  3033          DCA REM
0557  1362          TAD QUOTNT
0560  5736          JMP I DIV
0561  0000  MDVSOR, 0
0562  0000  QUOTNT, 0

----------------

                    *600
                    /PRINT NUMBER IN DECIMAL
                    DECIMAL
0600  0000  PRTNUM, 0
0601  4034          JMS CALL
0602  0536          DIV
0603  1750          1000
0604  4225          JMS PRTDIG
0605  7200          CLA
0606  1033          TAD REM
0607  4034          JMS CALL
0610  0536          DIV
0611  0144          100
0612  4225          JMS PRTDIG
0613  7200          CLA
0614  1033          TAD REM
0615  4034          JMS CALL
0616  0536          DIV
0617  0012          10
0620  4225          JMS PRTDIG
0621  7200          CLA
0622  1033          TAD REM
0623  4225          JMS PRTDIG
0624  5600          JMP I PRTNUM

            /PRINT A DIGIT IN AC
                    OCTAL
0625  0000  PRTDIG, 0
0626  1032          TAD KZERO
0627  4034          JMS CALL
0630  0425          PRTCHAR
0631  5625          JMP I PRTDIG

----------------

            *2000
2000  0000  BUF,0


Powyższy tekst jest luźnym tłumaczeniem wpisu bloga Roberta Cecila "Wujka Boba" Martina z dnia 21 lutego 2015 ze strony:


Proszę o komentarze, jeżeli ta luźność jest zbyt daleko posunięta.

Brak komentarzy:

Prześlij komentarz

Podstawy Programowania Funkcyjnego Epizod 3

Czy wszystkie Zasady Się Zmieniają? Kiedy tylko zaczynamy używać nowego paradygmatu , porównujemy z nim na...