z80 assemblert keresek linuxra

Parancssoros z80 assembler cross-compiler-t keresek. Jó lenne valami high-assembler szintű de legalábbis jó makrókezeléssel, hibareportolással. Az pedig hab lenne a tortán, ha képes lenne több parancsot is értelmezni egy sorban.

Amiket eddig próbáltam:

z80asm: hibás kódot is lefordít hibaüzenet nélkül, makrókezelése kezdetleges, akár fordítási időbe is belefagy, ha nem tetszik neki. Hibákat néha arra a fájlra jelzi, amiben van, néha arra a fájlra, amelyik include-dal használja, emiatt elég nehézkes.

crasm: nem tud bináris include-ot (legalábbis én nem találtam)

pasmo: a konstan kifejezéskiértékelése nem tud zárójelezni (a z80asm ebben elég jó), a lokális címkéket csak blokkon belül képes értelmezni, fájlon belül nem. (Ráadásul nem a . karaktert kezeli lokálisnak, mint más fordítók.)

zasm: bináris inlcude-ot ebben sem találtam. A többi tulajdonságában emiatt még nem mélyedtem el.

Eddig a pasmo a leginkább használható, de a lokális címkézése nehézkes. A perl féle objektumkezelés fájl szintű lokális címkézéssel kényelmesebb lenne. A konstans kifejezések külön nevesítése is felesleges körökre kényszerít.

Ha van ötletek, tapasztalatotok, szívesen olvasnám.

Hozzászólások

========================= Name & Summary Matched: z80 ==========================
vim-syntastic-z80.noarch : A syntax checker for z80 programming language
z80asm.x86_64 : Z80 Assembler
z80dasm.x86_64 : Z80 Disassembler
============================= Summary Matched: z80 =============================
d52.x86_64 : Disassemblers for 8051, 8048, and Z80 families
sjasm.x86_64 : A z80 cross assembler
tilem.x86_64 : Emulator and debugger for Texas Instruments Z80-based graphing
             : calculators
z88dk.x86_64 : A Z80 cross compiler

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Talán a zmac segíthet, de -- ahogy a leírásban szerepel -- le kell fordítani.

http://48k.ca/zmac.html

"Share what you know. Learn what you don't."

Esetleg a makró kezelést külső preprocesszorral meg lehetne oldani. Pl. cpp ha az assembly szintaxis engedi vagy akár yaha + jinja2.

Szerintem túl nagyok az igényeid. A Z80-ashoz nem nagyon írtak macroasm-et. Lévén, hogy a hardver szerény volt, azon még nem ment ilyesmi. Ez az x86-os világ találmánya lett később, ezt próbálod visszavetíteni a Z80-ba. Így ha Z80, akkor maradnod kéne a klasszik low level assemblereknél, és megtanulni boldogulni azzal.

Ha magasabb szint, meg makró kell, akkor inkább C-vel menj neki, SDCC vagy Z88D-k.

The world runs on Excel spreadsheets. (Dylan Beattie)

Az assembly macro nem az x86 világ találmánya. https://en.wikipedia.org/wiki/Assembly_language

• Sophisticated macro processing (although available on ordinary assemblers since the late 1950s for, e.g., the IBM 700 series and IBM 7000 series, and since the 1960s for IBM System/360 (S/360), amongst other machines)

A vasm egyébként tud makrókat is, meg régi 8-bites szintaxist is.

Ezen igen szomorúan felnyerítettem.

Maradva az akkori család(ok)nál:

Intel Isis-II -> asm80 + link + locate = 8080 és 8085 macroassembler (link)

Macro 80 -> m80 + link80 = 8080 és z80 macroassembler (link)

A két fordító hajszál híján tökegyforma és a std macro eszköztárat tartalmazza.

Ha magasabb szint, meg makró kell, akkor inkább C-vel menj neki

Sajnos így van ez. Manapság jobbára olyanok írnak asm fordítót a C++-tól kezdve a java-ig, akiknek fingjuk nincs a std makró mibenlétéről. A C makrók teljesen másra használhatók. Egy asm fordítóba keverve  pontosan olyan, mintha sql parancsokkal és lengyel logikával írnál bash scriptet. Érdekes módon az akkori assembler fordítókat assemblerben írták. Vagyis aki meg tudta írni, az használni is tudta. ;) Sőt, hibátlanul is meg tudta írni.

A 8080-ra készült Isis-II rendszert (!) 8086 vagy v20 gépen emulálta az i80 program, illetve a v20 tudott natív 8080 módot. A locate sajnos nincs a mai fordítókhoz. Ha írtam egy 10 modulból álló, epromból (0 címtől) futó programot, akkor pl. 3 modul elkészülte után tudtam hozzá használni a szimbolikus debuggert. A modulokat lefordítottam, linkeltem, majd (re)lokáltam a debugger munkaterületére. Ha elkészült az összes modul, akkor lokáltam a 0 címre és besütöttem az epromba. Ilyen vagy hasonló funkciókat csak a sokkal későbbi fejlesztőrendszerekben valósítottak meg.

Mindegy, akkor elismerem, hogy tévedtem. Találtatok nagyítóval egy speciális kivételt az ősidőkből, amiben van valami makró, ami nem is biztos, hogy jó lesz a kérdezőnek, vagy tudja mindazt, amit akar. Ennek ellenére nem „csak azért is alapon”, hanem mert tényleg így van, mindig tartom, hogy a topiknyitónak elszálltak az igényei. Akkoriban, mikor ezek a platformok uralkodtak, akkor nem voltak ilyen nyikhaj kényelmi megoldások, hogy bazi nagy IDE-k, mindenféle makrócsínyek, meg linterek, language server-ek, stb., debuggerek is primitívebben voltak. A nem voltak részt külön kifejtve: nagyítóval lehet találni valami kivételt, amit a NASA vagy a Cray vagy hasonló volumentű cég használt, nem az átlag fejlesztő Pisti az irodai/otthoni átlagos gépén, floppy-ról, magnóról meg lyukszalagról betöltögetve. Ahogy most is, akkor is az volt a felállás, hogy a legtöbb embernek ugyanaz a 2-3 féle gépe volt, ami mainstream el volt terjedve, és boltokban megfizethetően kapható volt, és ugyanez volt a szoftverekkel is, 2-3 népszerű compiler és assembler volt elérhető az átlagembernek, és 99,999%-uk ezt használta. Ha más nem azért, mert ehhez fértek hozzá, mert vagy ezt tudták megvenni, vagy az ismerősi körből, hobbikörből kölcsönkérni, lemásolni, lewarezolni, stb.. Ne feledjük, akkor még nem nagyon árultak a boltok ilyet, és nem volt internet se, hogy letöltögesse az ember fia.

