OldComp.cz

Komunitní diskuzní fórum pro fanoušky historických počítačů


Právě je 23.05.2025, 07:06

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 4 ] 
Autor Zpráva
PříspěvekNapsal: 09.05.2025, 15:36 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3979
Bydliště: Bratislava
Has thanked: 387 times
Been thanked: 848 times
Kde bolo tam bolo, kedysi za starych (dobrych) cias, sme programy v strojaku robili tak ze sme si skompilovany kod ulozili na kazetu (alebo neskor na ine medium) a potom (alebo predtym) k tomu napisali zavadzaci basic co nas kod nahral do pameti a spustil.

V modernych (este lepsich) casoch crossdevelopmentu mozeme pouzit asembler, ktory nam vie zavadzaci basic vygenerovat automaticky. Ale co ak chceme nejaky iny basic ? Alebo robime finalnu verziu programu a v basicu chceme mat nieco vlastne, napriklad nejaky ten REM s datumom vydania, nejak ten PRINT s informaciou o programe, ci chceme nahravat viac blokov alebo proste urobit este nieco dalsie ?

Stale mame moznost si takyto basic osobitne rucne napisat, ulozit a potom ho pripojit k skompilovanemu kodu. Ale co ak v nom chceme dodatocne urobit nejaku zmenu ? Musime ho nahrat, zeditovat a znovu ulozit. A popripade zmazat staru verziu.

Ale to byva niekedy otravne. Viem, pri ladeni programu tych zmien v basicu nezvykne byvat az tolko ako zmien v asemblerovom zdrojaku, ale aj tak. Asemblerovy zdrojak upravime, skompilujeme (pomocou nejakeho makefile) a je to. Co ak by existoval takyto jednoduchy postup aj pre basic ?

Toto sa da riesit roznymi sposobmi. Jednym z nich su rozne vyvojove prostredia pre basic (napr. Basinc...), alebo v ramci projektu mame plaintext subor s basicom a v ramci kompilacie v nejakom makefile mozeme zavolat nejaky bas2tap.

Ale co ak mame nejaky malicky projekt (napr. 8b demo na LoveByte) a chceme mat vsetko pekne pokope v kratkom asemblerovom zdrojaku ? Ale aj keby nie, co ak potrebujeme nejaky specialny basic ? Napriklad chraneny voci vyLISTovaniu ?

Samozrejme takyto basic si mozeme napisat priamo vo forme DB bajt,bajt,bajt,"text"... ale ruku na srdce - bola by to dost otrocka praca. Pametat si kody prikazov, format riadku, ako napisat ciselne hodnoty, sa asi nikomu nechce (okrem uplnych fanatikov).

A po nekonecnom filozofovani sa konecne dostavame k tomu, k comu sme sa chceli dostat :)

BasicLib.asm

je kniznica - subor definicii a makier ktory vam ulahci pisanie basic programu priamo v asemblerovom zdrojaku.

Umozni vam takto mat vsetky komponenty projektu (basic + kod) v jednom (alebo viacerych) ASM zdrojakoch a jedinou kompilaciou vygenerovat hotovy vysledny TAP subor s vasim programom !

Zaroven vam ponechava plnu kontrolu nad pisanym programom. Napriklad nie je najmensi problem kdekolvek do programu vlozit akekolvek riadiace kody, napriklad na zaciatok kazdeho riadku mozeme vlozit kod pre PAPER 255. Docielime tym to, ze akykolvek pokus o vyLISTovanie ktorehokolvek riadku v basicu skonci s chybou K Invalid colour :) (niektore stare slovenske textovky mali takto chraneny basic)

Pouzitie BasicLib je velmi jednoduche:
Kód:
INCLUDE Basic.Lib

LINE : db bright : NUM 1 : LEND
LINE : db print,'"Hello world"' : LEND
Vygeneruje sa tento basic program:
Kód:
10 BRIGHT 1
20 PRINT "Hello world"
Makro LINE vygeneruje zaciatok basic riadku (cislo riadku + dlzka), makro LEND zase riadok uzavrie (doplni na koniec kod ENTER) a vypocita dlzku riadku pre predchadzajuce LINE).
Makro NUM zase rozvinie ciselnu hodnotu do textovej podoby + doplni kod 14 a 5 bajtov hodnoty cisla. Volitelne je samozrejme mozne nechat si vygenerovat aj podobu VAL "cislo".

