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 11:12 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 22:12 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 22:12 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 00:12 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 02:12 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 10:12 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 12:12
       
      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 23:12 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:
    2.  
      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 19:01
       
      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.
    3.  
      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 17:01 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 :-)
    4.  
      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?
    5.  
      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 22:01
       
      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 14:01 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:
    6.  
      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 ;)
    7.  
      Przecinek by mono działa! :)
      Dzięki!
    8.  
      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 21:01 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.
    9.  
      A test czy FR0=FR1?
      • 23: CommentAuthorxxl
      • CommentTime27 Jan 2013 00:01
       
      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 00:01
       
      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:
      ...

    10.  
      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 10:01 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
    11.  
      xxl, dzięki :)

      A mógłbyś zasadę działania trochę rozjaśnić?
      • 28: CommentAuthorxxl
      • CommentTime27 Jan 2013 11:01
       
      to jest to samo co pokazal jhusak tylko zapisane inaczej - wolniejsza ale krotsza o 10b wersja.
      • 29: CommentAuthorBartoszP
      • CommentTime27 Jan 2013 11:01
       
      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 11:01
       
      10 - 4 = 3 ? "psucie" reg.Y jest mocno dyskusyjne ;)
      • 31: CommentAuthorBartoszP
      • CommentTime27 Jan 2013 11:01
       
      Oczywiście, że 3 bo to liczby o podstawie 7 były :-)

      Ale tak czy inaczej obstaję, że Y się "raczej popsuje".
    12.  
      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 15:01 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 ?
    13.  
      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 16:01
       
      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 19:01 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).
    14.  
      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 18:01
       
      to znaczy czego brakuje? porownywales szybkosc dzialania po kompilacji z mmg bsic compilerem?
    15.  
      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.
    16.  
      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 20:01
       
      1. To ograniczenie urządzenia E:. Limit jest oidp na 128 znaków.
      2. Tak. Nie jest.
      • 42: CommentAuthorbrx
      • CommentTime31 Jan 2013 21:01
       
      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 01:02
       
      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 18:02
       
      @brx: Fakt. Wystarczy zrobić:
      OPEN #1,12,0,"E:"
      INPUT #1,A
      CLOSE #1
      • 45: CommentAuthormono
      • CommentTime1 Feb 2013 18:02
       
      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
    17.  
      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 23:02 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.
    18.  
      @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 00:02
       
      @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 :)
    19.  
      @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.