Ez egyébként most sincs másképp, a fejlesztők 99,99%-a kb. ugyanazt az elterjedt fordítókat használja javarészt, Visual Studio, gcc, llvm és kész. Igen, biztos van, aki egzotikumokat használ, de azt nagyítóval kell keresni, és senki nem követi őket ebben. Asseblerből nem is tudom mit használnak most x86-on a nyikhajok. Ha most nekem ilyen kéne x86-hoz, a GNU as-szel mennék neki, de csak azért azzal, mert arra emlékszem, és tudom, hogy bármelyik disztró repójából elérhető, külön hekkelés, meg extra tárolók felvétele nélkül.

Ma már tuti lehetne írni persze modern Z80 assemblert, lehet valamelyik tudja is, amit a kérdező akar, nem tudom. De tipikusan nem sokan fognak ilyet írni, mert ha modern assembler írásába fog valaki, az jó eséllyel modern platform lesz, ha meg 8080-ra, vagy Z80-ra kell, akkor meg használja valamelyik legacy assemblert, annak minden korlátjával együtt.

Egyébként én sose voltam a makrók híve assembly-ben. Mindig is csalásnak tartottam, és ha ASM-et használtam (csakis x86-ot ismerem, azokat is DOS-on használtam, MASM, TASM, NASM, épp azt, amihez hozzáfértem az épp aktuális gépen), abban mellőztem, megírtam hagyományos címkékkel és CMP, JZ, stb. utasításokkal, már csak azért is, mert akkor nagyobb eséllyel megette a kódot a többi assembler is. Ha ennél magasabb szint kell, akkor szabvány C. Az szintén elég low levelnek számít ma már, sokan emiatt nem is szeretik, nincsenek benne mindenféle magasabb absztrakciók, meg hülyebiztos védelmi mechanizmusok, amik megfogják a hibákat.

The world runs on Excel spreadsheets. (Dylan Beattie)

Találtatok nagyítóval egy speciális kivételt az ősidőkből, amiben van valami makró, ami nem is biztos, hogy jó lesz a kérdezőnek

Ez nem egészen igaz. Ha úgy tetszik, ezek az ősidők processzorai. Akkoriban még a gyártók megfelelő eszközöket biztosítottak és mindenki azokat használta. Nem volt millió féle opensource félig elkezdett program, mint manapság. - Sokan belekezdenek valamibe, aztán kiderül, hogy túl nagy falat a feladat. ;) - Emiatt nem nagyítóval kellet keresni, mert rendelezésre állt és akkoriban ezekkel az eszközökkel dolgoztam. (Ha úgy tetszik, ősidőkből származó ősember vagyok, mert 40 éve programozok assemblerben. :-D)

A kérdező nem igazán fogja az assembly mibenlétét. Az assembley nem más, mint mnemonic -> gépi kód. Ebből nem lehet "ha képes lenne több parancsot is értelmezni egy sorban" szintaxist kihozni. "Jó lenne valami high-assembler szintű de legalábbis jó makrókezeléssel, hibareportolással." vs. "z80asm: hibás kódot is lefordít hibaüzenet nélkül, makrókezelése kezdetleges". WTF high-assembler? A z80asm béta, már tartalmaz a magasabb szintű nyelvekből származó számábrázolást, tehát "osztályidegen". A macroassembler kezeli a std makrókat, de mi az a "jó makrókezelés"? Ilyet csak Columbó felőgyelő mondott a döbbent hallgatóságnak, mikor javasolták, hogy vegyen másik autót:

Van másik autónk, de azt a feleségem használja - csak bevásárlásra jó.

Szóval egy fordító lefordítja a kódot, a makrókat és hibát jelez, ha hibás a kód. Nincs "hibareportolás", mert a kétmenetes fordításból adódóan vagy meg tudja jelölni a hibás sorokat, vagy a verikális struktúrát érintő hibánál kiszáll.

Amit a "std" makrókezelésként nevezek a következőt tartalmazza: MACRO,  ENDM,  LOCAL,  REPT,  IRP,  IRPC, EXITM. Persze egyéb nyelvi támogatás sem árt, pl.: IFB, IFNB, IF1, IF2, stb.

Mondhatnánk, hogy a REPT -> for, IRP -> while, de az IRPC hiánya sok irkafirkát eredményez. :( Bizony, ez van, ha valaki C aggyal próbál assemblert írni. Mint említettem, a "modern assemblerek" hátránya a modern gondolkodás adta kontraszelekció: A sok új fícsör mellett eltűnnek azok a funkciók, amit a hozzáértők - nem véletlenül - beleraktak.

A makró nem az ördögtől való. Ismétlődő műveletsort, adatdefiníciót lehet rövidíteni, de ami  a legfontosabb, megkönnyíti az olvashatóságot.

Írtam egy Wyse60 terminált, amelyben jópár klaviatúra map-et kellett definiálni. A fordító TASM és volt XMS, EMS, valamint speciális alaplappal és DRDOS használatával 890kB DOS memória. A makrók miatt éppenhogy lefordult!

Ami érdekes számomra az incbin. Lehet ilyet is, de nem törik le a keze senkinek, ha egyszer forrássá alakítja pl. a képeket. Pach esetén - ha már linux - tudom ajánlani az awk + xxd kombót. Nekem működik. ;)