Stahujte tu:
https://github.com/z00m128/sjasmplus/tree/master/examples/BasicLib
Na uvedenom odkaze najdete:
- BasicLib.asm
- Example-code-in-rem.asm ... priklad ako vytvorit basic so strojakom v REM prikaze
- Example-goto-restore.asm ... priklad ako pracovat s cislami riadkov v prikazoch
- Example-line-numbering.asm ... priklad ako si nechat automaticky cislovat riadky
- Example-simple-loader.asm ... priklad custom basicoveho loadera pre vas kod

V tom prvom priklade (code-in-rem) okrem ineho uvidite aj to ako v SjASMPlus ulozit do TAPky subory s menami obsahujucimi nielen klasicke ASCII znaky, ale aj samotne prikazy (tokeny).


Nahoru
 Profil  
 
PříspěvekNapsal: 09.05.2025, 16:37 
Offline
Radil
Uživatelský avatar

Registrován: 19.07.2013, 14:21
Příspěvky: 268
Bydliště: Košice
Has thanked: 155 times
Been thanked: 405 times
Ahoj,
pekna a sikovna vecicka, ale neda mi, aj toto by slo vylepsit. :dizzy:
Rozhodne mi nepride prehladne, ze tokeny su definovane malymi pismenami. Okrem toho, ze je to neprehladne, tak to nekoresponduje s tokenmi v BASICu spectra. Taktiez mi pri niektorych chyba "string" na konci (v podobe velkeho S). Vid definicie v udelatku, ktore som si robil pre svoje ucely: https://github.com/mborik/regression/bl ... rBASIC.inc

Dalsia vec, ktora mi prisla nelogicka je, ze si nevyuzil ponukanu moznost argumentu v makre LINE, ktory zada priamo cislo riadku priamo.
Autonumbering by mohlo pokryvat napr. AUTOLINE, alebo nieco take...

No a nakoniec, hodilo by sa v tvojom prispevku aspon spomenut, ze je to vylucne SjASMPlus zalezitost, nie ktorykolvek makroassembler (ziaden si v tomto pripade ani neskrtne) a este spomenut, ze aby sa ludom neplietli do ich kodu definicie tokenov, tak cely ich BASIC uzavriet do modulov.
Kód:
    module BASIC
    include Basic.Lib
...
    endmod


Nahoru
 Profil  
 
PříspěvekNapsal: 12.05.2025, 11:48 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3979
Bydliště: Bratislava
Has thanked: 387 times
Been thanked: 848 times
mborik128 píše:
Ahoj,
pekna a sikovna vecicka, ale neda mi, aj toto by slo vylepsit. :dizzy:
Jasne, kazdy napad je vitany !
mborik128 píše:
...tokeny su definovane malymi pismenami...
Tu som dlhsie rozmyslal, ako ich zadefinovat. Tvoje definicie typu C_TOKEN su sice programatorsky pekne, ale pri pisani vyzaduju ovela viac namahy :)
Ale ked sa to vezme cisto prakticky, s tymi mojimi sa nijak nebiju, takze nie je problem mat oboje naraz a clovek si moze vybrat, ktore pouzije. A hned mame prvy tip na zlepsenie :bulb:
Btw. tu by sa teraz naramne hodilo aby labely boli case insensitive, a aby tym padom mohol mat clovek plnu slobodu ci pouzije CAPS alebo nie.

