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:
         
        CommentAuthormgr_inz_rafal
      • CommentTime12 Oct 2012 15:10 zmieniony
       
      Hej,
      Parę miesięcy temu, podczas pisania Biednego Psa Antoniego zakiełkowała we mnie myśl, żeby napisać kompilator Basica na PC. No i właśnie kilka(naście) ostatnich wieczorów spędziłem nad Flexem i Bisonem tworząc szkielet parsera oraz zalążek generatora kodu ASM.

      Działa to tak, że program wciąga listing w BASIC i wypluwa kod w .asm, który za pomocą MADS przerabiamy na .xex i odpalamy :)

      Co w bieżącej wersji:
      1. Obsługa wyrażeń arytmetycznych
      2. Obsługa "PRINT wyrażenie_arytmetyczne"
      3. Obsługa "GOTO wyrażenie_arytmetyczne"

      Czyli bez problemu skompilujemy sobie program w stylu:
      10 PRINT (2 + 3) * 4
      20 PRINT
      30 PRINT 1 + 2 + 3 * (4 + 5 + 6) / (444.3 + 0.0001)
      40 GOTO (5 + 5) * 2

      Wynik działania poniżej:


      Wszystkie obliczenia dokonywane są przez Atari - kompilator nic nie optymalizuje. Ogólnie to zacząłem od podejścia takiego, że parser dokonuje obliczeń, ale różnica w wynikach operacji na liczbach zmiennoprzecinkowych zmusiła mnie do zmiany drogi ze względu na chęć utrzymania maksymalnej kompatybilności z Atari Basic. Choć trochę szkoda, bo dawało to niezłego speeda, np. taka linijka:
      PRINT "4 + 12 * 4 * (3 + 13) = "; 4 + 12 * 4 * (3 + 13)

      powodowała, że w .xex lądował od razu string takiej postaci:
      dta c"4 + 12 * 4 * (3 + 13) = 772"

      A teraz w to miejsce wygeneruje się pełno kodu operującego na FR0 :(

      Mniejsza o to, kiedyś może będzie opcja wymuszenia działania na liczbach całkowitych dla programów, które nie korzystają z floating-point.

      Wątek zakładam z trzech powodów:
      1) Aby się pochwalić :>
      2) Aby mieć miejsce, gdzie będę zadawał dziwne pytania o to jak coś zrobić w ASM, jeśli nie znajdę tego w opisie procedur systemowych
      3) Aby poznać Waszą opinię na temat kompilatora (ale to już po tym, gdy będę miał coś, co nada się do opublikowania).

      Kolejny krok:
      Zmienne nietablicowe.
      • 2: CommentAuthorgorgh
      • CommentTime12 Oct 2012 16:10
       
      • 3: CommentAuthorbob_er
      • CommentTime12 Oct 2012 18:10
       
      A myślałeś nad tym, by na PC zapisywać kod basicowy w postaci stokenizowanej?
      Tudzież, by była to opcja.
      Choć w sposób asmowy (jaki masz obecnie), to może być dużo szybsze.
    1.  
      @bob_er
      Właściwie to nie. Od początku planowałem robić bezpośrednio asma.

      Nie znam nawet za bardzo tematu basicowego tokenizowania. Czy zapis listingu do pliku BAS to nie jest właśnie to?
      • 5:
         
        CommentAuthortdc
      • CommentTime12 Oct 2012 20:10 zmieniony
       
      Ogólnie fajnie, jak się postarasz to może to będzie dobry konkurent dla Action! :P
      (w sensie wydajności, bo procedur tu nie będzie i wielu innych cennych rzeczy)
      • 6:
         
        CommentAuthorpirx
      • CommentTime12 Oct 2012 21:10
       
      Zarąbiste!

      Czy celem jest kompilowanie starych programów w atari basic?

      Bo jeśli nie, to może warto zastanowić się nad porzuceniem nr linii, labelkami jak w TBXL, procedurami / funkcjami.

      W grach zmienny przecinek można wyeliminować / zasymulować na kilku intach a systemowe floaty są b. wolne - kompilacja dramatycznie nie poprawi sytuacji.

      Piszę to, bo chyba brakuje takiego języczka, w którym możnaby usiąść i w wieczór zakodować prototyp - miał być Atalan, ale jakoś nie wychodzi z wieku embrionalnego. CC65 to inna liga. Action! jest super, ale jak już się w nim długo siedzi i wie, co można a co nie.
      • 7:
         
        CommentAuthorxeen
      • CommentTime12 Oct 2012 21:10
       
      co znaczy : cc65 to inna liga?
      • 8:
         
        CommentAuthortdc
      • CommentTime12 Oct 2012 22:10
       
      @pirx, no i koniecznie niech procedury mają parametry bo w TBXL nie mają i sam na własnej skórze odczułem że to fatalny brak...
    2.  

      tdc:

      bo procedur tu nie będzie i wielu innych cennych rzeczy

      tdc:

      no i koniecznie niech procedury mają parametry
      Póki co, żeby nie paść ofiarą feature creep, celem jest kompatybilność tylko i wyłącznie z czystym Atari Basic.

      pirx:

      Czy celem jest kompilowanie starych programów w atari basic?
      Tak szczerze, to moim celem jest dobra zabawa przy tym projekcie :)

      pirx:

      Bo jeśli nie, to może warto zastanowić się nad porzuceniem nr linii, labelkami jak w TBXL, procedurami / funkcjami.
      Tak jak pisałem wyżej, na razie Atari Basic, żeby się nie zagrzebać. Zresztą, praktyka pokazuje, że jeśli zrobi się dobry szkielet kompilatora, to dodawanie kolejnych funkcji to raczej betka, no chyba, że myślimy np. o polimormiźmie, ale do tego nie zmierzam :) Jeśli starczy mi sił na dobrą implementację arytmetyki, tablic, ideksowania tablic dowolnymi wyrażeniami, to już potem można sobie mnożyć różne pętle, ify, elsy, procedury, labelki...

      pirx:

      W grach zmienny przecinek można wyeliminować / zasymulować na kilku intach a systemowe floaty są b. wolne - kompilacja dramatycznie nie poprawi sytuacji.
      No właśnie wiem, że obliczenia FP "ssają". Wstępnie myślałem, aby w przyszłości ukraść procedury FP z bodajże Turbo Basica - tam to działało chyba trochę szybciej. Ale fakt, symulacja na intach jest ciekawa - robiło się takie rzeczy w midletach na pierwsze telefony z Javą, bo tam wcale nie było float ;)

      Podsumowując: na razie małe kroczki i tylko Atari Basic. Pracy wbrew pozorom jest dużo, bo np. taki program jak powyżej generuje ok. 14 zmiennych tymczasowych, które na razie nie są optymalizowane i zaśmiecają pamięć "na zawsze". Z powodzeniem mógłbym przez weekend dorobić obsługę GRAPHICS, PLOT, DRAWTO, USR, itp. itd., ale najpierw chcę dopracować fundament.
      • 10:
         
        CommentAuthortdc
      • CommentTime12 Oct 2012 23:10
       
      Mną się nie przejmuj bo ja nie jestem zainteresowany praktycznym wykorzystaniem tego. Ale chętnie zobaczę jak działa, jakie ma osiągi oraz jak się temat będzie rozwijał.
    3.  

      tdc:

      Ale chętnie zobaczę jak działa, jakie ma osiągi
      Na pewno GOTO będzie szybsze ;-)
      • 12:
         
        CommentAuthorpirx
      • CommentTime13 Oct 2012 13:10
       
      >mgr_inz_rafal
      >Tak szczerze, to moim celem jest dobra zabawa przy tym projekcie :)

      I tak trzymaj, to najważniejsze!!!!!!!!11!!!oneone

      >xeen
      >co znaczy : cc65 to inna liga?

      10 K=5
      20 ?"Ala ma ";K;" kotow":K=K+1:G.20

      Nie mam zainstalowanego i skonfigurowanego CC65, a z palca nie napiszę wersji w tym języku, ale myślę, że widzisz, o co mi chodzi. By napisać programik tego rodzaju trzeba wiedzieć, jakie biblioteki załączyć, itp. Generalnie chodzi mi o otoczkę kodu, która jest ważna dla komputera, a nie dla człowieka. Atalan to ideał, bo w nim praktycznie każdy znak jest ważny dla człowieka. W BASICU numery linii są takim elementem wymuszonym przez maszynę.
      • 13:
         
        CommentAuthortdc
      • CommentTime14 Oct 2012 13:10
       
      @mgr_inz_rafal
      He he, a ile teraz czasu goto zajmuje? tak z ciekawości pytam, 5 ramek ?;)
      • 14:
         
        CommentAuthorxeen
      • CommentTime16 Oct 2012 14:10
       
      >10 K=5
      >20 ?"Ala ma ";K;" kotow":K=K+1:G.20

      >Nie mam zainstalowanego i skonfigurowanego CC65, a z >palca nie napiszę wersji w tym języku, ale myślę, że >widzisz, o co mi chodzi. By napisać programik tego >rodzaju trzeba wiedzieć, jakie biblioteki załączyć, itp. >Generalnie chodzi mi o otoczkę kodu, która jest ważna dla >komputera, a nie dla człowieka. Atalan to ideał, bo w nim >praktycznie każdy znak jest ważny dla człowieka. W BASICU >numery linii są takim elementem wymuszonym przez maszynę.

      generalnie się nie zgadzam, ale rozumiem o co Ci chodzi :)
      • 15: CommentAuthorilmenit
      • CommentTime17 Oct 2012 19:10 zmieniony
       
      10 K=5
      20 ?"Ala ma ";K;" kotow":K=K+1:G.20

      Nie mam zainstalowanego i skonfigurowanego CC65, a z palca nie napiszę wersji w tym języku, ale myślę, że widzisz, o co mi chodzi. By napisać programik tego rodzaju trzeba wiedzieć, jakie biblioteki załączyć, itp. Generalnie chodzi mi o otoczkę kodu, która jest ważna dla komputera, a nie dla człowieka. Atalan to ideał, bo w nim praktycznie każdy znak jest ważny dla człowieka. W BASICU numery linii są takim elementem wymuszonym przez maszynę.



      A tutaj trzeba wiedzieć, dlaczego znak zapytania wypisuje coś na ekran, jaka jest składnia języka, dlaczego łącznik jest za pomocą średnika, że dwukropek oddziela instrukcje, co znaczy G kropka.

      Nie wiem, czy to znacznie prostsze od:

      #include <stdio.h>

      void main(void)
      {
      int k=5;
      for(;;) printf("Ala ma %d kotow",k++);
      }

      W jednym i w drugim przypadku potrzebna jest podstawowa znajomość języka.
      • 16:
         
        CommentAuthorpirx
      • CommentTime17 Oct 2012 21:10 zmieniony
       
      Hej! Dla wyjaśnienia - ja wcale nie uważam, że CC65 jest niedobre, wręcz przeciwnie. Uważam tylko, że to znacznie bardziej skomplikowane (zaawansowane) narzędzie od BASICa. Coś jak piła łańcuchowa i siekiera. Ja akurat szukałem dla siebie takiego małego toporka :]

      Konkretnie z tego przykładu chodzi mi o początek:
      #include <stdio.h>
      void main(void)

      Taka rozbiegówka...

      Kuuurcze, może jednak wezmę piłę łańcuchową?
    4.  
      Pytanie do znawców asemblera.

      Małe wprowadzenie: Każdą napotkaną w źródle liczbę muszę potraktować funkcją AFP, która wymaga tekstu ATASCII gdzieś w pamięci. Adres początku bufora należy wstawić do INBUFF.

      Moje pierwsze podejście było takie: Jak napotkasz liczbę, to dodaj taką linijkę (backslashe dodane przez Forum):
      fp75a dta c'444.3#'
      a gdzieś wcześniej:
      lda <fp75a
      sta INBUFF
      lda >fp75a
      sta INBUFF+1

      Wszystko oczywiście działa, ale pomyślałem naiwnie, że po co mi aż tyle linijek "dta" dla każdej liczby, skoro mogę zapisywać napotkane ATASCII do jakiegoś konkretnego, stałego bufora, np. od C0 do CA.
      Po krótkiej implementacji na jaw wyszła naiwność, bo proste "dta c'444.3#'" zamieniło mi się w 6 par LDA/STA, co pewnie zajmuje jeszcze więcej miejsca w .xex.

      Wróciłem więc do koncepcji pierwotnej, ale coś mi nie daje spokoju :) Konkretnie to, że AFP wykonuje się dość długo. Dlatego też - UWAGA - zadaję pytanie:
      1. Czy metoda z "dta -> sta INBUFF -> jsr AFP" jest Waszym zdaniem optymalna?

      I pytanie dodatkowe:
      1. Czy ktoś posiada może przypadkiem funkcję AFP przepisaną na C albo na jakiś pseudokod? :) Mógłbym wtedy 6 bajtów każdej liczby FP wyznaczać w czasie kompilacji.

      A na razie mam szatański plan, aby podczas kompilacji odpalać emulator z prostym xex-em, który obliczy mi to co chcę :>
      • 18: CommentAuthorrudla
      • CommentTime19 Oct 2012 13:10
       
      If you are using MADS, try using .FL directive.

      pi .fl 3.1415926535897932384626433832795 ; 40 03 14 15 92 65

      No additional conversion should be necessary, you may use FLD0R or FLD1R functions.
    5.  
      @rudla
      Tchx, that looks like something I was looking for :) Will try the implementation in the evening.

      -----
      OK, tried it. Works perfect!
    6.  
      Jest mały postęp, dodałem obsługę zmiennych liczbowych. Dzięki temu spokojnie kompilujemy taki kod:
      10 A = 3.4
      20 A = A + (A - (0.90 * A) / 17.54)
      30 PRINT A
      40 GOTO 20
      Efekt poniżej na obrazku.
      • 21: CommentAuthorLCD
      • CommentTime27 Oct 2012 01:10
       
      No niezle! Chcialem przypomniec ze Boriel zajmuje sie tez pisaniem kompilera BASICa który ma w przyszlosci obslugiwac Atari:
      ->link<-
      Jak na razie wersja dla ZX'a juz bardzo dobrze pracuje i powstalo kilka niezlych gier:
      ->link<-
    7.  

      LCD:

      Chcialem przypomniec ze Boriel zajmuje sie tez pisaniem kompilera BASICa
      Przypomnieć, a właściwie to uświadomić :) Nie wiedziałem wcześniej o tym projekcie.

      Szczerze mówiąc, to nawet nie próbowałem badać tematu - po prostu zacząłem sobie od nowa :) Ale Wiki Boriela chętnie poczytam.
    8.  
      A tak na marginesie... Poniżej efekt uruchomienia programu z postu #20 w BASICu. Liczby są przycięte do 10 znaków.

      Z jednej strony chciałbym być maksymalnie kompatybilny z BASIC, a z drugiej szkoda mi sztucznie ograniczać mojego PRINTa. Czy ktoś zna jakieś uzasadnienie, dlaczego BASIC tak przycina liczby?
      • 24: CommentAuthorwieczor
      • CommentTime27 Oct 2012 09:10
       
      A nie zauważyłeś nic charakterystycznego zwłaszcza po wypisaniu ich na ekranie? :) Wszystkie mają max 10 znaków :)
      • 25: CommentAuthorrudla
      • CommentTime27 Oct 2012 10:10
       
      It's hard to know for sure, but if the routine does rounding (not just ignores last digit), it would probably hide some computation inaccuracies from user.
    9.  
      @wieczór
      Zauważyłem - i dlatego właśnie pytam :) Czy ograniczenie do 10 znaków ma jakiś ukryty sens, czy po prostu komuś tak się podobało.

      Zastanawiam się, czy też powinienem tak przycinać? I pewnie będę musiał, bo przypuszczam, że istnieją gry/programy w BASIC, które korzystają z tej, nazwijmy to, cechy.

      @rudla
      It seems that computation is done correctly, since the numbers in both programs (ASM and BASIC) are equal after several iterations. The console output in BASIC seems to be limited to 10 chars, however.
      • 27: CommentAuthormono
      • CommentTime27 Oct 2012 11:10
       
      ->link<- sekcja "Format liczb zmiennoprzecinkowych".
    10.  
      Czy Atari Basic zeruje pamieć przydzielaną na tablice przez DIM/COM? Z doświadczenia wynika, że niezainicjowana tablica to same zera, ale wolę dopytać :)
      • 29: CommentAuthormono
      • CommentTime31 Oct 2012 11:10
       
      Nie zeruje. Prosty test:
      DIM T$(20):T$(20)="":? T$

      pokaże cały śmietnik.
      Oczywiście jeśli zrobisz to na świeżo włączonym atari, jako pierwsze polecenie (os zeruje pamięć podczas zimnego startu), możesz dostać same zera w stringu, ale to o niczym nie świadczy.
      Drugi test:
      DIM T$(50):T$="ALA MA KOTA A KOT MA ALE":NEW
      DIM T(20):? T(0)

      pokaże już śmieci, bo wcześniej w miejscu tablicy numerycznej znajdował się string.
    11.  
      Super, dzięki.
      To oszczędzi mi parę cykli :)
    12.  
      OK, uwinąłem się trochę z tymi tablicami i mam świeży, wieczorny wypiek :)

      Można już kompilować coś takiego:
      10 X = 1000
      20 Y = 10
      30 DIM ARR(X / Y)
      40 ARR(50 + 50) = 666
      50 BAR = 25
      60 PRINT ARR(BAR * 4)


      Wynik:
      • 32:
         
        CommentAuthorxeen
      • CommentTime31 Oct 2012 22:10
       
      awsome!
    13.  
      Dobra, to wrzucam jeszcze jeden update i idę szykować znicze :)

      Można już sobie zagnieżdżać tablice w wyrażeniach arytmetycznych, razem ze zmiennymi i stałymi, np.:
      5 DIM C(100)
      6 DUPA = 9
      10 DIM A(10)
      20 DIM B(10)
      21 B(2) = 3
      22 B(9) = 100 - (101 - B(2))
      23 C(66) = 5
      25 PRZEMYSLAW = DUPA - 7
      30 A(C(66)) = 10
      40 B(A(2 + B(B(B(B(PRZEMYSLAW) - 1) * B(B(DUPA)))))) = 666
      50 PRINT B(A(C(66))) / (B(2) - 1)


      I wynik:


      PS. Następny krok to trochę optymalizacji, bo mi się .xex za duży generuje. A potem wyrażenia warunkowe na liczbach, co pozwoli na zaprogramowanie prostych pętli i myślę, że będę mógł opublikować jakąś bardzo pierwszą wersję compilera.
      • 34: CommentAuthormono
      • CommentTime31 Oct 2012 23:10 zmieniony
       
      Zerknij może na to: ->link<- bo się okaże, że programy po kompilacji nie działają "poprawnie" :P
      Szczególnie polecam 1^44 i 2^44 oraz CHR$(34)=CHR$(35) (identycznie jest oidp z STR$).
    14.  
      Dzięki mono za czujność. Jak wiadomo, diabeł tkwi w szczegółach :)

      Potęgowanie zrobię za pomocą OS, więc będzie działać tak samo "dobrze" jak w Atari Basic.

      Natomiast o porównywaniu CHR$ nie wiedziałem, więc pewnie potrzebna będzie jakaś opcja kompilacji typu "--keep-bugs-for-compatibility" :)
      • 36:
         
        CommentAuthorjhusak
      • CommentTime1 Nov 2012 05:11
       
      Staję w obronie wszystkich Przemysławów!
      • 37:
         
        CommentAuthorjhusak
      • CommentTime1 Nov 2012 05:11 zmieniony
       
      Tak nawiasem mówiąc, to zbytnie rozrastanie się kodu pod 6502 to powszechna bolączka wszelkich kompilatorów, dlatego tak popularne są interpretery na ten procesor. Składnia i bajtkody rozpoznawane podczas wprowadzania kodu, potem już czysta interpretacja odpowiednich kodów.

      Narzut wbrew pozorom akceptowalny, a jakie długie programy można pisać :)

      Szczytem jest intepreter stosowany w SO i Basic wczesnych komputerów Apple: ->link<-

      Dla 6502, aby uzyskać sensowny kod wynikowy, trzeba mieć język, który łatwo wpisuje się w ten model.

      Polecam świetny artykuł - spis: ->link<-
      • 38: CommentAuthormono
      • CommentTime2 Nov 2012 12:11
       
      ? ASC("")
    15.  
      @jhusak
      Fakt, trochę RISCowy ten 6502... Mogli się pokusić chociażby o obsługę MOV :)

      Ale na chwilę obecną wydaje mi się, że rozrastanie da się opanować. Kod asemblerowy najbardziej rośnie w takich testowych programach, jak zaprezentowałem parę postów wyżej - na co dzień (dobry) programista raczej nie pisze takich kwasów. Zresztą już teraz widzę i przeczuwam, że wielkość będę mógł ściąć ~4 krotnie tworząc procedury i robiąc JSR, a nie po prostu sadzić powtarzające się ciągi LDA/STA/LDA/STA.

      Polecenia typu POKE, GRAPHICS, PLOT, SOUND raczej wiele asemblera nie wygenerują.
      • 40: CommentAuthorbob_er
      • CommentTime3 Nov 2012 19:11
       
      ale drawto może :)
      właśnie - zrobisz swojego drawa i plota (szybszego) czy oprzesz się na systemowym?
    16.  
      @bob_er
      A nie ma gdzieś tam w OS gotowego DRAWTO? :)

      Na początek chcę tylko w miarę dobrze odwzorować BASIC, później będę chciał optymalizować to co się da, np. obliczenia FP czy też inne funkcje, dla których przez 40 lat powstały lepsze odpowiedniki niż te w Atari OS.
      • 42: CommentAuthormono
      • CommentTime7 Nov 2012 13:11
       
      • 43:
         
        CommentAuthorMaW
      • CommentTime7 Nov 2012 17:11
       
      XIO #18 ?
    17.  
      Dzięki za info i linki. Jak już dojdę do grafiki, to pewnie zacznę dalej drążyć temat.
    18.  
      Ale, póki co... Pod "nieobecność" AtariOnline.pl dorobiłem do kompilatora instrukcję warunkową (IF...THEN) i pojawił mi się problem z "branch out of range".

      Jakiś czas temu w wątku o Biednym Psie mono podsunął mi rozwiązanie:

      mono:

      Zamiast beq,bpl,bcc,itd. używaj odpowiednich makr jeq,jpl,jcc,itd. To zrobi kod (np. dla jeq gdzieśtam):
      bne *+5
      jmp gdzieśtam


      W imię zasady, że chcę rozumieć to co piszę, prosiłbym o wyjaśnienie o co chodzi z tą gwiazdką przy bne i dlaczego +5?
      • 46: CommentAuthormono
      • CommentTime7 Nov 2012 22:11
       
      * oznacza bieżący pc, czyli miejsce ulokowania bne. a +5 ponieważ bne na 2 bajty, a jmp 3. Polecam gorąco tabelki na końcu ->link<-
    19.  
      JEQ spisuje się świetnie. Tzn. trochę dostałem rykoszetem, bo MADS jeśli może to generuje krótki skok, a jeśli nie może to długi. A muszę dokładnie wiedzieć jakie są adresy poszczególnych linijek w ASM (tzn. wiedzieć, jaki skok wygeneruje JEQ), żeby móc kompilować GOTO bez dodatkowego przebiegu... Stosunkowo trudno było to obliczyć w czasie kompilacji, dlatego na razie zawsze sadzę BNE *+5, żeby mieć pewność, że na skoki zjadam stałą liczbę bajtów.

      W każdym bądź razie oto efekt ostatnich paru dni spędzonych nad obsługą wyrażeń warunkowych.

      Program #1 - różne kombinacje większości, mniejszości, itp.:
      5 DIM KONGO(30)
      6 KONGO(20) = 3
      10 IF KONGO(20) - 1 < KONGO(10 + 2 * 5) THEN PRINT KONGO(20) - 2
      20 IF 2 < 2 THEN PRINT 2
      30 IF 2 < 1 THEN PRINT 3
      40 IF 2 > 3 THEN PRINT 4
      50 IF 2 > 2 THEN PRINT 5
      60 IF 2 > 1 THEN PRINT 6
      70 IF 2 >= 3 THEN PRINT 7
      80 IF 2 >= 2 THEN PRINT 8
      90 IF 2 >= 1 THEN PRINT 9
      100 IF 2 <= 3 THEN PRINT 10
      110 IF 2 <= 2 THEN PRINT 11
      120 IF 2 <= 1 THEN PRINT 12
      130 IF 2 = 3 THEN PRINT 13
      140 IF 2 = 2 THEN PRINT 14
      150 IF 2 = 1 THEN PRINT 15
      160 IF 2 <> 3 THEN PRINT 16
      170 IF 2 <> 2 THEN PRINT 17
      180 IF 2 <> 1 THEN PRINT 18
      200 GOTO 10
      1000 PRINT 666

      Myk z KONGO() wprowadzony po to, aby sprowokować konieczność długiego skoku.

      Wynik:


      Program #2 - IFy zagnieżdżone:
      10 KASZANKA = 100
      20 WIDELEC = 200
      30 PRINT WIDELEC
      40 IF KASZANKA > 10 THEN IF WIDELEC > 10 THEN WIDELEC = 2
      50 PRINT WIDELEC
      60 IF KASZANKA > 10 THEN IF WIDELEC > 10 THEN WIDELEC = 666
      70 PRINT WIDELEC


      Wynik:


      No i program #3 pokazujący, że już tylko mały kroczek dzieli nas od prawdziwego FORa :)
      10 MACIEREWICZ = 2
      20 PRINT MACIEREWICZ
      30 MACIEREWICZ = MACIEREWICZ + 3
      40 IF MACIEREWICZ < 31 THEN GOTO 20


      Wynik:


      A teraz dobranoc, idę pograć w Tappera ;)
    20.  
      Dziś mam pytanie do ludzi doświadczonych w Atari Basic...

      ...OK, sorry, nie było pytania - już czaję :)

      Pętle dostępne wkrótce :)
      • 49:
         
        CommentAuthorpirx
      • CommentTime13 Nov 2012 21:11
       
      >A muszę dokładnie wiedzieć jakie są adresy poszczególnych linijek w ASM (tzn. wiedzieć, jaki skok wygeneruje JEQ), żeby móc kompilować GOTO bez dodatkowego przebiegu...

      Hej! Ale po co znać adres? Nie lepiej byłoby skakać do labelki w rodzaju
      line100
      line110
      line120
      line130
      jeśli miałoby być tak bardzo basicowo?
    21.  
      @pirx
      Spoko, już temat ogarnąłem w taki właśnie sposób. Skok do następnej linijki (jeśli IF nie jest spełniony) jest robiony po labelce.

      Niestety to rozwiązanie nie działa dla wyrażeń (np. GOTO X * 10), bo ich wartość nie jest znana w czasie kompilacji i nie wiadomo do jakiej labelki zrobić JMP. Dlatego też zwykłe GOTO musiałem trochę bardziej zakombinować.