Ebben kicsit szemellenzős vagyok, mert szinte mindig abszolút kódot írok, az obj az másra való.

The BINOBJ command converts the absolute binary format of earlier versions  of
ISIS to the object module format of ISIS-II.

Sőt, pont fordítva ül a paci: .bin -> .inc (azaz .asm)

Így aztán - megszokásból - a pici webszerver-szerű programba a flavico.ico -> flavico.h átakakítással került bele, a 3800 sorból 800 soros flavicon. ;) Sőt, a weboldal (html) is .h-ba került. (De ez C meg linux és AIX.)

A patch az más. Már az őskorban is volt Intel HEX vagy Motorola S formátum. Az előbbit a PIC-hez is használják. A *nix környezetben a patch a HEX-be kerül, mert nem csak awk, xxd, de openssl és rhash is szükséges hozzá. Valódi bináris formátum gyártás közben nemigazán fordul elő, így a patch útvonala: text -> bin -> text -> HEX. (Vagy valami hasonló.)

awk-ot és xxd-t használom, csak másra (az xxd-t szótárak adatformátumainak az elemzésére főleg, az awk-ot shell scriptekben mezőkiválogatásra), és nem együtt. Csak ASM-et nem használtam már régóta, pedig anno szerettem, nagy ASM fan voltam, de mára megváltozott a véleményem, és inkább az elegáns magas szintű kód és a portolhatóság híve vagyok, nem az ASM-ben szétoptimalizálásé, és az egy architektúrához kötöttségé. Ahogy nézem, alap gcc telepítéssel jön az GNU „as”. Még mindig tartom, hogy nem sok értelme van makrózni ASM-ben. Kényelmes, elhiszem, de az ASM-nek pont az a lényege, hogy low level kódot írjál, minden utasítást te válassz meg, és ne bízzad magadat makrókra, még egy ciklust vagy feltételes ugrást se. Mondom, ha ez az igény, hogy IF1, IF2, akkor C-t kell használni, az is csak épp annyira high level nyelv, hogy még lényegében egy ASM fölé húzott makrógyűjteménynek felel meg majdnem hogy, és ott lesz a compiler, ami hibás kód esetén nagyobb eséllyel bevonyíthat.

The world runs on Excel spreadsheets. (Dylan Beattie)

Elég szoftveres az észjárásod. ;)  Ez nem baj, viszont a szoftveresek már 40 éve sem értették a hardvert.

Itt egy egyszerű "vegyes" awk függvény, amely eg 64 karakter hosszú (128 hex) stringbe (ami 0000ff... kezdetű), felülírja az ff-ek első 4 karakterét a little endian sorrendű crc32-vel.

function getcrc(hexstr)
{
    mkcrc=("echo -n" hexstr "|xxd -r -ps -l 128  | rhash -p %c -")
    mkcrc | getline crc
    close(mkcrc)
    crcle=( substr(crc,7) substr(crc,5,2) substr(crc,3,2) substr(crc,1,2) )
    sub(/ffffffff/,crcle,hexstr)
    return hexstr
}

A script az Intel HEX formátumú firmware-t látja el egyedi azonosítókkal és kulcsokkal gyártás közben.

No, akkor portoljunk egy kis assemblert is! A legutóbbi munkám egy 7 éve, két cég által gyártott termék portolása volt: Az MCU ára >2,5x lett, csak nem lehet kapni. Az analóg nyomásmérő (termékenként 4db) ára 6x lett (2€ ->12€).

A program a PIC18 család egyik tagjára készült. A kiválasztás szempontjai: SSOP28 tokozás (kisebb nem létezik és csak ez fér el), USB, >=2k RAM és lehet kapni. A kód könnyedén átírható 16 bitesre, de a PIC24 sem kapható és drágább is. Marad a beszerezhető 8 bites. A portolás alapfeltétele a legalább 1 éves gyártáshoz szükségees mcu készlet beszerzése!

A drága analóg nyomásmérők helyére egy 2€ árú integrált került, így az ADC helyett SPI+DMA használatával lehet kiolvasni.

Az USB driverbe kellett néhány utasításnyit belenyúlni, mert másik lapra kerültek a descriptorok hw pointerei. A vezérlő interfész és AES256 változatlan. Nem lévén EEPROM, a mérést engedélyező és a host azonosító kulcsok kezelése teljesen új lett és a flash-be került, az adatblokkokra meg crc. A nyomásmérők kiolvasása eldobva és újraírva az analóg -> spi miatt. A 10->24 bites adat miatt az adat interfész is megváltozott.

Az elkészült kód <8kB, amihez jön még 6kB adat/táblázat + 1,5k tesztelésre használt adat. Az utóbbi arra való, hogy a szoftver elkészülte előtt is lehessen tesztelni, mert a szoftveres kolléga építkezik. :-D

A kód mérete megfelel annak, hogy a 16, 32 és 64kB flash esetén még a legkisebb családtagba is belefér. Ti. olyan eszközzel folyik a gyártás, amit éppen sikerül beszerezni.

Felülről nézve a kód újrahasznosított része hordozható volt. A megváltozott feladat részt és a HAL-t (nevezzük így) meg kellett írni illetve módosítani. Ez C-ben sem működik másképp.

Az assembler nem arra szolgál, hogy "szétoptimalizáld" a kódot. Mindössze pontosan azt írom le, amit szeretnék csinálni. Ehhez nem kell kitekerni a C nyelv adta lehetőségeket. (Használd mindig a legfrissebb libet! - Mivan? Az USB drivert megírtam egyszer, azóta működik.) A hardvernél nem az optimalizálástól lesz gyors a kód, hiszen az idő 90%-ában nem történik semmi. Viszont nem kell rojtosra debuggolnom a szememet, hogy más mit rontott el. ;)