Btw. pri VAL$ mam aj ja to velke S nahradzajuce $ :D
mborik128 píše:
Dalsia vec, ktora mi prisla nelogicka je, ze si nevyuzil ponukanu moznost argumentu v makre LINE, ktory zada priamo cislo riadku priamo.
No to je prave naopak, logicke, pretoze aj tak 99% pripadov (odhad z brucha, ale urcite je velmi blizko k 100%) pisat cisla riadkov aj tak nepotrebujes. Idealne by bolo, ak by makra umoznovali nepovinny parameter - clovek by mal slobodu ci si napise cislo riadku alebo nie.
mborik128 píše:
Autonumbering by mohlo pokryvat napr. AUTOLINE, alebo nieco take...
Alebo by som ponechal to LINE ako je a ak chce uzivatel zadat cislo riadku, tak LINEn <cislo_riadku> ako si medzitym navrhol. Proste dve rozne makra, jedno s automatickym cislovanom riadkov a jedno s explicitne zadanym riadkom - je dobry napad.

Ak teraz chce mat uzivatel svoje vlastne cislo riadku, napr. 1000, tak to napise takto:
Kód:
line_number = 1000
   LINE : ...... : LEND
a tento riadok bude mat cislo 1000.
Priklad, ako si nastavovat cisla riadkov a krok pre autonumbering, je v prilozenom subore Example-line-numbering.asm.
Btw. takto si moze zadat lubovolne cislo riadku od 0 az do 16383 ;)
mborik128 píše:
No a nakoniec, hodilo by sa v tvojom prispevku aspon spomenut, ze je to vylucne SjASMPlus zalezitost, nie ktorykolvek makroassembler (ziaden si v tomto pripade ani neskrtne)
To je pravda. Cele BasicLib je v repozitari pre SjASMPlus (samotny SjASMPlus na konci prveho prispevku spominam), takze funkcnost s inymi asemblermi nie je garantovana :shrug:
Ale viem ze vela ludi pouziva Pasmo a nieco som na Pasmo uz portoval (DecLzx02.asm) tak ak by vznikla poziadavka, mozem pouvazovat aj nad portom BasicLib.asm.
mborik128 píše:
a este spomenut, ze aby sa ludom neplietli do ich kodu definicie tokenov, tak cely ich BASIC uzavriet do modulov.
Ano, to je pravda. V prvom prispevku som nechcel ist az takto do podrobna (je to skor reklama nez dokumentacia), preto som nespominal ani dalsie veci ako napr. custom cislovanie riadkov.


Nahoru
 Profil  
 
PříspěvekNapsal: 19.05.2025, 15:24 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3979
Bydliště: Bratislava
Has thanked: 387 times
Been thanked: 848 times
...a kedze (aj sam na sebe) viem ze ludia su lenivi citat oficialnu dokumentaciu / zdrojak (co je mimobehom najpresnejsia dokumentacia), napisem sem taky ludskejsi pokec, ako BasicLib pouzivat.

A ako je uz taka programatorska tradicia, zacneme jednoduchym Hello world. Vlastne, uz sme zacali - v prvom prispevku tohto vlakna. Takze to sem len znovu skopirujem::
Kód:
  INCLUDE  BasicLib.asm
  LINE : db bright : NUM 1 : LEND
  LINE : db print,'"Hello world"' : LEND
Vygeneruje sa tento basic program:
Kód:
10 BRIGHT 1
20 PRINT "Hello world"
Makro LINE nam otvori novy basicovy riadok. Do prelozeneho kodu vygeneruje cislo riadku a ulozi dlzku riadku.
Makro LEND riadok uzatvara - vygeneruje kod 13 (enter) na konci riadku a je tiez potrebne pre spravny vypocet dlzky riadku. Dalej automaticky inkrementuje cislo riadku o dany krok tak, aby dalsia dvojica LINE...LEND logicky vygenerovala dalsie cislo riadku.

Mozno ste si vsimli, v tomto programe je este jedno makro: NUM. Toto makro sluzi na generovanie ciselnej konstanty - do skompilovaneho kodu ulozi textovy tvar cisla, potom kod 14 a za nim 5 bajtov hodnoty cisla. Momentalne su podporovane iba cele kladne cisla 0-65535. Ak chcete zapornu hodnotu - proste dajte pred cislo znak '-'. Aj basic to tak robi - po kode 14 uklada len kladne hodnoty a pred cislom pouzije minus :)

