Virtuális gép, Assembler, távirati stílusban [VI. Why Not? [UPDATED!]]

Fordulóponthoz érkeztem. A mai nap hajnalán befejeztem az ASM & VM fejlesztését.
A produktum a végére még nevet is kapott. Why Not Assembler 'n VM lett belőle.

why not assembler

 

Apró igazításokat eszközöltem az asm-en és a VM-en is. Ezek:
-- Az ORG direktíva és annak szerepe már ismert. A főprogram címét jelzi.
Ha valaki a JMP-ot 00-val paraméterezi, akkor a JUMP utasítás az ORG címére (ez a főprogram belépési címe) ugrik és az a mellékhatása, hogy nem írja ki a stack-be azt a címet, ahonnan el-jump-olt. Ez a feature kb. egy main loop felépítésére használható. 
-- A másik változtatás a hex adatbevitel lehetősége a forráskódban. A formátum $00 .. $FF.
-- A label-ek kiértékelése valamivel korrektebb lett.
-- A harmadik és egyben utolsó változtatás a VM disassemblerében van. Ez ki lett bővítve, informatívabb lett, mutatja a konkrét memóriahelyeket vagy ugrási címeket.  Ezzel vége is az újítások sorának.  A frissített forrás alább a régi címen elérhető.

Innen már a régi blog tartalom következik:

Néhány változtatást ezen kívül is eszközöltem.

Ezek: Címkék, ORG direktíva és Compare Flag.

- a címkék formátumáról korábban írtam,  #n:
Ahol n egy decimális szám nullától kilencig (0..9). Tehát a címkék száma max. 10 lehet, viszont,  akár a programjaink elején is elhelyezhetők.

- ORG. Ez jelzi az assemblernek, hogy mi a programunk belépési pontja. Magyarán, honnan kezdődjön a program-végrehajtás. Ez a cím eddig fixen a 10h volt, vagy a memória méretének negyede+1.
   Igy, az ORG használatával megspóroltam egy jump-ot a paraméterével  együtt (ez két byte space) és ezzel az ugrási cím kiszámításának keserve is a múlté.  

   Érdemes tudni, hogy a programjainkat úgy kell szerveznünk, hogy legfelül kell legyenek a DAT-ok, azok alatt pedig maga a progi, aminek elején foglalhatnak helyet a szubrutinjaink, valahogy így:

#0:
LDA 01;
SUB 02;
STA 10;
RET;  

Erre a szubrutinra való hivatkozás a főprogramból (máshonnan nem ajánlott) a 

JMP #0;   vagy feltételesen a

JZR #0;   sorral történhet.

Ez alatt - tehát a szubrutinok legvégétől kezdődően - helyezkedik el a főprogram. Fontos, hogy a főprogi kezdete elé az

ORG;

direktívát és persze az ORG mögé a sorlezáró karaktert (pontosvessző) SOHA NE felejtsük el beilleszteni. Ez 'súgja meg az assemblernek, hogy hol is kezdődik a fő-programunk.

- A stupid 'disassembler'-ről már ejtettem szót.

- A CMP utasítás körüli dilemma (IV. részben olvasható, Hiéna-nak ezúton is külön köszönet) megnyugtató feloldásáig ilyen rövid idő alatt nem tudtam eljutni, viszont, mivel az igéretemmel (ezen sorozat) való vergődés sem tarthat örökké, így végül arra jutottam, hogy eredeti szándékom ellenére, mégis csak kap a masina egy Flag-et.
   Tehát, a korábbiakkal ellentétben annyi a változás, hogy az ACCU és a MEM[n] cím tartalmának összehasonlítása után, ha a két érték egyezik, akkor az ACCU tartalmához a gép -korábbiakkal ellentétben- nem nyúl, hanem egy Flag állapotával jelzi a komparálás eredményét. Ha egyezés van, akkor TRUE (1) a Flag, ha nem, akkor marad FALSE (0). A CMP utáni JZR utasítás nullázza ki a Flag-et ha azt 1 (TRUE) állapotban találja (mivel a JZR csak ekkor fut le).