Ami a legfontosabb: Hardvert programozok, amit egy >500 oldalas adatlap ír le. Az assembler kódban az adatlapban szereplő a neveket használhatom és nem kell kitalálnom, hogy mire gondolt a költő vagy hogyan fogalmazta meg a C-ben leírhatatlan dolgokat., amit az adatlap ír le.

Eccerű kis makró (itt alkalmazása): Ugrótábla. A kód olvashatóbb, a tábla egy mozdulattal átírható near->far értékre, tehát az írást is megkönnyíti. Belül pedig a cjump vagy cjump2 (computed jump) hívását és a bra vagy goto használatát variálja.

	JumpTbl		near
   	JumpTo		Search_First
	JumpTo		Search_0
	JumpTo		Search_F
	JumpTblEnd

Másik: Gyakori 16 bites műveletek 8 bites processzorra. Ebből persze van egy csokor. Olvashatóbb, kevesebbet kell írni, kevesebbet lehet téveszteni és nagyon könnyű átírni 16 bitesre a kódot.

ldPtr16		macro		Ptr, SFRpair
		movlw		low Ptr
		movwf		SFRpair, a
		movlw		high Ptr
		movwf		SFRpair+1, a
		endm

Ha már van #define: Alatta a C-s förmedvény, csak azt nem értem, hogy miért nem elegendő az RB7=1. Ja, mert a bitfield az absztrakt. ;)

#define		TRIGGER		LATB, 7, a
...
		bsf	TRIGGER

LATBbits.RB7= 1

Van amikor nem teljesen lehet leírni a szerkezetet C-be, vagy a C-hez értők nem értik a processzort. Pl. egy 16 bites indexregisztert és az alsó-felső bájtját is meg tudom címezni anélkül, hogy uint16+uint8+struct+union segítségével írnám le. Ha hülyeséget írok, azt egyik compiler sem fogja észrevenni.

nekem túl risc

Hát, RISC jellemzői:

  • sok regiszter, mellékhatásként C fordító számára szerethető architeltúra
  • dstreg src1reg src2reg alapú 3 regiszteres műveletek. Vesd össze CISC-nél jellemző a 2 regiszteres, ahol az egyik src+dst szerepet is ellát.

A klasszikus PIC szegény utasításkészletű, de nem RISC architektúra.

Ez alapján valóban nem RISC, de a sok regiszter azáltal megvan, hogy a címrész az opkód része. Teljesen meg voltam rémülve régen, hogy csak CALL, RETURN stack van, nincs adat stack, nincs PUSH, POP, jaj, mi lesz, mind meghalunk, de aztán nem, mert amiatt, hogy bárhova lehet címezni, nem kell menteni. Ha véletlenül kell, azt is egy bárhol elhelyezkedő címre meg lehet tenni. Meglepően hatékony PIC-re assembly kódot írni a kevés utasítással. Hatékonyabb, mint Z80-ra a maga bloat, CISC utasításkészletével.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

a sok regiszter azáltal megvan, hogy a címrész az opkód része.

Ez hajaz olyan VLIW elvekre, amelyben a hosszú utasítás bitjeinek egy része a memória legalább egy részének illetve memóriába ágyazott I/O címzésére szolgál.
Egyetlen nem elhanyagolható probléma ezzel ahogy említetted is, hogy nincs lehetőséged függvényhívásnál a regisztereket stackbe menteni és a függvényhívás végén visszahozni (push, pop). Ez nem barátja a C fordítónak. Illetve az indexelt címzés sem CPU-ból jön, hanem memóriába ágyazott I/O módon, mint célhardver lett implementálva. Használható, de látszik hogy szűkös a CPU-ban levő indexelt címzés lehetőségéhez képest és szintén nem barátja a C fordítónak.

Egyébként ha már itt tartunk, a harmadik csoport a verem gépek. Ez sem lett a számítástechnika megmentője, de tényleg egy olyan kuriózum, amit érdemes megismerni. Vele együtt a FORTH nyelvezetét.
Érdekesség, hogy kezdetben a 8087 floating point társprocesszor is veremgép-elven lett felépítve. Az is egy érdekesség, hogy az x86 AVX utasításkészlete már RISC elveket követ.

Amennyire én emlékszem, az ilyen esetekben a C fordító alapból "kisajátít" egy regiszter készletet.
Akkor foglalkoztam vele, amikor az ATMEGA16-ra írtam C és assembly vegyeset, alapvetően az interrupt rutinokba, hogy ne kelljen PUSH/POP-olni más regisztereket használtam - működött.

Egyébként dolgoztam olyan fordítóval is i386 aminek elő lehetett írni, hogy regiszterekben adja át az eljárások paramétereit és a visszatérési érték is regiszterbe ment (TopSpeed).

* Én egy indián vagyok. Minden indián hazudik.

Az avrgcc-nek elvileg meg lehet mondani, hogy fixen allokálsz magadnak regisztereket, és akkor azokhoz nem nyúl. Én még nem csináltam ilyet, azért macerás, mert minden kódot újra kell fordítani így ebben az esetben, a gyári libeket is.

x86 alapon többféle függvényhívási szabályrendszer is van, a regiszteres gyakori volt. Az ARM-eken pedig alapból ez a standard, hogy regiszterekben vannak a paraméterek és a visszatérési érték. És van olyan regiszter, amit a hívott félnek nem kell menteni, így az egyszerűbb függvények RAM elérés nélkül is megvalósíthatóak.

Az ARM-eken pedig alapból ez a standard, hogy regiszterekben vannak a paraméterek és a visszatérési érték. És van olyan regiszter, amit a hívott félnek nem kell menteni, így az egyszerűbb függvények RAM elérés nélkül is megvalósíthatóak.

Ez az AVR-nel (avr-gcc ABI) is igy van, szoval hasznalhatsz olyan sajat regisztereket is mert azt a hivott fel mindig menteni fog hogyha hozza kell nyulnia valami miatt. Lasd itten: az r2...r17 es az Y (r28, r29) regiszterek hasznalata ilyenertelemben "szabad". De igen, az ketsegtelen hogy ez diffuzabb mint az ARM-nel (ott az r4-r7 eseteben kell garantalnia a hivott felnek hogy nem nyul hozza, a felso regisztereknel mar nem emlekszem, ott talan az r12 meg az ami ilyen). RISC-V eseten meg mar a regiszter (alias) neveben benne van hogy mikor kell mentenie a hivott felnek :) 