V basicoch setriacich pamet sa casto pouzivaju usporne tvary cisel VAL "cislo". Aj taketo nieco vie makro NUM vygenerovat.
Pre tento ucel je k dispozicii logicka premenna line_useval. Defaultne je nastavena na nulu ale ked si ju nastavime na nenulovu hodnotu, makro NUM bude
generovat cisla pomoocu VAL.
Kód:
  INCLUDE  BasicLib.asm

line_useval = 1

  LINE : db bright : NUM 1 : LEND
  LINE : db print,'"Hello world"' : LEND
Vysledkom bude tento program:
Kód:
10 BRIGHT VAL "1"
20 PRINT "Hello world"
Vsimli ste si, ze makra LINE a LEND nam riadky automaticky cisluju po 10 (tak ako byva zauzivanym zvykom) ?
Co ale ak chcem nejake ine cisla riadkov ?
V takom pripade su k dispozicii tieto dve premenne:

line_number ... aktualne cislo riadku ktore sa ulozi pomocou makra LINE
line_step .... krok o kolko sa v makre LEND zvysi cislo riadku pri generovani dalsieho riadku

Takze ak chcem aby moj program zacinal na riadku 100 a riadky sa cislovali po 1 tak staci spravit:
Kód:
  INCLUDE  BasicLib.asm

line_number = 100
line_step   = 1

  LINE : db bright : NUM 1 : LEND
  LINE : db print,'"Hello world"' : LEND
Vygenerovany program potom bude:
Kód:
100 BRIGHT 1
101 PRINT "Hello world"
Cislo riadku sa da samozrejme nastavit aj kdekolvek v ramci basic programu, napriklad:
Kód:
  INCLUDE  BasicLib.asm
  LINE : db bright : NUM 1 : LEND

line_number = 9999

  LINE : db print,'"Hello world"' : LEND
Basic program potom bude vyzerat:
Kód:
  10 BRIGHT 1
9999 PRINT "Hello world"
BasicLib automaticky kontroluje, aby cisla riadkov neprekrocili maximalnu moznu hodnotu 16363. Ak by malo dojst k vygenerovaniu riadku s cislom vyssim, kompilacia skonci s chybou "Line number overflows".

Niekedy je ale potrebne cisla riadkov pouzit v programe, napriklad v prikazoch GOTO, GOSUB, RESTORE, SAVE LINE ... Co v takom pripade ?
Kedze aktualne cislo generovaneho riadku vzdy mame v premennej line_number, nie je nic jednoduchsie, nez vyuzit tuto premennu.
Kód:
  INCLUDE  BasicLib.asm
  LINE : db bright : NUM 1 : LEND

goto_here = line_number

  LINE : db print,'"Hello world"' : LEND
  LINE : db goto : NUM goto_here  : LEND
A my dostaneme takyto program:
Kód:
10 BRIGHT VAL"1"
20 PRINT "Hello world"
30 GO TO 20
Kedze line_number sa inkrementuje v makre LEND, tak nielen v ramci generovania aktualneho riadku, ale uz pred nim je premenna line_number nastavena na cislo riadku ktory sa bude najblizsie generovat. Preto si staci pred riadkom, na ktory budeme skakat, odpametat line_number do inej premennej a tuto inu premennu nasledne pouzit v prikaze GOTO.
Ak skaceme na dany riadok v ramci tohto riadku, mozeme v prikaze GOTO a v za nim nasledujucom makre NUM rovno pouzit premennu line_number.
Samozrejme funguju aj dopredne skoky, t.j. prikaz GOTO ktory skace na niektory riadok ktory je v programe dalej.

A teraz trosku zlozitejsie veci :)

Ak chceme nacitat 16-bitove cislo v basicu, spravime to klasicky: PEEK adresa + 256 * PEEK (adresa+1).
Pokial chceme usporny tvar pomocou VAL, logicky nas napadne: PEEK VAL "adresa" + VAL "256" * PEEK VAL "adresa+1".
Lenze ! Naco zbytocne mat 3x VAL"" ked to staci iba raz ? Proste, cely vyraz zavrieme do jedineho VAL-u :) VAL"PEEK adresa + 256 * PEEK (adresa+1)"
Kedze samotna adresa nemusi byt vopred znama konstanta (ktoru vieme priamo napisat ako text), ale moze to byt nejaky label ktoreho hodnotu
sa dozvieme az kompilaciou, mali by sme mat moznost napisat aj takyto vyraz. Cize potrebujeme nieco, co nam ciselnu hodnotu previedie
do textovej podoby bez pouzitia VAL a generovania kodu 14 a 5 bajtov za nim.