Hogy a Flag miért nem bool tipusú, az maradjon orvosszakmai titok. Akinek nem tetsz, az majd átírja, ha akarja.

Még egy jó dolog: Az ASM által generált memória-kép fájl tartalma maga a memória tartalma.
Ez a stack, az adat és a kódszegmens, plusz az Fh címen a kimeneti port.
    A stack (ami ugye a MEM[00]) ebben a fájlban mindig üres volt. Ezért ezt felhasználtam és a program belépési címe van eltárolva ezen a byte-on.  Ez a byte be is töltődik a VM-be, futás előtt megkapja az értékét az IP és ezen a címen indul el a végrehajtás (főprogram!).     

A Why Not Assembler és VM forráskódja az alábbi két címen található és tölthető le:

https://pastebin.com/BzizriFh       (Why Not Assembler 1.1)

https://pastebin.com/2eRQGYCv  (Why Not VM 1.1)

Megint a lusták jártak jól, nem kell nekik gépelniük.  A fordításhoz a http://www.freepascal.org  fordítója szükséges.

-------------------------------------------------------------------------------------------------------
Egy, a fordítást és futtatást menedzselő batch file tartalma:

fpc.exe wnVM.pas      >out.txt
fpc.exe wnASM.pas  >>out.txt
del *.o
wnASM.exe < first.prg   first.bin
wnVM.exe first.bin  > output.txt

--------------------------------------------------|
a first.prg file tartalma:

Why Not?

és a kimenet utolsó három stációja:

    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0  22 14 06 0A 03 00 00 00 1A 07 00 00 00 00 00 00 
1  AB 01 AD 02 BA 08 FF AB 03 AA 04 BA 09 FF EA 10 
2  EA 17 EA 3F 00 00 00 00 00 00 00 00 00 00 00 00 
3  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

   Accu: 07  Ip: 1B  Flag: 0 Instr: ACCU <- MEM[09]
---------------------------------------------------| 9
    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0  22 14 06 0A 03 00 00 00 1A 07 00 00 00 00 00 00 
1  AB 01 AD 02 BA 08 FF AB 03 AA 04 BA 09 FF EA 10 
2  EA 17 EA 3F 00 00 00 00 00 00 00 00 00 00 00 00 
3  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

   Accu: 07  Ip: 1D  Flag: 0 Instr: RETURN to 22
---------------------------------------------------| 10
    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0  24 14 06 0A 03 00 00 00 1A 07 00 00 00 00 00 00 
1  AB 01 AD 02 BA 08 FF AB 03 AA 04 BA 09 FF EA 10 
2  EA 17 EA 3F 00 00 00 00 00 00 00 00 00 00 00 00 
3  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

   Accu: 07  Ip: 22  Flag: 0 Instr: JUMP to 3F
---------------------------------------------------| 11
    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0  24 14 06 0A 03 00 00 00 1A 07 00 00 00 00 00 00 
1  AB 01 AD 02 BA 08 FF AB 03 AA 04 BA 09 FF EA 10 
2  EA 17 EA 3F 00 00 00 00 00 00 00 00 00 00 00 00 
3  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

   Accu: 07  Ip: 3F  Flag: 0 Instr: PROCESS Outrun
---------------------------------------------------| 12

Hozzászólások

Ez jól hangzik, tetszik.

Jöhet a fejlesztési igény?

Az ADD és SUB ne csak a Zero flaget állítsa be, hanem egy-egy biten jelezze azt is, hogy volt-e túlcsordulás előjeles illetve előjel nélküli értelemben.

Hasonlóan a CMP is jelezze az egyenlő mellett, hogy előjelesen kisebb-e illetve előjel nélkül kisebb-e.

Szívből örülök, hogy tetszik és köszönöm a tetszésnyilvánítást, ahogy a közreműködésedet is.
Minden más jószándékú ember közreműködédét is köszönöm.