Lazan kapcsolodik hogy az ARM-nel az ABI es az ISR stack frame indentikus, azaz barmilyen `void funct(void)` fuggveny lehet megszakitas-vektor is egyben es vice verza.

Én úgy értettem a regiszter allokációt, hogy a teljes futás idejére annyira, hogy senki ne nyúljon hozzá, és így ISR-ből is használható változót lehet bele tenni. Teljesen ASM-ben írt programban ugye meg lehet ezt csinálni, C-ben alapból nem, de az avr-gcc-vel erre is van mód elvileg. Én sem próbáltam még, de elvben tetszik.

de az avr-gcc-vel erre is van mód elvileg.

Hm... erdekes, igy elsore nem latok itten ilyesmit... de persze lehet hogy van. Viszont kerdes hogy ha meg tudsz is igy forditani sajat kodot, a libc-beli fuggvenyek ezt pont az ISR-ek szempontjabol elronthatjak. Aztan persze igen, ha mar ott vagyunk hogy a libc-t is ujra kell forditani emiatt akkor mar lehet hogy egyszerubb valami mas trukk ha van ra mod :)

A RISC architektúra az más. Az hogy "kispórolt proci", amely még az indexelt memóriacímzést sem ismeri (külső hardverelemmel valósítja meg lásd INDF és FSR memóriacímek) az nem RISC proci. Ahogy az sem, hogy egyetlen valódi regisztere van és mindenhet memóriába nyúl be. Ennyi erővel a fent említett veremgép is RISC lehetne. Kevés utasítás, főleg PUSH, POP, SWAP, ROT meg külső cím írás és olvasás és mindent szoftveres eljárással bővítesz fel.  :)

A marketing viszont mindent kibír, meglovagolták a RISC szót, mert az jól hangzott a számítástechnikában és risc-nek hirdették magukat.

Hidd el, csak nem vagy tisztában a működéssel!  A "külső hardverelem" bent lakik a processzorban és mint sokszor sok helyen, itt is van olyan elem, ami több címzéssel is elérhető.

Legyen a példa egy utasítás: INCF f,d,a = increment file

Az opkód: 0010 10da ffff ffff

  • ffff ffff = a file cime
  • d = dest = W regiszter vagy file
  • a = BSR (által címzett lap) vagy ACCESS (0. lap 0..5f vagy 60-tól SFR)*

Az AVR8

The ALU supports arithmetic and logic operations between registers or between a constant and a register.
...the operation is executed and the result is stored back in the Register file in one clock cycle.

A PIC

The ALU supports arithmetic and logic operations between (W register and file) or between a constant and  (W register or file).
...the operation is executed and the result is stored back in the (W register or file) in one clock cycle.

Megállapítom, hogy ugyanaz van odaírva, csak  a PIC (register) file szervezésű. Pici processzor, hiába írják, nem haverja a magasszintű nyelveknek. Viszont van egy extended módja, ahol el tudja játszani pl. az FP és BP regisztereket is, akár a 8086. (Csak elég kínos a szoftveresen emulált stack miatt.)

*Nézzük csak a "külső hardverelemet", ami bent lakik a processzorban és a kis neve FSR{0..2} (file select register), ami egyébként ugyanúgy működhet, mint bármelyik másik "file". Tehát lehet inkrementálni, hozzáadni, stb. Ez a három regiszter kb. azt tudja, mint az AVR X, Y és Z regiszterpárja, vagyis dedikált indexregiszter. Ha a fenti utasításban ffff ffff=ef, akkor az INDF0 végzi a címzést (INCF (FSR0), f, a - csak nem így írjuk), míg f9 esetén az FSR0 kisebbik bájtja inkrementálódik (INCF FSR0L, f, a).

Szóval a PIC csak 1 db regisztert használ, amivel megspórolták a register addressing bitjeit (pl. 8080 3 bites), de ugyanazzal az utasítással 352+3 memóriacímet és ~148 (elméletileg) SFR-t tudsz címezni. Ez a 8080 esetén 7 regiszter és 1 indexelt cím. Az AVR jobban támogatja a magasszitű nyelveket, viszont az INC utasítása csak 32 regiszter címzését teszi lehetővé. Tök jó az a sok regiszter, csak néha uncsi megtölteni őket. :-D Ha nem erőlteted a C függvény stack kezelését, akkor a PIC sokkal hatékonyabb.

A "küső hardverelem" esetünkben csak egy map, aminek nagyon egyszerű az oka: Az SFR-ek többen vannak, mint 160, és az access területen kívüli regisztereket be kell lapozni az eléréshez. Persze az ilyenek általában ritkábban használt  regiszterek.

Itt egy link, ami elég jól leírja a RISC kritériumait. Megnézheted máshol is, de ha a PIC nem risc, akkor az AVR sem. Egyiknek sincs pipeline (Az AVR 1 mélységűt ne soroljuk ide!), data cache, instruction cache, sőt még a memóriát sem támogatják. ;) De leginkább egyik sem legalább 32 bites. Viszont a RISC<->CISC viszonylatban pont kiemeli a PIC RISC voltát, miszerint sokkal gyorsabb, mint egy 8086. Ott az a 20 pont, aminek alapján az AVR sem RISC, mégis említik. Ha leszakadnál a C és Rust vonalról, akkor más szemüveggel látnád a világot. ;)

És amit már párszor leírtam: Nézd meg a 8X300-at, ami nem RISC, de signal processor kategória. A fenti idézetek is megállják a helyüket, mert egy cikluson belül a load+data manipulation (De még hogy, 13 bitet használ rá!)+store megy neki. És csak 8 utasítása van!

Lehet, hogy olajoshal? :-D

