Jeżeli śledzisz moje konta na twitterze, facebooku czy
githubie, mogłeś zauważyć, iż 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, o ile 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ę, iż każdy świeżo upieczony programista powinien spędzić tydzień lub dwa programując na jednej z tych starych maszyn. Wydaje mi się, iż 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żeli 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, iż 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ć, iż 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ć. interesujące 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 przez cały czas 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.
<uśmiech> Powinieneś był zobaczyć, jak te światełka mrugały!
Prędkość uruchomieniowa to około 4000 instrukcji na sekundę. Mimo iż 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ą. choćby FOCAL działa wystarczająco gwałtownie 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
<chlip>). 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 (<och>). 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ł przez cały czas 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 choćby jeżeli nie pisałem testów, czułem się tak, jakbym pisał -
czułem się, jak podczas TDD.
Oczywiście to prawda, iż 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żeli 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, iż 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, iż 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.
- 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żeli listing jest długi.
- Załaduj edytor z taśmy papierowej. To zajmie kilka minut, więc zrób sobie kawę.
- 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)
- Włóż papierową taśmę z twoim kodem źródłowym do czytnika
- Wczytaj jedną "stronę" kodu z papierowej taśmy używając komendy R. (50 linii lub mniej. 1 minuta lub więcej).
- Idź do tej strony w twoim listingu i nanieś poprawki, używając komend I, C i D. Pamiętaj, iż nie masz ekranu, więc edytujesz linia po linii, używając numerów linii. Zaplanuj spędzić nad tym trochę czasu.
- Wydrukuj aktualną stronę, używając komendy L. Upewnij się, iż wszystkie zmiany są poprawne.
- Wydziurkuj aktualną stronę na papierowej taśmie, używając komendy P. (minuta lub więcej).
- Wydziurkuj aktualną stronę i następnie ją wczytaj, używając komendy N i o ile to nie była ostatnia strona, idź do punktu 6.
- 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!
- Załaduj assembler do pamięci z papierowej taśmy (10 minut lub więcej).
- Ustaw przełącznik na panelu przednim na 2002: to konfiguracja "przejście pierwsze, wyjście na drukarkę".
- Załaduj źródłową taśmę do czytnika.
- Załaduj 0200 do rejestru PC, i wciśnij RUN.
- Kompilacja przejście pierwsze wczyta całą taśmę z kodem źródłowym i wydrukuje tablicę symboli. (10 minut albo więcej).
- Gdy komputer się zatrzyma, ustaw na panelu przednim przełączniki na 4003: konfiguracja "przejście drugie, wyjście na dziurkacz".
- Załaduj twój kod źródłowy do czytnika.
- 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.
- Gdy komputer się zatrzyma, jeżeli były jakieś błędy, wyrzuć papierową taśmę, która była przed chwilą dziurkowana i przejdź do punktu 1. jeżeli 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?)
- Ustaw przełączniki na panelu przednim na 6002: to konfiguracja "przejście trzecie, wyjście na drukarkę".
- Włóż twoją źródłową taśmę do czytnika.
- 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ę, iż masz wystarczająco dużo papieru w drukarce!
- Oderwij listing i go sprawdź.
- Włóż swoją taśmę binarną do czytnika.
- Ustaw rejestry PC na 7777 (adres ładowarki binarnej, która zwykle jest przechowywana w pamięci rdzenia) i naciśnij RUN. o ile 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.
- 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ę, iż 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ąć manualnego 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żeli 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ę, iż kod jest dobry; iż wyedytowałeś go odpowiednio; iż przełączniki są ustawione adekwatnie; iż 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, iż ich buildy stają się kruche i podatne na błędy. Tworzą tak wiele niewyizolowanych zewnętrznych zależności, iż 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 systemu 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, o ile ta luźność jest zbyt daleko posunięta.