Eredetileg úgy saccoltam , két-három napot igényel ez az egész

- ezért is íram  "távirati" stílust, amitől végül eltekintettem -

ehelyett egy hete ezzel foglalkozom és a tennivalóim csak torlódnak.  Ahogy írtam is, a dolog fejlesztését ma hajnalban lezártam.  Később (nem holnap) lesz egy afféle kalauz, amely a kezdőknek segít a programozásban, meg talán még a periféria illesztésre, kezelésre is példát ad, de azzal részemről ennek a sorozatnak vége. 

Ha bármi változtatást szeretnél,  azt, a forráskód birtokában, magadnak kell megejtened. *
Egyszerűen, nincs rá több időm.
Kérem szíves megértésedet.

* Ez vonatkozik az esetleges javításokra is, mivel a bővítésről szóló részben említett három utasítást (SWP, INC, DEC) ugyan beillesztettem, de idő hiányában nem teszteltem. Ez vonatkozik a label-ek címének beolvasására is, ott is elkelne némi hibakezelés. A label második (szám-ként elvárt) karakterét validáltatni kellene a numeric függvénnyel. 

Csak eljutunk az 1970-es évek végi kisprocesszorokig.
  - Zero flag
  - Carry flag
Jól kifundálták annó az elődök.

Nem kizárt hogy hamarosan jön ennek a témának a nyomdokán egy nagyon alap Forth-jellegű proci is. Addig is lehet gyakorolni:
$ gforth

: köb DUP DUP * * ;     \ lehet akár több sorban is írva. A : és a ; a lényeg.
3 köb .
4 köb .
3 köb 6 köb SWAP / .

Mellesleg a gforth szintén Forth-ban van írva.

Azt kérdezted: kit érdekel ez ilyen szinten?

Látod.  Néhány órája tettem fel az utolsó  írást és itt 120 látogató, a pastebin-ről meg több mint félszázan töltötték le, vagy legalább néztek bele a forrásba. 
 

Eddig annyit számoltam ki az ujjaimon, hogy az előjeles számításnál az előjelbitetek (MSB) kell nézni.
Legyen A+B=C, A-B=D, akkor

Ha A_MSB=B_MSB és A_MSB<>C_MSB, akkor az előjeles összeadás túlcsordult;
ha A_MSB<>B_MSB és A_MSB<>D_MSB akkor a előjeles kivonás túlcsordult
 

Előjelest az egyszerű hardver még nem támogatott, ezt szoftverből a hardveres megoldáshoz hasonlóan a 2 eset vizsgálatával és N-1 bites számmal műveletet végezve az alábbi szerint is csinálhatod:

1. szeparálod az előjelbiteket (legfelső), oda nem csordulhat rá eredmény. A legfelső bitet szoftver esetén kinullázod (hardver szeparáltan kezeli, nem vezeti ide a carry-t).
2. előjel azonos (xor --> 0), akkor összeadod. Ha a felső bitre 1 kerül, akkor carry 1.
    előjel eltér (xor --> 1), akkor kivonás lesz. Ha a kivonás a legfelső bitet 1-re dobja, akkor carry 1.
3. előjelet visszaírod szoftver esetén.

Ha már belementünk a flag-ekbe: digit carry megvan?
Ösök bölcsessége +1 bitnyi regiszterért.

csak nekem furcsa, hogy az ami itt "jmp" azt regen "call" -nak hivtak ?

HUP te Zsiga !

bocsi, hogy nemolvastam az elozmenybejegyzeseket.

mielott potolnam, ezen sor azert meg belevert egy szoget a koporsom helyett a fejembe :

" legfeljebb, ha nem akar valaki visszatérni, akkor majd jó erősen kerüli a RET használatát és kész. A köv ugrásnál  felülíródik a stack? Mint a vihar! "

 

akkor ez egy 1 elemu "stack" ?

HUP te Zsiga !