A PIC18-tól, ha úgy tetszik, 96+1 (sőt sokkal több) regisztert is használhatsz. Tudom, zavar a konkrét hardver implementáció, de talán más processzoroknál csak nem tudod pont hogyan működik. Csak a C fordítót nem kell belekeverni. ;)

Ugyan  írják, hogy C Compiler Optimized Architecture for Re-Entrant Code, de a szoftveresen emulált stack frame nem az igazi. Nem is erre való, hanem inkább vezérlésre. Az adatokhoz nincs PUSH és társai, de a sok regiszter miatt nem is szükséges.

A 3 regiszteres műveletek persze nincsenek, inkább egy egyszerűsitett 8X300-hoz hasonlítanám. Sok utasítás címez, adatot manipulál és betölti vagy visszaírja - ami sok esetben nagy spórolást jelent.

Persze nem kell elszállni, ezek picike processzorok, nem a C fordító és a FP egységek száma alapján kell megítélni őket. ;)

Nincs ezzel baj, teszi amire való. Csak lazán felültettek a jól csengő RISC architektúra távoli nemrokon lovára, hogy ez is az lenne. Lófüttyöt.
Vesd össze AVR8 procival. Nem véletlen, hogy arra lehetett portolni a GCC-t, PIC16/18 családra pedig olyan C fordító kellett, aminél gyakran egy indirekt címzést sem tudsz értelmesen leírni, hanem C-ből kell piszkálnod INDF és FSR nevű memóriacímeket.

Lásd példának az 1990-es években megjelent AVR8 mikrovezérlőt: https://c.godbolt.org/z/q6Mqz1MPx

C-ből kell piszkálnod INDF és FSR nevű memóriacímeket

A választ lásd feljebb. Kifejthetnéd, hogy pl. az FSR0 mennyiben külöbözik az AVR X regiszterétől.

Amit írsz, az utalhat a PIC gyenge C fordítóira, de semmi köze a RISC/nem RISC kérdéshez. Nem tudom mivel akadtál össze, de elég súlyos lehet, ha az egyikhez van X=dst, míg a másikhoz nincs FSR0=dst. :-D

#define RISC: portolható rá a gcc - ezt megjegyeztem. :-DDD

Azt gondoltam, itt majd mindenki a saját, jól bevált fordítóját fogja ajánlani. :) Bár elég "erős" feltételeket fogalmaztál meg itt-ott. :) Esetleg nézz rá a The Macro Assembler AS-ra. Ez ugyan egy rakás (100-as nagyságrend :-D ) architektúrát ismer, de közte van a Z80 is (a nem-dokumentált utasítások is használhatóak, ha kell). Én - jellemzően - 6502 meg 68K targethez használom, de volt Z80-as projektem is vele, "működött". :)

A listádból: bináris inklúd van benne (BINCLUDE :) ), zárójelezés szokott neki menni. Lokális címkék vannak (több fajta is), bár az "egész fájlra érvényes" kitételben nem vagyok biztos, én így sose használtam. (A "globális" címke hatáskörén belüli ".lokális" címkére a "globális.lokális" módon lehet hivatkozni.) Ez a "konstans kifejezés külön nevesítése" nem tudom, mit takar a leírásodban, hogy ez itt ilyen-e vagy sem, azt nem tudom. :)

(Kissé off: amit én nem nagyon bírtam megszokni, az a Z80 (meg még jó pár korabeli CPU) assemblerének a postfix-es számrendszer jelölése. Jellemzően prefixet igénylő szintaxisú kódokat írtam /-ok, pl. a decimális 255 az hex-ben 0xFF vagy $FF. Az itt ugye FFh lenne, de az inkább címkének tűnik, nem számnak, ezért az assemblernek nem is jó, 0FFh-t kell helyette írni (szám az csak számjeggyel kezdődhet). Értem benne a logikát, de na. :) )

"Azt gondoltam, itt majd mindenki a saját, jól bevált fordítóját fogja ajánlani. " Jópofa vagy. Amikor ezzel foglalkoztam tán MS fordítót használtunk CP/M alatt. Itt viszont Linux-ra kell compiler. Az pedig az SDCC.

Viszont, ha jól értem valami régi forrást akar lefordítani.

* Én egy indián vagyok. Minden indián hazudik.

Itt viszont Linux-ra kell compiler. Az pedig az SDCC.

A linkelt darabot én Linuxon használom, az SDCC meg szerintem C fordító, a kolléga meg asszemblert keres. :)

Függőségi gond nekem nem rémlik, csak az, hogy a "stable" verzió annyira ősrégi, hogy azzal nem érdemes foglalkozni, a "latest" (asl-current) lesz a jó. Most lehúztam az aktuális forrást, a könyvtárában van egy "Makefile.def-samples" alkönyvtár. Ebből a "Makefile.def-x86_64-unknown-linux" fájlt visszamásoltam a forrás gyökerébe "Makefile.def" néven, majd egy szimpla make lefordította. Utána egy "make test" paranccsal le lehet tesztelni, hogy minden jó-e.

Ja, a listádból kihagytam: természetesen tud makrót. Sőt, lehet benne függvényeket is definiálni. (Az egyik ismerősöm demókat kódol vele, úgy, hogy a szükséges táblázatokat is jellemzően az asszembler generálja. :) ) De - nyilván - nem erőszak, mindenki azzal szív azt használ, ami neki szimpatikus. :D

"a kolléga meg asszemblert keres" - jogos.

Viszont amikor STM8S programoztam, használtam assembly-t "sdasstm8" - működik :)
Az sdasstm8 a csomag része, feltételezem hogy Z80-hoz is van.

Az ilyen program csomagokat általában lefordítom magamnak, nem az előre gyártott csomagot használom. Mivel hw nem kezelnek általában nem szokott problémát okozni a fordítás.

A gondot valóban a makrók okozhatják, viszont (ha nagyon kell) ezt át lehet hidalni kézileg vagy vlmi szövegfeldolgozó programmal. A makrók alapvetően egy az egyben behelyettesítendő kód részt képviselnek.

