atarionline.pl ABC czyli Atari Basic Compiler - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1: CommentAuthormono
    • CommentTime4 Dec 2012 zmieniony
     
    BASIC inicuje. Przecież jak odpalasz xexa to nie masz BASICa ani włączonego, nie mówiąc o przekazaniu mu sterowania :)
    Nie planujesz wiernego odzwierciedlenia działania BASICa? Będą na Ciebie kląć, że "nie działa" :P

    Edit: No tabulacja nie działa u Ciebie jak w BASICu, bo w LMARGIN ($52) jest jeszcze lewy margines. Sama bieżąca pozycja kursora COLCRS i odliczanie do wielokrotności nie wystarczy - trzeba by odjąć ten margines...
  1.  
    Hehe, w sumie rzeczywiście - istnieje zagrożenie wywołaniem "przecinekgate" jak ta niekompatybilność wyjdzie na jaw :)

    Zapiszę na wszelki wypadek na samym... dole listy TODO :)
    • 3:
       
      CommentAuthormgr_inz_rafal
    • CommentTime12 Dec 2012 zmieniony
     
    Getting back to work :) Dzisiaj trochę agrarnie...

    Chciałbym przedstawić Wam zmienne tekstowe. Na razie jeszcze nie mam obsługi kilku zmiennych w jednym DIM po przecinku, stąd też te cztery początkowe linijki. Nie dodałem też na razie możliwości edytowania stringów. Zanim takowa się pojawi minie trochę czasu, gdyż - przy okazji implementowania zmiennych tekstowych - wpadłem na fajny pomysł jak można zoptymalizować tablice i goto pod obliczany adres :) Teraz więc siadam do pracy nad przeróbką tego co już działa (tablice, goto), żeby działało lepiej.

    A póki co przykładowy kod i standardowo już zrzut ekranu.
    10 DIM ZUPA$(10)
    20 COM POMIDOROWA$(20)
    30 DIM ORAZ$(30)
    40 COM MAKARON$(10)
    100 POMIDOROWA$ = "SIE NA MORZE!"
    110 ZUPA$ = "POLE ORZE "
    120 MAKARON$ = "TO NIE PATRZY "
    130 ORAZ$ = "KIEDY ROLNIK "
    200 FOR I = 1 TO 7 STEP 2
    210 PRINT ORAZ$;ZUPA$;MAKARON$;POMIDOROWA$
    220 NEXT I
    230 PRINT 666


    Wynik:
    • 4:
       
      CommentAuthormgr_inz_rafal
    • CommentTime18 Dec 2012 zmieniony
     
    Siedzę sobie zatem nad tym GOTO i przepisuję po raz kolejny. Doszedłem do - jak mi się przed chwilą wydawało - ostatecznego rozwiązania, ale... No właśnie, zawsze niby coś tam da się zoptymalizować. I tutaj chciałbym zasięgnąć Waszej opinii.

    Generalnie, aby "GOTO do dowolnego wyrażenia" działało, musimy przeszukać kod, tak jak robi to BASIC. Dodaję zatem do każdej linijki na początku mały, czterobajtowy header w postaci:
    2 bajty = numer linijki
    2 bajty = adres headera następnej linijki
    Implementacja GOTO porównuje sobie pierwsze dwa bajty z docelowym numerem linijki i jeśli pasują to skacze, a jeśli nie, to bierze header następnej linijki i znowu porównuje.

    Mamy zatem taką linked-listę numerów linijek. Alternatywnie można to zinterpretować jako jump-lookup-table, ale rozproszone w różnych miejscach pamięci.

    Wszystko śmiga. Jednak biorąc po uwagę fakt, że numery linijek są ładnie posortowane, aż się prosi aby zastosować binary-search. Ale header musiałby urosnąć do 6 bajtów:
    2 bajty = numer linijki
    2 bajty = adres headera linijki jeśli mniejsze
    2 bajty = adres headera linijki jeśli większe
    Do tego oprócz zwykłego porównania musiałbym sprawdzić, czy bieżąca linijka jest mniejsza czy większa od docelowej, zatem pewnie jakieś SBC + BMI + przyległości musiałby się pojawić w procedurze skaczącej.

    No i teraz chciałbym zapytać, czy wg Was pokusić się o implementację wyszukiwania binarnego (oprócz zabawy jest to jednak roboty kupa, a zysk wydaje się niewielki, no bo ile taki średni program BASICowy ma linijek?). Wiem, że można to sobie statystycznie policzyć, ale wierzę, że intuicja bardziej doświadczonych koderów sprawdzi się lepiej niż arkusz kalkulacyjny :)

    Może dlatego, że jestem przeziębiony, to mi takie chore pomysły przychodzą do głowy :)
    • 5:
       
      CommentAuthorjhusak
    • CommentTime19 Dec 2012 zmieniony
     
    Zrób wykrywanie takich sytuacji.
    - jak jest podany tylko goto const to stosujesz zwykły kod skoku.
    - jak jest podany choć raz goto zmienna to wtedy warning! i dodawanie tych informacji.

    Lista dwukierunkowa na nic ci się nie zda przy binary search, bo jak skoczysz w środek listy?
    Prędzej tablica wszystkich linijek ( a tych może być 32767) wraz z adresami(2 bajty) - całą pamięć można zapełnić samymi adresami linijek...

    Ale jak mało linijek - to będzie git, i binary search zadziała, i oszczędniej.
    Ostatni element oznaczasz jako linijkę nr $8000 i jesteś w domu.

    Oczywiście to drugie rozwiązanie, jak już będzie wszystko napisane (cała reszta).
    • 6: CommentAuthormono
    • CommentTime19 Dec 2012 zmieniony
     
    Uwaga na trick z edytorem E:! W niektórych programach w basicu (np. Graph3D) używane jest automatyczne wprowadzanie linii. Jeśli do rejestru ICAUX1 otwartego edytora zapisze się kod 13 (R/W append oidp), wtedy podczas operacji wprowadzania danych z edytora (INPUT, GET lub oddanie sterowania do BASICa po STOP lub END) automatycznie "wciskany" jest RETURN i wprowadzana jest linia, która znajduje się na pozycji kursora na ekranie. Stosowane jest to np. w rzeczonym programie do wpisywania nowej funkcji do wyrysowania. Czynność jest powtarzana w nieskończoność, albo do chwili wpisania do ICAUX1 wartości 12 (R/W). Zazwyczaj program maluje na ekranie zawartość nowej linii BASICa, a po niej w następnej linii rozkaz CONT. Następnie cofa się na początek linii, która ma być wprowadzona i robi STOP. Sterowanie oddane zostaje do edytora, wprowadzane są linie, po czym sterowanie wraca do programu po wykonaniu CONT w trybie bezpośrednim. W ten sposób zarówno ilość linii programu, jak i ilość/zawartość zmiennych może się zmienić. Tak to mniej więcej wygląda:
    10 POS.2,2:?"30 X=3.14":? "CONT":POS.2,0:POKE 842,13:STOP
    20 POKE 842,12
    40 ? X

    Jest to chamski hak, ale czasami (i przez niektórych wręcz z lubością) używany.
    Ale to taka dygresja.

    Wracając do tematu - poza w/w przypadkiem ilość linii będzie raczej stała więc i tablica może być stała. Minimalna linia
    10 ?

    zajmuje 6 bajtów, więc 37902/6=6317 linii :) Ale jeszcze przecież jest obszar zmiennych (max 128*8B), bufor tokenizacji (256B), tablice (n*6B dla numerycznych, nB dla tekstowych) i stos BASICa, więc i linii będzie mniej.

    W programie zapisanym przez SAVE/CSAVE jest też zapisywana ostatnia linia wprowadzona w trybie bezpośrednim (o nrze 32768) - zazwyczaj właśnie "SAVE" lub "CSAVE", którą można zignorować.

    Co zrobisz kiedy wyliczonej linii w programie nie będzie? BASIC raportuje ERROR- 12 AT LINE x.

    Edit: ICAUX1=842 - to ICAUX1 dla #0. Tam domyślnie OS otwiera edytor ekranowy E: Z BASICa nie można go zamknąć, bo BASIC może działać tylko na kanałach 1..7.
    • 7:
       
      CommentAuthormgr_inz_rafal
    • CommentTime19 Dec 2012 zmieniony
     
    @jhusak
    Wolę nie wykrywać takich sytuacji, lecz pozostawić wybór użytkownikowi, jeśli tacy będą. Tak jak kiedyś pisałem będzie w kompilatorze opcja "skacz tylko pod stałe" i wtedy w przypadku "goto nie-stała" będzie błąd. Zaoszczędzi mi to też roboty oraz jednego przebiegu kompilacji :)

    Lista jak najbardziej się przyda do binary-search. Kwestia dobrego poukładania wskaźników na niej przechowywanych - a to da się zrobić, bo ilość linijek jest znana. Przynajmniej jeśli udamy, że nie czytaliśmy ostatenigo postu mono ;)

    Ale jednak poranny, świeży umysł podpowiada mi, że nie warto aż tak walczyć o złożoność logarytmiczną. Miałoby to może sens, gdyby rzeczywiście w realnych programach ilość linijek sięgała 32767 albo np. 1000000 :) A realnie to pewnie ich liczba kręci się w okół paru stówek. Np. w Biednym Psie jest ich 381, a pamięć już jest wypchana. Tu złożoność liniowa pewnie doskonale się sprawdzi.

    @mono
    Pamiętam z dzieciństwa taki program właśnie do rysowania wykresów funkcji, przepisany chyba z jakiegoś Bajtka, TA lub książki do Basic. Sam chyba raz z czegoś podobnego skorzystałem, aby dynamicznie usuwać z programu linijki - nie pamiętam tylko po co :) Nie da się jednak ogarnąć takich bajerów w kompilatorze, więc stosowacze chamskiego haka muszą pozostać przy języku interpretowanym :)

    Co zrobisz kiedy wyliczonej linii w programie nie będzie? BASIC raportuje ERROR- 12 AT LINE x.

    Będzie bum :) Nie robię żadnych sanity-check, ani w goto, ani np. przy zapisie do tablic. Jak w C :) Po części z lenistwa (70%) a po części z tego, że szkoda mi każdego bajta "zmarnowanego" na kontrolę (30%) :) Zakładam, że kompilowane będą programy, które już są wystarczająco dobrze przetestowane w samym BASIC.
    • 8: CommentAuthorrudla
    • CommentTime19 Dec 2012
     
    You should use separate table at the end of application code, 4 bytes per line:

    jump_table:

    DW LINE_NO, LINE_ADR

    Then search is easy, binary search is easy, memory requirement is minimal.

    You may compress the table so, that all lines with same high byte of number are grouped:

    DB >LINE1_NO, COUNT
    <LINE1_NO, LINE1_ADR
    <LINE2_NO, LINE2_ADR
    • 9:
       
      CommentAuthormgr_inz_rafal
    • CommentTime22 Dec 2012 zmieniony
     
    @rudla
    Your idea is probably the ultimate one. I will get back to it once I'm ready to rewrite goto implementation again :)

    Back to polish... W międzyczasie zakończyłem wsparcie dla poszatkowanych stringów (na razie tylko jako r-value). Można sobie już wypisywać kawałki ciągów znakowych:
    10 DIM A$(5)
    30 A$="ZENEK"
    50 PRINT A$(2,4)
    60 PRINT A$(2)
    70 PRINT A$
    77 PRINT A$(1,1)
    78 PRINT A$(5,5)
    79 PRINT A$(1,NOT 0);A$(1 + 1,2);A$(3,(1 + 1) * 5 - 7);A$(2 * 2, 5 - 1);A$(5)


    I wynik:
    • 10:
       
      CommentAuthormgr_inz_rafal
    • CommentTime1 Jan 2013 zmieniony
     
    Hmmm... A co wy śpicie? Nikt nie zauważył błędu? :)

    Właśnie przepisałem od nowa obsługę stringów i wyszło, że wynik działania kompilatora przedstawiony w poście nr 3 na tej stronie zawierał błąd :) Poprawnie powinno to wyglądać tak jak poniżej, gdyż pojemność MAKARON$ to tylko 10 znaków...


    I żeby nie było, ten sam programik uruchomiony w BASIC:
    • 11: CommentAuthorrudla
    • CommentTime2 Jan 2013
     
    Btw. if you think some unit tests would help you, you may try to use con6502 utility that is part of Atalan.
    You would have to implement some kind of ASSERT command, but that should be quite easy.
    • 12:
       
      CommentAuthormgr_inz_rafal
    • CommentTime12 Jan 2013 zmieniony
     
    Ostatnie dni upłynęły mi w miłej atmosferze przepisywania w kółko od nowa obsługi stringów :)

    No i w końcu mam coś działającego dobrze, ale nadal nie jestem zadowolony, bo kod kopiujący stringi ma aż 220 bajtów... To 25% mojego dotychczasowego runtime... :( Mam mocne wrażenie, że algorytm powinien być zdecydowanie prostszy :)

    Czas pokaże, czy będę to znowu przepisywał od nowa czy zostawię tak jak jest :) A tymczasem mały przykład zmiennych tekstowych jako lvalue:
    10 DIM A$(20)
    20 A$(3,3)="KOPERNIK"
    30 PRINT A$
    40 A$="ROLNIK SAM W DOLINIE"
    50 PRINT A$
    60 A$(1,6)="BISKUP"
    70 PRINT A$
    80 A$(12)="NA SAM"
    90 PRINT A$
    100 A$(17)="N"
    110 PRINT A$;"KACH"
    120 A$="BERET"
    130 PRINT A$


    Wynik:


    @rudla
    How much time did you spend on the ATALAN language so far? I presume quite a lot!

    The idea behind it is outstanding, so I start to regret that I began to get acquainted with ATALAN only after your last post in this thread.
    • 13: CommentAuthorrudla
    • CommentTime14 Jan 2013 zmieniony
     
    @mgr_inz_rafal

    Yes, I have spent a lot of time on Atalan. Probably too much, but I enjoy it. It's still not usable for production, but I like the experiments I'm performing on Atalan :-)
    • 14:
       
      CommentAuthormgr_inz_rafal
    • CommentTime18 Jan 2013 zmieniony
     
    Wydaje mi się, że zamknąłem temat kopiowania stringów :) Poniżej taki oto program testowy, sprawdzający różne kombinacje przypisań. Mamy zatem po lewej jak i po prawej stronie znaku równości konstrukcje A$, A$(x) oraz A$(x,y). Do tego dwa warianty: przypisywanie tekstu krótszego niż "pojemność" strony lewej oraz dłuższego, co wymaga przycięcia :)

    Kod testowy wygląda tak:
    0 REM STRING COPY REGRESSION TEST
    10 DIM A$(5),B$(3),C$(20)

    30 A$="X": REM SHORTER
    40 PRINT "X =",A$
    50 A$="123456": REM LONGER
    60 PRINT "12345 =",A$

    110 A$(3)="W": REM SHORTER
    120 PRINT "12W =",A$
    130 A$(3)="QWERTYUIOP": REM LONER
    140 PRINT "12QWE =",A$

    210 A$(1,3) = "R": REM SHORTER
    220 PRINT "R2QWE =",A$
    230 A$(1,2) = "ASDFGHJKL": REM LONGER
    240 PRINT "ASQWE =",A$

    310 B$="!@#":C$="EXTREMELYlongSTRING"
    320 A$=B$(2): REM SHORTER
    330 PRINT "@# =",A$
    340 A$=C$(5): REM LONGER
    350 PRINT "EMELY =",A$

    410 A$(1)=B$(2): REM SHORTER
    420 PRINT "@# =",A$
    430 A$(4)=C$(4): REM LONER
    440 PRINT "@#ERE =",A$

    510 A$(2,4) = C$(10): REM SHORTER
    520 PRINT "@lonE=",A$
    530 A$(2,4) = C$(8)
    540 PRINT "@LYlE =",A$

    610 A$=C$(4,6): REM SHORTER
    620 PRINT "REM =",A$
    630 A$=C$(1, 10): REM LONGER
    640 PRINT "EXTRE =",A$

    710 A$(1) = C$(9, 9): REM SHORTER
    720 PRINT "Y =",A$
    730 A$(3) = C$(7, 15): REM LONGER
    740 PRINT "YXELY =", A$

    810 A$(1, 3) = B$(1, 1): REM SHORTER
    820 PRINT "!XELY =",A$
    830 A$(2, 4) = C$(1, 12): REM LONGER
    840 PRINT "!EXTY =",A$


    A wynik:


    Dołączam też obrazek z Atari Basica. Z grubsza jest to samo, ale niestety ten cholerny przecinek mi się źle drukuje :( Czy ktoś byłby tak dobry i przedstawił (pseudo)kod obliczający ile spacji narysować na ekranie po napotkaniu przecinka w PRINT?
    • 15:
       
      CommentAuthormgr_inz_rafal
    • CommentTime18 Jan 2013 zmieniony
     
    I jeszcze mała ciekawostka :) Ponieważ idziemy z duchem czasu, nie będę wprowadzał sztucznych ograniczeń na długość linii :)
    10 DIM ZENEK$(1000)
    20 ZENEK$="Dnia 12 grudnia 2012 roku o godzinie 13:00 odbylo sie otwarcie czasowej i dlugoterminowej ekspozycji Muzeum Historii Komputerow i Informatyki. Mozna tam zobaczyc komputer ODRA z jednostka centralna 1305 oraz kilka mniej znanych komputerow. Na niektorych mozna nawet pograc. Muzeum miesci pomieszczeniach udostepnionych przez Wyzsza Szkole Mechatroniki w Katowicach-Szopienicach. Zapraszam wszystkie osoby zainteresowane, szczegolnie te mieszkajace blisko, do zwiedzenia muzeum. Przybywajcie na adres: ul. 11 listopada 13 Katowice-Szopienice. Jednak trzeba potwierdzic zwiedzanie. Normalnie jest one czynne tylko w godzinach: piatek : od 16 do 19"
    30 PRINT ZENEK$


    Wynik:


    PS. Linijkę w kodzie zawija forum.

    PS2. To jeszcze dla ciekawskich widok na surowego .xexa :) Na początku kod, potem dane, a na końcu przydługi runtime kompilatora ;)



    Udanego weekendu!
    • 16:
       
      CommentAuthorMaW
    • CommentTime18 Jan 2013
     
    Wydaje mi się, że w przecinku jedyne, czego Ci brakuje, to informacji, o ile punkt przystankowy jest przesunięty w stosunku do lewego marginesu, o czym już pisał Mono w #101.

    A co do kodu xexa - na końcu zaplanuj jakiś prosty kompresor bo aż się prosi, żeby przynajmniej na stringach zaoszczędzić bajtów :-)

    PS. To już weekend ? A dopiero co poniedziałek był :D
    • 17: CommentAuthormono
    • CommentTime20 Jan 2013 zmieniony
     
    @mgr_inz_rafal: a może być w pytongu?
    basic_print to przepisana zwartość funkcji print basica.

    Wywołanie
    basic_print("","abc","","1234567890","!@#$")

    naśladuje funkcję
    PRINT ,"ABC",,"1234567890","!@#$"

    drukuje teksty rozdzielane przecinkami (do pythonowej funkcji lista stringów przekazywana jest w kolekcji items więc przecinek "obsługiwany jest" po wydrukowaniu elementu z kolekcji).
    Każdy znak jest drukowany osobno celem zwiększenia licznika cox i aktualizacji auxbr, tak jak to się dzieje w basicu.
    range(a,b) to odpowiednik for i=a to b-1.

    Edit: Przy renderowaniu przecinka BASIC nie uwzględnia LMARGIN więc nie trzeba się nim przejmować przy obliczeniach. LMARGIN i RMARGIN jest uwzględniany oczywiście przez samą procedurę PUTBT urządzenia E:
    • 18:
       
      CommentAuthormgr_inz_rafal
    • CommentTime21 Jan 2013 zmieniony
     
    Czas na pierwszy test kompilatora w warunkach bojowych :)

    Wziąłem na warsztat Biednego Psa Antoniego i wyciąłem z niego mechanizm, który pozwala mi stosować deklinację w wypisywaniu kroków, na które psu starczy paliwa (1 krok, 2 krokI, 5 krokÓW, itp.).

    "krok" wypisywane jest zawsze, a do końcówek powstaje look-up table o rozmiarze 302 bajtów, zawierająca 151 dwuliterowych członów: "<space><space>" lub "ów" lub "i<space>". Żeby to wszystko wygenerować powstało trochę dziwnego kodu:
    6 Q0=0:Q1=1:FI=Q1:MQ1=-1:MQ2=-2:Q2=Q1 + Q1:Q23=23:Q7=Q2 + Q2 + Q2 + Q1:Q22=Q23-Q1:Q30=Q23 + Q7:Q3310=3310
    75 DIM STPC$(302),ST$(Q2)
    76 STPC$(3,4)=" ":ST$(Q1)="o":ST$(Q2)="w"
    77 FOR J=Q0 TO 13:FOR I=Q0 TO Q2:STPC$((20*J) + 5 + I*Q2,(20*J) + I*Q2 + 6)="i ":NEXT I
    78 FOR I=Q0 TO 6:STPC$((20*J) + 11 + I*Q2,(20*J) + I*Q2 + 12)=ST$:NEXT I:NEXT J
    79 FOR I=285 TO 290 STEP Q2:STPC$(I,I + Q1)="i ":NEXT I:FOR I=291 TO 302 STEP Q2:STPC$(I,I + Q1)=ST$:NEXT I
    80 FOR J=Q0 TO Q1:FOR I=25 TO Q30 STEP Q2:STPC$(200*J + I,200*J + I + Q1)=ST$:NEXT I:NEXT J

    Gotowe look-up table siedzi w zmiennej STPC$.

    Jak widać, oszczędzałem tutaj pamięć stosując zmienne zamiast stałych. Do tego kod jest na tyle zakręcony, że poddaje ciężkiej próbie działanie zmiennych, arytmetyki oraz stringów i pętli. Ważne jest też to, że STPC$ ma długość większą niż 256, bo jak się okazało mój kompilator dobrze manewrował stringami jeśli ich długość nie przekraczała 256 :)

    Następnie dołączyłem inny, lekko zmodyfikowany kawałek Psa, który odpowiada za obliczanie odpowiedniego offsetu w look-up table i wypisywanie kroków na ekran
    95 MAXSTEP=151
    99 FOR CURSTEP=117 TO 148 STEP Q2
    100 STEPTOPR=MAXSTEP-CURSTEP-Q1:STEPTOPR1=MAXSTEP-(CURSTEP + 1)-Q1
    120 PRINT STEPTOPR;" krok";STPC$(STEPTOPR*Q2 + Q1,STEPTOPR*Q2 + Q2),STEPTOPR1;" krok";STPC$(STEPTOPR1*Q2 + Q1,STEPTOPR1*Q2 + Q2)
    130 NEXT CURSTEP:CURSTEP=149:STEPTOPR=MAXSTEP-CURSTEP-Q1
    200 PRINT STEPTOPR;" krok";STPC$(STEPTOPR*Q2 + Q1,STEPTOPR*Q2 + Q2)

    Działa :)

    Oto wynik:


    mono:

    a może być w pytongu?
    Jasne, że może. Dziękuję bardzo! Teraz właśnie zajmę się tym feralnym przecinkiem ;)
  2.  
    Przecinek by mono działa! :)
    Dzięki!
  3.  
    A jak najprościej sprawdzić, czy FR0 jest równe FR1?

    Mam naiwną prockę, która porównuje 6 kolejnych bajtów, ale jak się okazuje, zero może być reprezentowane przez: "00 00 00 00 00 00" jak i "40 00 00 00 00 00".

    I czasem nie działa mi IF :)

    Na razie kusi mnie zrobienie FSUB, potem FPI i sprawdzenie, czy w FR0 jest "00 00", ale to jednak sporo cykli w du*.*pę :) Poza tym, dla małych różnic między FP i tak mogłoby przekłamać.

    Czy jest szybszy sposób?

    Przy okazji - podobną słabość mają moje procki OR oraz AND na FR0/1. Jest do tego w MADS jakiś gotowiec?
    • 21:
       
      CommentAuthorjhusak
    • CommentTime26 Jan 2013 zmieniony
     
    A może - test czy 0
    test0:
    lda FR0+1
    clc
    adc FR0+2
    adc FR0+3
    adc FR0+4
    adc FR0+5
    bcs noeq
    bne noeq
    lda FR0
    and #BF
    bne noeq
    ; tutaj kod jeśli zero


    Ale nie wiem, czy załapałem o co biega.
  4.  
    A test czy FR0=FR1?
    • 23: CommentAuthorxxl
    • CommentTime27 Jan 2013
     
    a moze ten fragment:

    lda FR0+1
    clc
    adc FR0+2
    adc FR0+3
    adc FR0+4
    adc FR0+5
    bcs noeq
    bne noeq

    zapisac tak:

    lda FR0+1
    ora FR0+2
    ora FR0+3
    ora FR0+4
    ora FR0+5
    bne noeq
    • 24: CommentAuthorBartoszP
    • CommentTime27 Jan 2013
     
    Ale to jest sprawdzenie czy FR0 = 0 ? Chodzi chyba o sprawdzenie czy FR0 = FR1 i to dla dwóch wersji a to mozna zrobić tak:
    ; porownujemy kolejno 5 bajtow z FR0 i FR1 i tego
    ; nie unikniemy.
    lda FR0+5
    eor FR1+5
    bne nierowne
    lda FR0+4
    eor FR1+4
    bne nierowne
    ...
    ; tu zaczyna sie kluczowy moment
    lda FR0
    eor FR1
    ; A = maska bitow roznych w FR0 i FR1
    ; jesli A = 0 to FR0 = FR1 i mozna by skoczyc do rowne:
    beq rowne
    ; FR0 != FR1 ale musimy sprawdzic czy to nie dwie wersje
    ; zera wygenerowaly maske A != 0
    and #$BF
    beq rowne
    ; FR0 != FR1 bo roznice byly na bitach innych niz 6 czyli

    nierowne:
    ...

    rowne:
    ...

  5.  
    Dzięki BartoszP,
    Czyli rzeczywiście chodzi tylko o ten feralny, pierwszy bajt. Dzisiaj sprawdzę jak to zadziała w praktyce.

    @jhusak, @xxl
    Wasz kod na "is 0" również pozwolę sobie wykorzystać, bo moja procka wykonująca to samo jest znacznie dłuższa :)
    • 26: CommentAuthorxxl
    • CommentTime27 Jan 2013 zmieniony
     
    jesli o dlugosc kodu chodzi to krocej bedzie tak:

    ldy #4
    @ lda FR0+1,y
    bne noeq
    dey
    bpl @-
    lda FR0
    and #%10111111
    bne noeq

    17b
  6.  
    xxl, dzięki :)

    A mógłbyś zasadę działania trochę rozjaśnić?
    • 28: CommentAuthorxxl
    • CommentTime27 Jan 2013
     
    to jest to samo co pokazal jhusak tylko zapisane inaczej - wolniejsza ale krotsza o 10b wersja.
    • 29: CommentAuthorBartoszP
    • CommentTime27 Jan 2013
     
    I do tego "psuje" rejestr Y. Aby go zachować trzeba by zrobić TYA, PHA a potem PLA, TAY czyli 4 bajty czyli zysk maleje do 3 bajtów
    • 30: CommentAuthorxxl
    • CommentTime27 Jan 2013
     
    10 - 4 = 3 ? "psucie" reg.Y jest mocno dyskusyjne ;)
    • 31: CommentAuthorBartoszP
    • CommentTime27 Jan 2013
     
    Oczywiście, że 3 bo to liczby o podstawie 7 były :-)

    Ale tak czy inaczej obstaję, że Y się "raczej popsuje".
    • 32:
       
      CommentAuthormgr_inz_rafal
    • CommentTime28 Jan 2013 zmieniony
     
    Okej, podane przez Was procki działają zgodnie z oczekiwaniami. Jeszcze raz dzięki - odpowiednie creditsy pojawiają się już w wygenerowanym kodzie :)

    Czy mógłbym w takim razie prosić o napisanie procek realizujących logiczne OR i AND pomiędzy FR0 i FR1 oraz logiczne NOT na FR0?

    Już widzę, że moja obecna implementacja będzie nieodporna na ten nieszczęsny pierwszy bajt FP :)

    PS. Akurat w tym przypadku nie zależy mi na zachowaniu wartości Y, więc - w imię minimalizacji runtime kompilatora - wybrałem rozwiązanie zaproponowane przez XXLa.
    • 33: CommentAuthorBartoszP
    • CommentTime28 Jan 2013 zmieniony
     
    To mój kod na porównanie też można skrócić gdy Y nie jest ważny i dodatkowo można usunąć jeden skok (tak przy okazji mnie "naszło"):
    test:
    ldy #4
    @ lda FR0+1,y
    eor FR1+1,y
    bne nierowne
    dey
    bpl @-
    lda FR0
    eor FR1
    ; beq rowne ; to jest zbędne
    and #$BF
    beq rowne
    nierowne:
    ...
    rowne:
    ...


    A co ma robić OR z liczbami zmiennoprzecinkowymi FR1 i FR0. Oraz jaki jest sens NOT na FR0 ?
  7.  
    Dobre pytanie :) Chodziłoby o to, aby dobrze kompilować np. taki kod:
    PRINT 4.5 AND 5.6
    PRINT 3.14 OR 0

    Ale przecież jak już mam dobrą prockę na "is 0?" to będzie to banalnie proste :)

    Sorki więc, nie było pytania.
    • 35: CommentAuthorBartoszP
    • CommentTime28 Jan 2013
     
    Bo trzeba odróżnić operacje logiczne na reprezentacji bitowej obiektów od operacji logicznych na obiektach "jako takich". Czyli pojawia się pytanie jak i co reprezentować jako wartość TRUE i FALSE.
    • 36: CommentAuthormono
    • CommentTime28 Jan 2013 zmieniony
     
    0=FALSE, niezero=TRUE. Wynikiem operacji logicznych jest 0 albo 1.
    Nie jestem pewny czy basic realizuje short-circuit OR/AND...

    Edit: ...co miałoby znaczenie właściwie tylko przy operacjach logicznych na wyniku USR (bo w basicu inaczej nie da się zdefiniować własnej funkcji).
    • 37:
       
      CommentAuthormgr_inz_rafal
    • CommentTime31 Jan 2013 zmieniony
     
    Jeszcze tylko obsługa INPUT i będę próbował kompilować program "Sortowanie Alfabetyczne" z książki "Atari Basic" :) Myślę, że po tym milestonie upublicznię wersję bieżącą kompilatora na Forum, bo w sumie na razie wyświetlam Wam tylko obrazki, które to mogą być fejkiem przecież :)

    A dziś przedstawiam operatory porównania na stringach:
    2000 DIM A$(10), B$(10)
    2010 A$="JANEK"
    2020 B$="FELCIA"
    2025 BARSZCZ = 7

    2030 PRINT A$(2,3) < B$(4),
    2042 PRINT B$ < A$,
    2052 PRINT A$ < B$,
    2054 PRINT A$(2,2) < B$(6,6)

    3030 PRINT A$(2,3) > B$(4),
    3042 PRINT B$ > A$,
    3052 PRINT A$ > B$,
    3054 PRINT A$(2,2) > B$(6,6)

    4030 PRINT A$(2,3) = B$(4),
    4042 PRINT B$ = A$,
    4052 PRINT A$ = B$,
    4054 PRINT A$(2,2) = B$(6,6)

    5030 PRINT A$(2,3) <> B$(4),
    5042 PRINT B$ <> A$,
    5052 PRINT A$ <> B$,
    5054 PRINT A$(2,2) <> B$(6,6)

    6030 PRINT A$(2,3) >= B$(4),
    6042 PRINT B$ >= A$,
    6052 PRINT A$ >= B$,
    6054 PRINT A$(2,2) >= B$(6,6)

    7030 PRINT A$(2,3) <= B$(4),
    7042 PRINT B$ <= A$,
    7052 PRINT A$ <= B$,
    7054 PRINT A$(2,2) <= B$(6,6)

    8000 IF A$ = "JANEK" AND BARSZCZ < 6 THEN PRINT A$;" POSIADA ";BARSZCZ;" BARSZCZY":GOTO 8010
    8001 BARSZCZ = BARSZCZ - 2
    8002 GOTO 8000
    8010 PRINT 666

    Wynik:
    • 38: CommentAuthorxxl
    • CommentTime31 Jan 2013
     
    to znaczy czego brakuje? porownywales szybkosc dzialania po kompilacji z mmg bsic compilerem?
  8.  
    Czego brakuje? No dużo rzeczy jeszcze brakuje do końca :) A do skompilowania "Sortowania Alfabetycznego" to właściwie tylko INPUT, bo CHR$ to pikuś :)

    Nie robiłem jeszcze testów wydajności. Na razie tylko widzę "na oko", że wszystko dzieje się trochę szybciej niż z poziomu interpretera BASIC.
    • 40:
       
      CommentAuthormgr_inz_rafal
    • CommentTime31 Jan 2013 zmieniony
     
    Odnośnie tego INPUT-a - w sąsiednim wątku mono edukował mnie następująco:

    mono:

    Poprawny EGETCH to standardowy odczyt znaku z CIO - zakładając, że nie zamykasz edytora to po odpaleniu programu jest on otwarty w kanale 0:
    ldx #0
    lda #GETBT
    sta ICCMD
    stx ICBUFL
    stx ICBUFL+1
    jsr JCIOMAIN
    bmi error
    Właściwie to wszystko ładnie działa, ale chciałbym tylko dopytać o dwie kwestie:

    1. Jak wpisuję dużo znaków, to w okolicach końca trzeciego wiersza słychać bzyknięcie. BASIC też to ma. Czy ten złowieszczy dźwięk oznacza jakiś limit na ilość znaków?

    2. Znak zapytania, który pojawia się po INPUT w BASICu to już kwestia samego BASICa, tak? Nie jest on generowany przez CIO?
    • 41: CommentAuthormono
    • CommentTime31 Jan 2013
     
    1. To ograniczenie urządzenia E:. Limit jest oidp na 128 znaków.
    2. Tak. Nie jest.
    • 42: CommentAuthorbrx
    • CommentTime31 Jan 2013
     
    O tym, że można używać polecenia INPUT w ogóle bez wyświetlania pytajnika, dowiedziałem się dopiero gdzieś z 20 lat później :)
    • 43:
       
      CommentAuthorKaz
    • CommentTime1 Feb 2013
     
    Myślę, że po tym milestonie upublicznię wersję bieżącą kompilatora na Forum


    Przeczytalem caly watek i czekam z niecierpliwoscia na pierwsza wersje. Swietny projekt i oby doczekal takiej wersji, ktora da sie wykorzystac. Powodzenia Rafal.
    • 44: CommentAuthormono
    • CommentTime1 Feb 2013
     
    @brx: Fakt. Wystarczy zrobić:
    OPEN #1,12,0,"E:"
    INPUT #1,A
    CLOSE #1
    • 45: CommentAuthormono
    • CommentTime1 Feb 2013
     
    A w ogóle to ostatnio trafiłem na ciekawą nekonsekwencję w basicu. Mianowicie operacje OPEN,CLOSE,XIO,STATUS dostępne są dla kanałów 1..7. A INPUT i PRINT można przeprowadzać bez problemu też na #0 :D
    • 46:
       
      CommentAuthormgr_inz_rafal
    • CommentTime2 Feb 2013 zmieniony
     
    OK, dodałem CHR$() oraz LEN() i sortowanie alfabetyczne działa. Uff :)

    Kod musiałem lekko zmodyfikować, gdyż wciąż brak obsługi pewnych detali:
    1. Zamiast THEN NUMER musi być THEN GOTO NUMER
    2. Nie kompiluję jeszcze pustych stringów, dlatego B$="" musiałem zastąpić B$="*" (dlatego też wpisywanie tekstów kończymy właśnie gwiazdką, a nie enterem)
    3. Na wszelki wypadek dodaję spacje na lewo i prawo plusa i minusa (np. zamiast 2+3 wstawiam 2 + 3). Coś muszę poprawić w parserze, żeby plus rozpoznawał jako działanie a nie jako jawnie podany znak dla trójki, co skutkuje syntax errorem).

    Jest jeszcze jeden problem - nie działa mi INPUT B$ w linijce 150. Nie mam pojęcia dlaczego. Po wykonaniu jsr JCIOMAIN dostaję do akumulatora śmieci. Proszę o pomoc w znalezieniu przyczyny, bo sam latam trochę po omacku. Wcześniej taki INPUT działa, więc może w międzyczasie, w wyniku działania programu uszkadzane są jakieś ważne komórki pamięci dla CIO. Czego szukać?

    Załączam skompilowany prog.xex. Skok do CIO jest pod $7AC0. Proszę na razie nie kpić ze struktury programu, ze skoków bez tablicy skoków, złej implementacji PRINTa (bez CIO), układu danych w pamięci :) To na później :)

    Po poprawieniu tego błędu oraz powyższych paru punktów gotowa do publikacji będzie wersja ALFA :)

    PS. Na jutuba wrzuca się właśnie film demonstrujący porównanie prędkości sortowania przed i po kompilacji. Jak się wrzuci to dodam link. Widać na nim, że sortowanie przyspieszyło "jako tako", natomiast największego kopa dostała linijka 135 :)

    OK, filmik już jest, polecam oglądać na YouTube w HD:


    A tutaj kod sortowania z lekkimi modyfikacjami:
    5 REM  *  *  *  SORTOWANE ALFABETYCZNE  *  *  * 
    10 DIM A$(2000),B$(20),C$(20)
    15 PRINT CHR$(125):REM MAZANIE EKRANU
    20 PRINT :PRINT "SORTOWANIE ALFABETYCZNE"
    25 PRINT :PRINT "PODAJ TEKSTY DO SORTOWANIA"
    26 REM N - ILOSC ELEMENTOW
    35 N=0:PRINT
    40 N=N + 1
    45 PRINT N;")";:INPUT B$
    50 IF B$="*" OR N>100 THEN GOTO 70
    55 P=N * 20 - 19:A$(P)=B$
    56 REM P - ADRES 1 ZNAKU n - tego TEKSTU
    60 FOR J=P + LEN(B$) TO N * 20:A$(J)=" ":NEXT J
    65 GOTO 40
    70 PRINT :PRINT " POCZATEK SORTOWANIA"
    75 FOR J=2 TO N - 1
    80 B$=A$(J * 20 - 19,J * 20)
    85 FOR K=J - 1 TO 1 STEP -1
    90 C$=A$(K * 20 - 19,K * 20)
    95 IF C$<B$ THEN GOTO 110
    100 A$(K * 20 + 1,K * 20 + 20)=C$
    105 NEXT K
    110 A$(K * 20 + 1,K * 20 + 20)=B$
    115 NEXT J
    120 PRINT
    125 FOR J=1 TO N - 1
    130 PRINT J;")";A$(J * 20 - 19,J * 20)
    135 FOR K=1 TO 200:NEXT K
    140 NEXT J
    145 PRINT :PRINT "NACISNIJ RETURN"
    150 INPUT B$
    155 GOTO 15
    • 47: CommentAuthormono
    • CommentTime2 Feb 2013 zmieniony
     
    Rejestr X powinien zawierać nr kanału * 16.

    Edit: A i jeszcze może się okazać, że z jakichś przyczyn CIO się nie uda (np. wciśnięto break). Wtedy po powrocie z jciomain od razu powinieneś sprawdzić znak (bmi) i obsłużyć błąd. Ale to pewnie planujesz w dalszej kolejności.
  9.  
    @mono, dzięki
    Sprawdzę co mam w tym X :)

    A obsługę błędów - fakt - planuję na później ;)
    • 49: CommentAuthorbrx
    • CommentTime3 Feb 2013
     
    @mono: książka "Poradnik programisty Atari" informuje, że do wymuszenia wprowadzania danych bez pytajnika wystarczy:

    INPUT #16, zmienna

    I to działa :)

    @mgr: nie wiem jak to wygląda "od środka" i jak to działa, ale oba rozwiązania będziesz musiał zaimplementować ;)

    Nawiasem mówiąc wielka szkoda, że nie było tej informacji w słynnym "Atari Basic"... Mnóstwo rzeczy potoczyłoby się pewnie inaczej :)
    • 50:
       
      CommentAuthormgr_inz_rafal
    • CommentTime3 Feb 2013 zmieniony
     
    @mono
    Dzięki, wystarczyło LDX #0 i zaczęło działać.

    Teraz tak: domyślam się zatem, że przed wywołaniem CIO muszę do X wpisać to, co jest ewentualnie pierwszym parametrem INPUT * 16, tak?

    Np. jak jest
    INPUT #5, A$
    to do X wstawiam 80?

    A jak nie ma numeru kanału to przyjmujemy 0.

    I przy okazji, czy mógłbyś - analogicznie do EGETCH - pokazać, jak zrobić poprawny EPUTCH? Zmieniłbym od razu implementację PRINTa na słuszną.

    @brx
    Ja też za bardzo nie wiem, jak to wygląda od środka. Na szczęście mono ma to wszystko w małym palcu :) Póki co wydaje się, że numery kanałów i ich obsługa to wewnętrzna sprawa CIO, więc może nie będzie tak trudno.