A prave na toto je mozne vyuzit makro DEC ktore rozvinie 16-bitovu celociselnu hodnotu na postupnost cislic.
Kód:
        ..      .....
adresa  dw      nieco   ; Nejaka 16-bitova premenna niekde v kode
        ..      .....

  INCLUDE BasicLib.asm

  LINE
    db    let,'a=',val,'"',peek
    DEC   adresa
    db    '+256*',peek
    DEC   adresa + 1
    db    '"'
  LEND
(tu mozete vidiet ze som jeden basic riadok kvoli prehladnosti rozpisal na viac asemblerovych riadkov)

Dajme tomu, ze po kompilacii bude mat label 'adresa' hodnotu #8002 alebo 32770. Potom ziskame takyto program:
Kód:
10 LET a=VAL "PEEK 32770+256*PEEK 32771"
Na zaver este zopar poznamok k pouzitym tokenom (uz som sa toho trosku dotkol v predchadzajucom prispevku):

Kedze som chcel aby sa tokeny pisali co najjendoduchsie, su napisane malymi pismenami. Pre niektore velmi dlhe prikazy (RANDOMIZE, CONTINUE) som zaviedol aj 4-pismenove skraty (rand,cont).

Niektore tokeny (and,or,not) mozu byt v konflikte s logickymi operatormi asembleru, tam som pridal 'x' na koniec nazvu (andx,orx,notx).
Takze pokial sa vam na nejaky token vypise nejaka chyba (undefined a pod.) najlepsie je sa pozriet priamo do BasicLib ako je tam dany token napisany.
A pre pokrocilejsich programatorov isto nebude problem pripadny konflikt vyriesit vlastnou zmenou definicii priamo v BasicLib :)

Ak potrebujete v ramci projektu vytvorit viac basicov, potom INCLUDE BasicLib staci iba raz, ale pre dalsie basicy je vhodne (ale nie nevyhnutne)
definovat zaciatocny riadok, napriklad line_number = 10 aby riadky roznych basicov nesli pekne po sebe ako keby to bol jeden velky basic.
Kód:
  INCLUDE  BasicLib.asm
;Basic 1
  LINE : db bright : NUM 1 : LEND
  LINE : db print,'"Hello world"' : LEND
;Basic 2
line_number = 10
  LINE : db bright : NUM 1 : LEND
  LINE : db print,'"Goodbye world"' : LEND
A na uplny zaver len znovu zopakujem to co uz napisal mborik vo svojom prispevku: Ak by sa vam niektore tokeny bili s inymi labelmi ktore mate v kode, a nebude sa vam chciet konfliktne labely kompletne predefinovavat, pomoze ak cely basic vratane INCLUDE zabalite do modulu:
Kód:
  MODULE moj_basic
  INCLUDE BasicLib
  ....
  ENDMODULE
Len v tomto pripade si dajte pozor, ak definujete nejaky label v ramci tohto modulu a chcete ho pouzit mimo modulu, potom je potrebne aby ste pouzili label v tvare Nazov_modulu.nazov_labelu. Napriklad:
Kód:
  MODULE MOJ_BASIC
  INCLUDE BasicLib
  ....
goto_here = line_number
  ....
  ENDMODULE
  ...
  ; Kod mimo modulu s basicom:
  ld bc,MOJ_BASIC.goto_here


Nahoru
 Profil  
 
Zobrazit příspěvky za předchozí:  Seřadit podle  
Odeslat nové téma Odpovědět na téma  [ Příspěvků: 4 ] 

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 1 návštěvník


Nemůžete zakládat nová témata v tomto fóru
Nemůžete odpovídat v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete přikládat soubory v tomto fóru

Hledat:
Přejít na:  
Založeno na phpBB® Forum Software © phpBB Group
Český překlad – phpBB.cz