Amikor a Z80 volt a CPU a makró még gyerekcipőben járt, ahány assembler annyiféle, és akár ugyanaz a kulcsszó másként működött.

* Én egy indián vagyok. Minden indián hazudik.

Ma sincs ez másként. Azt a PIC-re írt assembly kódot, amelyet az mpasm lefordít, nem tudod lefordítani az xc8 fordítójával. Átírni a forrást nagyon nagy munka, szóval azt csináltam, hogy feltelepítettem a régi fejlesztői környezetet és azzal fordítottam.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerencsére a fordító programok nem hw függőek (annyira) így létre lehet hozni a számukra megfelelő működési környezetet.
(Lehet a CP/M-hez is van szimulált környezet, talán qemu-ban is megoldható)
A lényeg hogy sokkal munkásabb rekonstruálni a "megfelelő" környezetet, lehet megéri újra írni.
Eleve az assembler nem hordozható, a mai beszerzési problémák miatt is jobb a plain C, szinte minden processzorhoz van.
 

OFF: A risk processzorok assembly programozása nagyon munkás, tiszteletem azoknak akik még űzik ezt a művészetet.

* Én egy indián vagyok. Minden indián hazudik.

Re: OFF

Fene tudja. Z80 volt az első assembly nyelv, amelyet megtanultam, aztán programoztam valamennyit 80C32-re, ez ugye a 8051 család a nagyon béna utasításkészletével. Például van 16 bites inkrementálás, de dekrementálás már nincs, azt meg kell írni 8 bites utasításokból.

Aztán sokat programoztam kis PIC-ekre assembly-ben, és nagyon meglepődtem azon, hogy a kevés utasítás és az adat stack hiányának ellenére mennyire hatékonyan lehet programozni. Ugye Z80-on volt nem túl sok regiszter: AF, BC, DE, HL, SP, IX, IY, AF', BC', DE', HL', IR, PC. Fejből írtam, ha valami kimaradt, akkor kopnak az emlékeim. Mivel mindenhez ezeket lehetett használni, gyakran kellett menteni és visszaállítani, ezért kellett sok PUSH és POP.

Ezzel szemben PIC-ek esetében az opkód tartalmazza a címrészt is, így a memória egy lapja közvetlenül címezhető, tehát lényegében az egész RAM egy nagy szelete látható regiszterként. Meg van egy szál W. Nem kell menteni semmit, mert rögtön az operanduson végzi az ember a műveletet, nem pedig egy közbenső regiszteren. Cserébe persze megnyertük a lapozgatást, ami kicsit kényelmetlen.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Én is a Z80 majd később a MCS51-es "emlőin" nevelkedtem, nagyon szegényes eszköz készlettel.

A PIC viszont teljesen kimaradt, alapból nem tetszik a risk architektúra. Megörültem amikor az STM8S sorozat extended utasítás készletével találkoztam. Anno a Z80 az MC6800 és az Intel 8085 "vad házasságából" keletkezett, az STM8S új magasságokba röpítette ezt a filozófiát.

Viszont ha később is fejleszthető, hordozható kódot akarok muszáj a C-re átlépni. Szerencsére a mai fordítók (mint pl. az SDCC) nagyon jó minőségű kódot állítanak elő - eleinte sokat nézegettem a közbülső assembly kódot különösen az interrupt rutinokban de úgy látom itt-ott még jobban csinálják mint én.

Ami a C forrásokban sok gondot okoz nekem az a shift utasítások, számomra sokkal egyszerűbb és átláthatóbb az assembly opcode.

* Én egy indián vagyok. Minden indián hazudik.

$ apt-cache search dosbox
dosbox - x86 emulator with Tandy/Herc/CGA/EGA/VGA/SVGA graphics, sound and DOS

És lehet nosztalgiázni, mindenféle MSDOS alatt futó szépséget futtatni, például ősrégi z80 assembly fordítóját.
Ja és működik ilyesmi:
  mount a: /tmp
  a:
  dir

Ezáltal dosbox-ban csak a szükséges minimumot kell csinálni, minden mást lehet Linux alól.

Köszönöm!

Már nagyon rég nem használtam a dosbox-ot. Jelen esetben viszont a CP/M kellene, ezért említettem a quemu-t de sosem próbáltam azt sem, elvileg tud idegen CPU-t emulálni.

OFF: CP/M adapter létezett a Comodore 64 -hez, létezett olyan Videoton terminál ami V20 NEC csipet használva tudott natív CP/M-et futtatni, vagy ha nagyon megrázom magam még összerakhatnék egy CP/M gépet Z80 szívvel.

* Én egy indián vagyok. Minden indián hazudik.

C-ben a rotálást hiányolom. Lel lehet ezt írni:

uint8_t x;

x = x << 1 | x >> 7;

És utána lehet reménykedni, hogy a compiler rájön, hogy ez egyetlen assembly - és egyúttal gépi - utasítás. De ugyanez a bajom az osztással és a moduloval. Nagyon remélem, hogy nem végzi el kétszer az osztást, hanem ugyanannak az osztásnak a hányadosát és maradékát használja majd. De ettől függetlenül nagyon szeretem a C nyelvet, és hasznos, hogy mielőtt C-ben programoztam volna, sokat programoztam assembly-ben. Van úgy, hogy nincs kedvem bit field-et létrehozni C-ben, simán maszkolgatok, shiftelgetek, mintha assembly-ben csinálnám.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Itt ki lehet próbálni, mit csinál egy forgatás leírására a fordító:

C: https://c.godbolt.org/z/36PThcavr (és más C fordítókkal is)
Rust: https://rust.godbolt.org/z/MKGePcs4P - van rá metódus. Lásd: https://doc.rust-lang.org/std/primitive.u8.html#method.rotate_left

Érdekesség: ha 3 bitnyit akarsz forgatni, a barrel shifter egy lépésből csinálja.
    https://c.godbolt.org/z/Yozczc716 - meg kell értenie a fordítónak a szándékodat. GCC régóta optimálisan fordítja, CLANG csak a 12. verziótól. Vajon a többi C fordító?
    https://rust.godbolt.org/z/Kboh196Y9 - egyértelmű, hogy mit fordítson

Nem kell rájönni, ha a compiler jó, akkor van közbülső assembly, ott meglehet győződni róla.

Az előbb csak a shift utasítás csoportról beszéltem, de persze ott a rotate és ezek logikai ill. aritmetikai alternatívái.

A modulo számítások nekem sajnos mindig homályosak, többszöri próbálkozás kell mire helyesen leírom (ráadásul valamiért nem bírom megjegyezni az osztó, osztandó, hányados és reciprok angol megfelelőit, folyton fel kell csapnom a szótárat. )
Hiába no, nem ez volt a tanult szakmám.

* Én egy indián vagyok. Minden indián hazudik.

Ha valóban beírja memóriába, akkor azzal elveszíted a teljesítmény előnyt. Alapból minden regiszterekben van és a következő lépés is ott fogja várni. Ha a struct memóriába írását ki tudja optimalizálni a fordító, akkor oké lehet. De megint ott tartunk, hogy leírunk valamit, de valójában valami mást szeretnénk igazából.

Ha azt írod, hogy

x= exp1/exp2; y= exp1%exp2;

akkor a fordító bátorságán múlik, hogy úgy dönt-e, hogy elég egy darab maradékos osztás; ha viszont azt írod, hogy

div_t qr= div(exp1,exp2); x= qr.quot; y= qr.rem;

akkor a fordító nyugodtan mondhatja, hogy elég egy darab maradékos osztás.

Az első eset sem a bátorságán múlik, mert ha a változók nem volatile-ok, akkor szabályszerű nem újraolvasni az értéküket. Ha meg eleve lokálisak voltak akkor pláne. Tehát nem bátorság, hanem ügyesség inkább. Ahogy a második esetben is: szó szerint beírja egy stacken foglalt változóba, majd visszatölti lokálba, ami jó esetben regiszter. Ha ügyes akkor a memóriába írást kispórolja. Ugyanaz.

Csak ilyen esetben jellemzően azt szeretnénk, hogy ez atomikus legyen. Tehát ugyanazon pillanathoz tartozzék a hányados és a maradék, még akkor is, ha egy volatile változót a megszakítás felülírhat. Tehát marad a div() függvény vagy az IT tiltás, ami meg barbárság.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

ugy kb. nemertem, mi a problema.

anno 1986 korul a TLSW Scapcara Corp mintáját követve irtam magamnak Z80 Assemblert ; ha jólemléxem kb. 2-3 hét volt -- forditáshoz Z80 kódtáblát használva --  az egész project.

később pcre is portoltam pascalban de akkor már futtatókörnyezetet is ganyoltam hozza ; valahol még van egy elvileg működő 1.44 -es floppy meghajtóm,  a lemezek is itt kallódnak valahol, nekiugorjak előkeresni ?

HUP te Zsiga !

akkoriban nekem ez nem teljesen hobbyproject volt, egy spéci Z80 alapu gepet kellett hasznalhatova tenni, mielott csinalnak belole még pár példányt ; a Homelab ( aricomp16 ?  ) es a ht1080Z romjat is atalakitottuk megfelelore, szoval basicból el voltunk látva, sot TLSW Scapcara  (c) maestro kesobb cp/m -et is portolt az "erőműre".

HUP te Zsiga !

Voltak ilyen cikkek a Hackadayen, hogy ki mire állt át a csiphiány miatt. Érdekes történet. Vannak ilyen pár cent árú mikrovezérlők is, amik most kvázi divatosak lettek. Például eszerint 4 dollárcent volt akkor egy Padauk chip: https://cpldcpu.wordpress.com/2020/04/05/addressable-7-segment-display/ Ránézésre egészen tisztességes adatlapja van. A csapda az, hogy egyszer programozható, aztán kuka. És nem is a csip ára lesz a gond, hanem forrasztgatni minden szoftver verzió után... Foglalatba kell tenni? Vagy van flash-es változata, amit fejlesztésre használnak? Ennyire nem mentem bele. Szerintem hobbira nem számít az a néhány dollár annyit, hogy emiatt érdemes legyen megtanulni valami újat. De ha párszázezres példányszámú terméket csinálnék, akkor ezzel olcsósítanám a kütyüt, a csipek árát pedig zsebre tenném.

Én sokat morfondíroztam azon, hogy merre menjek tovább a 8 bites AVR-ről és végül úgy döntöttem, hogy az újabb 8 bites AVR-ekre megyek. Míg az "eredeti" sorozat felment 3-4-5 dollárra, az új sorozat többet tud és 1 dollár körüli áron volt akkor. Az a gyanúm, hogy valódi projektekre, ahol nagy sorozatokat vesznek, ott már nem használják a régieket, és lényegében hobbistáknak szól már az árszabás.

A Z80-at sajnos nem ismerem, de az egyetemen még tanultunk egy példát vele. Csinálnak még hobbin kívüli projektet vele?

Melyik 8 bites vezérlők lettek a csiphiány nyertesei?

A Z80 tényleg leginkább hobbi projektekhez használható, de ahhoz is drágállom. A topic leginkább arról(hat) hogy van valami kütyü amihez kell egy kis ráncfelvarrás és jó lesz (gondolták).

Melyik 8 bites vezérlők? Sajna ezt nem tudom, viszont a csiphiány előtt, az egyszerű 32 bites ARM processzorok, sokkal több erőforrással (RAM, FLASH és I/O) gyakorlatilag egy árban voltak a 8 bites bugyuta csipekkel.
Csak ránéztem a Farnell kínálatára, 24 305 terméket jelez amiből 11 474 8 bites (persze ez csalóka, mert lehet hogy olyan is van benne ami nincs raktáron és a beszállítási idő jövőre).

* Én egy indián vagyok. Minden indián hazudik.