ASM megértése

Assembly tanuláshoz keresek könyvet, dokumentumot, ami segít elsajátítani a lényegét. Abszolút kezdő vagyok a témában, de nem kezdő programozó, viszonyolag stabil programozói ismereteim vannak, több nyelvben és keretrendszerben.
Amire szükségem lenne, az egy jól átgondolt írás ami erre arra kalandozva elmeséli a lényeget, mint pl a For Dummies vagy Head First köyvek. Az sem baj, ha régebbi, bele tudok helyezkedni egy DOS-os környezetbe, talán könnyebb is (?).

Magyart is, angolt is szívesen olvasok.

Hozzászólások

https://www.scribd.com/document/329631797/Socha-Norton-Assembly-Languag…
En anno a magyar forditast olvastam, nekem bejott. Mondjuk az meg foleg 16 bites ASM volt (ha jol emlekszem, erintette a 32 biteset is).

Ha ma kezdenek, akkor valoszinuleg hanyagolnam a DOS-t, talan AVR8 vagy PIC vagy valami hasonloval foglalkoznek inkabb. Vagy ARM-mal. Ezeknek valami minimalis haszna is van. x86-on max. akkor, ha virusokkal szeretnel foglalkozni - ami egyebkent jo buli, meg DOS-on csinaltam ilyesmit, sokat tanultam az Ontario visszafejtett kodjabol.

Egyebkent elfelejtetted leirni, hogy mi a celod a megszerzett tudassal. Ha csak ismeretbovites, akkor a Socha-Norton konyv teljesen jo. Ha valami gyakorlati tudas, akkor biztos van jobb nala.

--
When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

Most már uC esetén is inkább C vagy C-szerű nyelvek vannak, mint assembly... hacsak nincs valami komoly oka az embernek arra, hogy hónapok munkájával jobb kódot készítsen, mint egy dedikált fordító, akkor értelmetlen ennyire processzor-közeli szintre lemenni... még milliós szériák esetén se mindig éri meg, mire az ember befejezi a szarrá optimalizált kódját, addigra kijön a vezérlőből egy olyan verzió, amelyik ugyanannyi fogyasztással és ugyanannyi költséggel kétszer gyorsabb.

Rövid az élet, sokkal több hasznosabb dolgot meg lehet tanulni, aminek haszna is van. :)

--
https://iotguru.live

Biztos csak veletlen egybeeses, de en is C-ben szoktam AVR-t programozni (vagy az Arduinos IDE-ben a sajat moduljaival, ha olyan a feladat).

Viszont neha itt meg jol johet az ASM, pl. ott az Arduinos ws2812 library, ami elegge idozites-kritikus, illetve interruptoknal is lattam mar olyat, aki a kutyu reakcioidejen huzott azaltal, hogy az interrupt rutint ASM-be atirta.

Az ASM ritkan hasznos, inkabb szemleletet ad szerintem (hogy tudd, hogy mukodik egy gep), de uC-nel tobb kozvetlen haszna van, mint x86-nal, es kontrollaltabb a kornyezet is. Emiatt ha ma ASM-et szeretnek tanulni, inkabb valami ilyen architekturat valasztanek.

--
When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

Persze, de manapság a legkisebb megvehető uC is már 4 MHz frekvencián pörög és annyit tud, mint egy 80286-os processzor... és annyira kicsi különbség van ez és egy 80 MHz frekvencián futó uC között, hogy csak nagyon nagy széria esetén éri meg lemenni assembly forrásig és még akkor is leginkább azért, mert egzaktul lassan futó programra van szükség, a C fordító pedig kioptimalizálná a tervezett lassítás miatt beletett felesleges utasításokat.

--
https://iotguru.live

Hogy valamiért (pl. delay) ne optimalizáljo a C, arra ott a volatile kulcsszó.
De manapság mikrovezérlőn se menő a delay, helyette timer felhúz & sleep ... akkubarátabb.

A mai C fordítókkal a legtöbb C kód max 1..2%-kal lassabb egy full optimális assembly kódnál. Ezért nem éri meg a nehezen karbantartható, rejtett bugokat nagyobb mértékben "támogató" assembly programozás.

Hát igen, 20 éves architektúrával ma már nem érdemes megváltani a világot. Ha komolyabb a feladat, ugyanakkora fogyasztásból és kb. abból az árból kapható 32 bites komolyabb mikrovezérlő is (MIPS PIC32 néven vagy számtalan ARM Cortex M3, M4 architektúrás NXP, STM32, SAM3, ...).

A 8 bites architektúrák többé-kevésbé megmaradtak az ezredforduló előtti állapotban, kevéske RAM, kevéske flash, kevéske számítási teljesítmény. De egy LED-es dobókockára még jó választás lehet. :)

Szerintem nem nézed ezt jól. Ipari alkalmazásban simán elég lehet a 8 bites mikrokontroller. Egy léptetőmotor vezérléséhez, néhány szenzor viszonylag lassú méréséhez nem kell 32 bites MCU, nem kell USB, nem kell Ethernet, nem kell DSP core. (Bár már gondoltam arra, hogy kompenzálni kellene a léptetőmotor reluktancia nyomatékát, s így elérhető lenne, hogy csendesen, nyomatéklüktetések nélkül járna. Természetesen microstep-re küldve.)

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

A kicsik jellemzően egyszerűbbek. Nagyon nem szeretem, amikor akár hardware tervezéséhez, akár firmware írásához naphosszat dokumentációt kell olvasgatni. Jó, hogy szinte mindent tudnak a perifériák, de lassan eljutok oda, hogy nem kérek az I2C hardware támogatásból, inkább megírom software-esen port lábak billegtetésével, olvasásával, mert ahhoz legalább nem kell bogarásznom 17 regiszter leírását. (Nem konkrét szám, nyelvi fordulat.)

Meg aztán, hogy ontopic legyek, egy 8 biteset biztos, hogy nagyobb örömmel fogok assembly-ben programozni, mint egy 32 bites eszközt.

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

Nem értek ezzel egyet. Egyszerű feladathoz minek nagy MCU, amely ráadásul sok helyet visz a PCB-n, feleslegesen sok lába van, egyszerű dolgokhoz sokat kell tanulmányozni a doksit, így legalább lassú rá a fejlesztés, már kényelmetlen assembly-ben programozni, magasabb szinten pedig fene tudja, mi fordul a kódba, s az mennyi ideig fut?

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

Jah, igazad van. 5x5mm akkora helyigény, hogy ki sem lehet gazdálkodni. (LPC845, QFN33 tok, 64K flash, 16K RAM, 30MHz)
De a PIC32 is egy helypocsékolós állat 9x9mm-rel. (QFN64, 200MHz, 512K flash, 128K RAM)
Az ESP32 (2core, 240MHz, 520K RAM, egy zsák szolgáltatás) is elbaszott 5x5mm, igaz kell hozzá external flash, az is vagy 5x5mm.
Tény, hogy ASM-ben halál lenne programozni ESP32-t, de minek, ha van C?
És pont erről szól az egész, hogy ma már nem kell minden assemblyben összerakni. Mit ma? Már a PDP11 idején sem.
Persze lehet asm betétet belerakni a kódba, ahol időkritikus dolgok lehetnek, de pont itt jön ki a 32 bites SoC-ok előnye, hogy annyival gyorsabbak és tudnak többet, hogy emiatt nem kell lemenni asm szintre.

Tehát én sem értek veled egyet. Egyszerű feladathoz is azt a targetet fogom választani, amivel a leghamarabb lesz production kódom. Ha 1k+ mennyiségben kell gyártani, akkor elkezdek azon gondolkodni, hogy van e árelőny, ha valamivel olcsóbb SoC-cal bohóckodok, de több ideig assemblyben.

Mindez nem jelenti azt, hogy ne lenne értelme megtanulni „assembly-ül”.

Szerintem nagyon software-es szemüvegen át nézed a világot. Létezik MCU SOT23-6 tokban is, meg MSOP8-ban, de persze rakjunk mindenhova 32 bites MCU-t, s programozzuk C-ben. Aztán fene sem tudja, hogy minek.

Amúgy mégis mi a fenének gyártanak a mai napig 8 biteseket? Ha igazad lenne, csak és kizárólag 32 bites MCU-kat lehetne kapni a piacon.

Én hardware fejlesztőként azzal keserítem a kollégáim életét, hogy nem tervezek fel a szükségesnél nagyobb MCU-t a nyákra. Aztán vagy én írom a firmware-t assembly-ben, vagy más úgy, ahogy akarja.

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

A nagy MCU-nak ott van értelme, hogy már nem vagy feltétlenül rákényszerülve, hogy asm-ben, meg low level szinten toljad rajta a feljesztést, mert elbír értelmesebb fejlesztést is magasabb szintű nyelveken. Tehát amivel bonyolultabb, nagyobb, többet fogyaszt, azt a másik oldalon visszakapod könnyítésként.

No keyboard detected... Press F1 to run the SETUP

„már nem vagy feltétlenül rákényszerülve, hogy asm-ben, meg low level szinten toljad rajta a feljesztést”

Azt hiszem elbeszéltek egymás mellett. Amit eddig locsemege elárult magáról és a munkájáról, abból én arra következtetek, hogy neki ez nem kényszer. Már évek óta ezt csinálja, és egyszerűen ért hozzá.

Bár nem én vagyok a moderátor, de ilyenkor szoktam rendreinteni. :-D
Ez itt egy fórum. A következtetésednek nem sok haszna van. Itt bárki hozzászólhat, véleményt nyilváníthat teljesen szabadon.
Akkor is, ha csak papíron látott processzort. Vagy esetleg csinált már egy hobbi projektet.

Nem tudom, valamit félreértettetek. Nem személyeskedni akartam, csak megemlítettem, hogy a nagyon MCU combosabb hardvert is jelent, és azon opció a magasabb szintű nyelven fejlesztés is akár. Nem akarom előírni, hogy ki miben fejlesszen.

No keyboard detected... Press F1 to run the SETUP

Szerintem bánottál senkit. Remélem én sem.

Neked is iderakom az egyik példaprogramot, ami egyébként a való világban működik.
Átírtam C-be is. Az apró szépítések miatt talán egyik sem megy. ;)
https://pastebin.com/KJdzi2zv
https://pastebin.com/dCzTALTy
https://i.imgur.com/flWsUSY.jpg

Rávezető kérdés: ;)
Ezt a feladatot milyen combosabb hardveren oldottad volna meg?

hg2ecz írta:
Hát igen, 20 éves architektúrával ma már nem érdemes megváltani a világot.
Valamint ebben a hozzászólásban is osztja valaki az észt. Nosza, megnéztem ezen az oldalon a 8, 16 és 32 bitet bepipálva hagyva találok-e olcsóbb szerkezetet. A feladat nem bonyolult: USB, 5V, 2k RAM és 28 lábú SSOP tok, mert a TQFP már nem fér el. A választott procinál van néhány olcsóbb (a választáskor a Microchip még nem vette meg az Atmelt), de a nagyobb bitszámúak mind-mind 3,3V-osak, viszont a bemenő jelek 5V-osak. És már így is alig lehet összekötni az alkatrészeket, mivel nem breadbordon készül az áramkör, hanem az alkarészgyártók által előírt topológiával. A következő választásnál megy az ügyeletes hupos szakértőhöz a kérdés. :-)
A 8 biten kiválóan megy az AES256. A kód megírása helyett van 180Ft-os Atmel csip is. Az alkatrészek költsége az egyik termékben 700Ft körüli. Évi 6000 példánynál nem mindegy. Ugyanaz az mcu, de nagyobb flash csak 36Ft többlet. Akkor írhatom C-ben is, mert befér. Ekkor a hosszabb kód hosszabb ideig is fog futni. A másik esetben annyit kell magyarázni a fordítónak, hogy egyszerűbb direktben megírni. ;)

Elhiszed-e, hogy sokaknál jobban el tudom dönteni az eszközválasztást és a nyelvet?
Már 1983-tól fejlesztek és programozok hardvert (most is), de közben 20 évet C-ben és shellben is programoztam. Bármelyik nyelven megírom ugyanazt a vezérlő algoritmust.
A "20 éves architektúra" azt jelenti, hogy napjainkban egyre újabb modelleket hoznak ki a PIC16 családból. (8 bit, 14bites utasítás) Érdekes módon a 80-as években sem az x86-os, sem a 8 bites processzoroknak volt a legnagyobb piaca, hanem a 4 biteseknek. A gyártmányokban az ár a legfontosabb, néhol meg a megbízhatóság. Okostelefonból+routerből jóval kevesebbet adnak el, mint PIC16-ból.

Nem akarok én senkit kényszeríteni arra ami jó. Nyilvánvalóan egy python vagy C# programozó nem fog olyan feladatokkal találkozni, mint én. És nagyon remélem én sem olyanokkal mint ők. ;)

Nosztalgiáztam picit. Elővettem az általam ismert legkisebb 8 bites történelmi mikrovezérlőt.

256 byte programmemória
16 byte RAM

Ez is szépen szépen programozható C-ben, tapasztalat. A kódhatékonyság > 95% itt is egy optimális assemblyhez képest.
Persze néha akad olyan meló, ahol kell mikroidőzítés, ezért a C-be kellhet assembly betét. De a legtöbb feladat szerencsére nem ilyen.

+1

Mennél többet tud valami, annál bonnyolultabb, ami nem tesz jót a megbízhatóságnak. Vannak területek, ahol a megbízhatóság a legfontosabb szempont, ott annak is van értelme, hogy kipróbált régi architektúrára dolgozzunk, hogy ne kelljen rejtett hibáktól tartani.

Fontos lehet az is, hogy milyen feltételekkel lehet source-olni. Simán el tudom képzelni, hogy a kb 20 éves 8 bites AVR architektúra csipjeit tovább lehet majd source-olni, mint a mai legújabb ARM Cortexeket. Egyszerűen azért, mert ott már lassabb a fejlődés, viszont igény van rá, ezért nem fogják leállítani.

Vannak esetek, amikor a SW fejlesztés ideje elenyésző a rendszer többi részéhez képest, amit ezen lehetne spórolni, magasabb szintű eszközökkel, az marginális. Ráadásul ha a magasabb szintű eszközök nem eléggé kiforrottak, és esetleg van bennük valami bug, akkor várhatóan a végeredmény drágább lesz, mert más által írt framework kódokban kell kidebuggolni valami jól rejtőzködő hibát.

Ha valakinek már van jópár terméke egy architektúrára épülve, akkor hülye lesz hobbiból upgradelni: ameddig az új termékekhez elégséges a régi, addig azt fogja beépíteni, mert azzal van tapasztalat.

Fontos az is, hogy mennyi infó található róla. A 8 bites eszközöket a hobbisták ízekre szedték kívül-belül, rengeteg infót találni róla, ha valamit akarsz csinálni, akkor azt hogyan lehet.

Szóval vannak érvek az egyszerűbb architektúrák mellett is jócskán.

Én például zsír új terméket is 8 bites ATMega AVR-rel fejlesztenék, mert azt ismerem. Ha abba nem férne bele az alkalmazás, akkor viszont valószínűleg egyből valami 32 bites csodára ugranék, valami olyanra amihez van FOSS fordító, sok lib és sok user.

Elég sokmindent meg lehet csinálni egy atmega256-tal, ritka az olyan probléma, amihez uC kell, de ennél erősebb.

Én egyszer belefutottam egy ismerős gyerekének házi feladatába. Volt egy néhány utasításos „processzor”, és egy lefuttatandó program. A program tele volt ciklusokkal és feltételes ugrásokkal. A szép megoldás az lett volna, ha tanulmányozom a programot, és az elemzés után megmondom a végeredményt. Ezzel két baj volt: A program bonyolultsága miatt ez sokáig tartott volna, illetve utána a gyereknek ezt elmagyarázni még több idő lett volna. Így aztán C-ben írtam egy szimulátort. A program meglepően rövid idő alatt lefutott, és ez gyanús lett. Mikor kikapcsoltam minden optimalizációt a fordításnál, akkor viszont több óra alatt sem végzett. Ezért aztán az eredeti programot átírtam natív intel assembly-re, ami kb. 1 óra alatt le is futott, és természetesen teljesen más volt az eredmény, mint az optimalizált C változatnál. Azt az ismerősömre bíztam, hogy a gyerek mit fog mondani a megoldás menetéről. :-)

A poén az, hogy a 2017-es adventi feladatok között volt egy hasonló. Így elővettem a korábbi megoldást, és az alapján átírtam a programot. Az is kiderült, hogy a korábbi megoldás nélkül gondban lettem volna, mert az assembly tudásom már erősen konvergált a nullához.

Réges-régen, évtizedekkel ezelőtt programoztam assembly-ben, C64, x86, mikrovezérlők.
Ma azt kell mondjam, hogy minden szempontból inkább C és kritikus helyen csak az általa fordítottat nézem át, hogy futásidő nézve jól fordította-e, de nem assembly-ben írom.

gcc -Ofast -march=native -S xy.c
xy.s -ként keresd az assembly kimenetét.

Ennél csak az élet nagyon speciális területén fogsz jobbat írni assembly-ben, ráadásul a C kódot ha viszed x86 helyett ARM-ra vagy MIPS-re, az ugyanazt fogja tenni. Az assembly sajnos nem hordozható. Ellenben az assembly kód olvasása hasznos lehet.

Pár anyag - először a bemelegítéshez:
http://www.cs.virginia.edu/~evans/cs216/guides/x86.html
https://en.wikibooks.org/wiki/X86_Assembly
https://www.nayuki.io/page/a-fundamental-introduction-to-x86-assembly-p…
https://www.engr.mun.ca/~anderson/teaching/8894/reference/x86-assembly/
https://www.csie.ntu.edu.tw/~cyy/courses/assembly/10fall/lectures/hando…

Alaposabb művek:
https://www.ic.unicamp.br/~pannain/mc404/aulas/pdfs/Art%20Of%20Intel%20…
http://lms.uop.edu.jo/lms/pluginfile.php/2420/mod_resource/content/1/as…
http://www.egr.unlv.edu/~ed/assembly64.pdf
https://studenthelp62.files.wordpress.com/2017/03/intelasseblylanguage…
https://doc.lagout.org/programmation/asm/X86%20Assembly%20Language%20an…

És ha kivégezted az x86-ot, akkor jöhet az ARM assembly:
https://doc.lagout.org/programmation/asm/ARM%20Assembly%20Language_%20F…

Maximálisan egyetértek. És itt architektúrán nem csak hardveres prociarchitektúrát értek, hanem OS függő is. Tehát ha még feltételezzük az x86 vagy x86_64-et architektúrát, akkor is, modern OS alatt máshogy kell működő ASM kódot írni, nincs szegmens:offszet címzés, valós mód helyett védett módban fut minden, sok hardverhez nem enged az OS közvetlenül hozzáférni, stb..

Én emiatt pl. régi, DOS-hoz készült PC Assembly könyvet már hanyagolnám is. Továbbá ASM tanulásához jók a magasabb szintű nyelvek eleinte. Ezt úgy értem, hogy megírni egy progit magas szintű nyelven, aztán elkezdeni egyes részeket beágyazott ASM-re cserélni. Én annó így tanultam, eleinte Pascalban, volt 1-2 dolog, amit nem lehetett megoldani hagyományos utasításokkal, arra használtam beágyazott ASM kódot. Aztán egyre több rutint, blokkot cseréltem le ASM kódra, míg végül már az egész Assemblyben volt, és csak onnan tértem át tisztán Assembler használatára.

No keyboard detected... Press F1 to run the SETUP

Mi nem tetszik? Gyönyörű, átgondolt utasításkészlet és címzésmódok. (Ahogy mondták régebben: azért olyan szép, mert vették a DEC VAX-ot és kidobálták a használható részeket. A maradékot elnevezték Motorola 68000-nek.)

=====
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?

Egyébként igen, nem rég (pár éve) úgy láttam, hogy valamelyik régebbi jelölés helyett valami újat használtak.

Már nem emlékszem, milyen processzor volt (bár valószínű x86-os lehetett), és nem emlékszem milyen program (de azt hiszem, valami opensource assembler), de úgy tűnt, hogy a korábban használt mnemonikok és jelölésmód helyett egy másikat, (számomra) jobban olvashatót használtak.

Semmi részletre nem emlékszem, de olyasmit képzeljetek el, hogy mondjuk régen az volt, hogy
LD AX, 42
és most meg az lenne, hogy mondjuk MOV #42, AX vagy LDA 42 vagy akármi.

És persze ugyanarra a gépi kódra fordul le.

Khhmm.
És láttál már olyan vastagabb könyvecskét, ami hasonló funkciót tölt be egy intel processzornál?

Egyébként tudom miről beszélsz, jómagam is fogtam 6-8 ilyen hibát. Mivel a dolog elég alacsony szinten van, némi hozzáértéssel könnyen megkerülhető, kihagyható vagy körbeprogramozható.

Ugyanez egy szinttel magasabban már elég kínos lehet. Először csak néztem a C fordító eredményét. Nem is az a megdöbbentő, amikor felesleges vagy indifferens utasításokat rak a kódba, mer azt el is várom tőle. ;) Inkább az a borzasztó, amikor amikor képtelen vagyok 20 év C tapasztalattal megfogalmazni tök egyszerű dolgokat, vagy esetleg a jól megfogalmazott dolgokból hülyeséget, működésképtelen dolgot fordít. Ilyen indítással, ha nem tudtam volna assemblerben programozni akkor is megtanultam volna.

Aztán az sem véletlen, hogy az Arduino és attól felfelé jó a C fordító. Hiszen a regiszterkészlet stb. hasonlít a Motorola 68000-hez. Szóval természetesen PIC-ről beszélek, ahol az egyetlen regiszter (8 bitesen) és a szoftver stack hiánya miatt mindent szoftverből kell emulálni. Viszont azzal (látszólag) sokkal hatákonyabban meg lehet írni a ledvillogtatót. ;)

Intel processzorét nem nézegettem, de minél bonyolultabb egy CPU/MCU, jó eséllyel annál több hiba is van benne... az x86 / x64 meg azért elég bonyolult. :)
Mondjuk nem minden hiba kerül úgy nyilvánosságra, mint annak idején az F00F bug, de szoftveresen nagyon sok workaround van ezekre, a Linux kernelben is.

Van olyan (komolyabb) hiba, ami szoftveresen nem javítható egyszerűen (pl. az eszköz egyik I²C interfészének elérhetetlensége), de azért több dologra van megoldás (pl. inicializációs sorrend megtartása, bizonyos egymás utáni állapotok vagy utasítások kerülése)...

Én PIC-kel nem foglalkoztam, csak MSP430, AVR meg STM32 járt a kezeim alatt eddig. :)

Ami a stack-et illeti, szinte pánikban voltam, hogy a PIC-ekben nincs. Pontosabban van call/return, illetve IT és retfie. De nincs push, pop. Aztán érdekes módon - talán a fileregisztereknek köszönhetően, az egyszerű direkt címzés okán - nem is hiányzik. Ezzel szemben Z80-on szinte az összes rutinom a regiszterek stack-re mentésével kezdődött, s egy rakás pop-pal végződött, aminek következtében lassú volt a kód.

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

Ez csak "a magasszintű nyelvek támogatása" okozta rossz beidegződés, vagy a rossz programszervezés - józan paraszti ész hiánya - miatt keletkező probléma.

Abban az időben, amikor a TurboPascal-ban (stb.) megjelent az Iterrupt(), láttam ilyen programot. Az első nagyképernyős PSION-on futtattunk terminálos programot, ami kissé nem volt flicker free. :-)
Először el kellett olvasni a dokumentációt, amely leírta az LCD frissítésének kikerülését, majd jött a program újraírása. Az Interrupt() az okoskák szerint a push+push+push... mókával kezdődött. Az újabb processzorokon persze létezik a pusha utasítás, de az is egy-egy ciklust eszik regiszterenként. Aki meg gondolkodik, az tudja, hogy egy soros interrupt esetén csak az FLAG, AX, DX regisztereket használjuk. A buffer írás-olvasás meg mehet indexelten globális változón keresztül.

A PIC esetében is szükség lehet sok regiszterre. Ezeket rendre felveszem (a 18-asnál az Acess területre) R0, R1,.., és a 16 bites műveletekhez low endian-ként használva az R01,.. párosításokat. Igy jól makrózható a regiszterek használata. Az interrupt-on belül az r0, r1,.. változókat használom, így a scratchpad mentésére sincs szükség. A high priority intrrupthoz meg az r0h, r01h tartozik. Ezeket is csak akkor kell definiálni, ha szükséges.
Ugyanez áll az indexekre is. Meg kell tervezni, hogy hány indexelt buffer lesz, és előre kiosztani a használt indexregisztereket. Így ezeket sem kell menteni, legfeljebb az alsó felét.
Szintén PIC18 esetén, mivel a változók jó része az Access területen van, nincs szükség a BSR használatára. Ha nem elég az Access terület, akkor ki lehet gyűjteni a speciális feladathoz tartozó változókat - pl. USB kezelés - egy másik lapra. Ehhez kézenfekvő az USB RAM első lapjának maradéka, ahol az az USB regiszterei is vannak. Inicializálás után a BSR erre a lapra mutat. Ettől kezdve nincs szükség a BSR mentésére és megváltoztatására sem. Mindössze annyit kell megjegyezni, hogy az USB kezelése közben a lokális változókat "b", egyéb változókat meg "a" címzéssel lehet megtalálni.
Ilyen trükkökkel gyakorlatilag felére csökken a kód, miközben még áttekinthetőbb is lesz.

A (PIC)C fordító libjeivel meg az a bajom, hogy mindent úgy írnak meg, mintha operációs rendszerből indított hívások lennének. Pedig én írom az én hardveremen, nem konkurrens környezetben a programot. Éppen ezért a segítségként alámtolt szabványos hívások csak az erőforrást és az időt pocsékolják, miközben a konvenciókat kell kerülgetnem.
Hasonló mentéseket végez egy "rendes" C fordító is. Ennek az a célja, hogy a program írójának az esetek többségében ne kelljen gondolkodni. A fent leírt eredmény lehet elérni a "pragma isolated_call" direktívával. Ennek a "tudom mit csinálok" lenne a helyes magyar fordítása. ;) Ilyenkor a fordító nem generál kódot a használt változók mentésére és viszzaállítására a függvényhívás előtt-után. Vagyis amit írsz azt fordítja. Mint az assembler!

És tudod mi a vicc? Amit írtál, az igaz. Ha nem működik, akkor ők szúrták el.

Bár finomításra szorul. Egyfelől a processzorok sem hibátlanok, másfelől magasabb szintű nyelveknél ritkán hibázik a compiler. Szóval ott is a programozó a hibás, ha nem megy.

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

PC-n azért mert nem tudsz assemblyben látványos dolgot készíteni.
Mikrokontrolleren (PC-n is) azért mert millió+1 külső lib-től függsz.

30-40 éve egyszerűbbek voltak a gépek, sokkal könnyebben tudtál valamit villantani.
Ezért is nincs értelme manapság. Hiába van teljes szabadságod ha nem tudsz vele semmit sem kezdeni.

Az első érvelést elfogadom, a PC, az oprendszer, a perifériák bonyolult dolgok.

A második nem igaz. Mitől függök? Van valamennyi programtáram, valamennyi RAM-om, valamennyi perifériám, meg vannak az utasítások, van a dokumentáció, egy szövegszerkesztő és én. Mi kell még, hogy assembly-ben programozzak? A végén az assembler, meg valami, amivel letöltöm a mikrokontroller flash memóriájába az eredményt. Semmitől sem függök.

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

Ez már feladattól függ. Ha az egész hardware-t magadnak álmodod meg, s nem feltétlenül szükséges pl. egy USB vagy Ethernet szintű dolog, akkor nem kell semmiféle lib. PIC-re írtam már úgy kódot, hogy az USB stack a netről származott, C-ben íródott, a program többi részét assembly-ben írtam, s ezt a két dolgot sikerült egyetlen programmá gyúrnom. Az assembly és C kód közötti függvény hívások, címek, pereméter átadások az izgalmasak, a fordító dokumentációját kell hozzá olvasni.

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

Nekem ez a könyv nagyon tetszett annó: https://moly.hu/konyvek/petho-adam-variaciok-assembly-re

Jó a stílusa, szórakoztatva tanít.

Az ASM nagyon platformfüggő (bár a gondolkodás lényege többnyire platformfüggetlen), úgyhogy én is elgondolkodnék a helyedben a platfromon. Ha péládul valami 8 bites mikrovezérlőre írsz ASM-et, abból még valami értelmet is ki lehet csiholni. Meg szkóppal mérni az időzítéseket. Cool stuff! Például egy Arduino-val (AVR Atmega328 csip) olcsón és könnyen el lehet indulni.

Manapság X86-on nem sokmindent van értelme ASM-ben írni. Hogy mégis mit érdemes, arról kérdezd hajbazert :-).

Valamikor a 80-as évek végén, vagy a 90-es elején (?) kiadott PC-DOS könyv harmadik kötete tárgyalta a 8086-os utasításokat, úgy, hogy mindegyiknél hozott egy PASCAL példát arra, hogy a gépi utasítás kb. mit is csinál.

Linux alatt sem vészes elkezdeni. Írtam fentebb, hogy a gcc -S kapcsolója tanulmányozható, gcc-vel továbbfordítható assembly forrásra fordít.

Viszont van még a nasm (sudo apt install nasm) x86-ra, amely szintaktikájára egy példa:

teszt.asm:


SECTION .DATA
	msg:     db 'Hello world!',10
	msgLen:  equ $-msg

SECTION .TEXT
	GLOBAL _start 

_start:
    mov eax,4       ; write syscall 
    mov ebx,1       ; 1: stdout
    mov ecx,$msg    ; msg ptr
    mov edx,$msgLen ; msg len
    int 80h         ; syscall
    
    mov eax,1       ; exit syscall
    mov ebx,0       ; errorcode: 0
    int 80h         ; syscall

Lefordítása:
$ nasm -f elf64 teszt.asm -o teszt.o
$ ld teszt.o -o teszt
$ ./teszt # és fut

Ebből aztán sokat lehet tanulni. :( Hívjunk meg egy függvényt, ami megoldja a problémát. Ezzel az erővel a C++ programozást is nevezhetném assembly-nek, mert majd lefordítja, meg gépi kód lesz belőle, ami meg futni fog valahogy.

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

Például azt, hogy mi a nasm alapszintaktikája és azt, hogy az assembly programod eredményét hogyan írd ki Linux alatt.
Tudod jól, hogy amíg például nem tudod villogtatni a LED-et a mikrovezérlővel, azaz nincs semmi vizuális kimenete a kódodnak, addig ne akarj továbblépni. Ha már ki tudod írni az eredményt a képernyőre, akkor már fejlesztheted tovább a PC-s assembly kódodat.

Vagy rosszul gondolom?

Jó, hát ha ez a cél. De épp a lényeget fedi el: egyesével végigmenni a string karakterein egy pointerrel, a végén kilépni a ciklusból. Persze, ha van oprendszer, aligha lehet közvetlenül video RAM-ba írni, meg video módot beállítani. DOS-ban lehet.

Itt vissza is jutottunk oda, hogy ahol operációs rendszer van, ott tényleg értelmetlen az assembly programozás. Mikrokontrolleren van értelme.

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

Pedig a modern x86 Assembly az tényleg ilyen. Még Windows alatt is lehet benne Win32 API-t használó GUI-s programot írni, meg OOP-t használni. Sajnos ezt nem értette hajbazer, hogy a modern OS ma már „mindenes”, nyújt minden szolgáltatást, azokat kell használni. Sőt, kell is használni, mert normális OS nem engedi, hogy te low level szintű hardverhozzáféréssel alányúlj a kernelnek meg a jogosultságoknak. Ez egyfelhasználós DOS alatt még oké volt, meg C64-en, de pl. Linuxon, NT architektúrás Windowsokon akadályokba fog ütközni.

No keyboard detected... Press F1 to run the SETUP

Akkor bocs, nem tudtam, hogy neked ez ennyire világos. hajbazer nem értette, hogy azért nem írnak ma már PC-s alkalmazásokat asm-ben, mert így is, úgy is az OS API-k hívogatása határozza meg az erőforrásigényt, és ezzel az asm előnye elveszik, főleg, ha egy optimalizációval dolgozó modern fordító produktumával versenyezteted, cserébe az asm-ben fejlesztés lassú, nehézkes. PC-n ezért is kopott ki, már csak 1-2 teljesítménykritikus részt írnak asm-ben, de már ez is egyre ritkább, mert inkább a fordítót hekkelik ilyenkor optimalizációval. A DOS korszak más volt, mikor egy demónak bele kellett férnie 0,25-64 KB-ba, egy proginak rá kellett férnie egy kisfloppyra, meg bele kellett férnie a 640 KB alatti szabad memóriaterületre, és elfogadható sebességgel kellett futnia 8088-286-os procin is, akkor még nagyon megérte, de azóta túl sok minden változott.

Beágyazott rendszereken, mikrokontrollereket még van értelme, mert ott low level hardverhozzáférés van, és nem kell felsőbb szintű absztrakciós rétegeken átmenni, meg API-kat hívogatni és a hardveres erőforrások is sokkal szerényebbek.

Lassan már a C-re is egyfajta low level, asm-szerű nyelvként tekintenek sokan, és túl alacsony szintűnek, túl nehézkesnek tartják. Persze erre lehet azt mondani, hogy nem tanultak meg programozni, de nem véletlen, hogy a népszerűsége a sima C-nek csökkent a modernebb, még magasabb szintű nyelvek rovására.

No keyboard detected... Press F1 to run the SETUP

A C-nek számtalan baja van a modernebb nyelvekhez képest. Igazából csak azért nem kopott ki, mert viszi a lendület. A C++ még szarabb lett, a jobb nyelvekhez pedig nincsen bármire fordító. Még ma is egy új projekt indításakor a C++ korlátoz abban, hogy min tudod majd futtatni a programot. Bármi más meg pláne korlátoz. Amire viszont C fordító sincs, arra nyugodtan mondhatod a menedzsmentnek, hogy bocsika, de azt nem támogatjuk.

Úgyhogy még jó sokáig marad nekünk a C. Ami jó, mert közel végtelen sok munkát biztosít a sok hülyesége. :-)

A C-nek számtalan baja van a modernebb nyelvekhez képest. Igazából csak azért nem kopott ki, mert viszi a lendület. A C++ még szarabb lett, a jobb nyelvekhez pedig nincsen bármire fordító. Még ma is egy új projekt indításakor a C++ korlátoz abban, hogy min tudod majd futtatni a programot. Bármi más meg pláne korlátoz. Amire viszont C fordító sincs, arra nyugodtan mondhatod a menedzsmentnek, hogy bocsika, de azt nem támogatjuk.

Úgyhogy még jó sokáig marad nekünk a C. Ami jó, mert közel végtelen sok munkát biztosít a sok hülyesége. :-)

Írjál már kérlek kernel drivert pythonban. Csak mert modern nyelv.

Bár ez után, hogy pythonban írtak meg olyan cuccot (ami C-ben az 1/100-ad mérete sem lenne és elég könnyen elrejthető lenne), és még pikk-pakk is könnyen visszafejthető, megérett a világ arra, hogy az emberek majd olyan robot operálja aminek a kódját pythonban írták. Aztán csak imádkozzanak, hogy a space-ekkel jól 'tabulálták' a kódot.

Hát igen, hol vannak azok az idők, amikor a bare metal programming volt az általános megoldás.

- Linux fut igen sok beágyazott cuccban ... user space programozás, indőnként az erőforrásokhoz rendszerhívással.
- RTOS és társai a maradék kisebb erőforrású mikrovezérlős cuccban, szintén rendszerhívással kapunk erőforrás elérést
- és van még néhány egyszerűbb mikrovezérlős megoldás, ahol találkozhatunk bare metal programminggal, de az is leginkább C-ben és csak minimális assembly betéttel.

Jut eszembe, Rust nyelven is készülgetnek RTOS-hez hasonló csírák, megfigyelhető benne is hogy ahol szükséges, oda paszíroznak kis assembly betétet. De csak amennyi assembly indokolt: https://github.com/tock/tock/blob/master/arch/cortex-m0/src/lib.rs

Tockos :)
https://www.tockos.org/

Mert a gyártóspecifikus utasításokat univerzálissá tették.
Ez jó lehet a crossassemblerhez is.

Viszont sajnálatos, hogy az assemblerben akár programozni se tudó C++, sőt java programozók által írt tákolmányok mennyivel kevesebbet tudnak, mint a régi fordítók. Így aztán könnyen rávágja bárki, hogy használhatatlan nyelv.

Ahogy páran már írták, nem árt hozzá architektúra ismeret.
Ez nem is baj, mert a tök egyszerűtől kezdve a durván bonyolultig minden van.
Én C64-en kezdtem az assemblyt (bár a mai napig nem fejlesztek másra asm-ben), és szerintem az nagyon jó kezdésnek.
Nem is kell hozzá igazi C64-es, lehet kódolni emulátorban is.

A lényeg, hogy megismerd a regisztereket, flageket, stacket... egyszóval a proci részeit, hogy aztán tudd őket kezelni programból.

C64 azért is jó alap, mert hamar lehet látványos dolgokat művelni:
Mozgatni a kurzort, írni a képernyőre, színezni a keretet, szöveget, hátteret...
Vagy hangokat kicsikarni a SID-ből. :)

Tehát ezen megismered az alapokat, amik arra jók, hogy tisztán lásd az assembly lényegét és felvedd azt a gondolkodásmódot ami kell a nyelvhez.
Aztán léphetsz a bonyolultabb procik felé, amikhez DOS-ban, vagy Linuxban is tudsz kódolni.

Vagy akár beszerezhetsz egy FPGA-t, amihez akár Te magad is fejleszthetsz assembly nyelvet! Bár lehet nem pont ezzel kellene kezdeni :)

Nicknevem miatt erintett vagyok a temaban :)

Regen gyerekkent foglalkoztam egy kicsit C64 es x86 (<386) assemblyvel, de ami igazan tetszett, az a DSP-k programozasa felnottkent. Diplomamunkam soran egy Analog Devices SHARC DSP-t hasznaltam. Es azt kell mondjam, hogy ezekre elvezet assembly nyelven programozni. Annyira jo, sokoldalu, celorientalt utasitaskeszletuk van, hogy rendkivul tomor kodot lehet vele irni. Ezekre jellemzo, hogy egy ciklus alatt elvegezheto egy komplexebb ALU muvelet + adatmozgatas + pointerek/counterek inkrementalasa, ezert nehany sorbol kijon egy FIR szuro. C nyelven se lenne rovidebb/tomorebb. Lasd: http://www.analog.com/en/design-center/processors-and-dsp/adsp-218x-219…
Adja magat, hogy az adatfeldolgozo reszeket asm-ben kodoljuk le, nem lesz tole kevesbe "elegans" a forraskod.

Szoval en is ugyanazt tudom javasolni, hogy inkabb vmilyen altalad elerheto embedded kornyezetben tanulj asm-et, ahol nincs OS, csak az altalad irt kod fut (+ bootloader). Szerintem az uncsi, hogy Linux x86 esetben a kod nagy resze abbol all, hogy a regiszterek tartalmat elokeszitgetjuk es int-et hivogatunk.

Az igazi DSP-nél való alkalmazással teljesen egyetértek. Ott adja magát a DSP frankón eltalált assembly nyelvezete.

x86 és ARM esetén a szaturációs SIMD műveleteknél még van jelentősége az assemblynek - Linux felett is.
Legalábbis amíg el nem árulja nekem valaki, hogyan tudom C-ben a szaturációs aritmetika használatára rávenni a GCC-t.

btw: letezik valami jo doksi (itt elsosorban tutorialra gondolok es nem referenciara), ami nem a regi 16/32bit dolgokrol szol, hanem egybol a latest&greatest infokat targyalja?

Köszi a sok hasznos linket, tanácsot. El lettem látva minden jóval :)

Volt valamikor programozás órán olyan feladat, hogy "mit ír ki"?
És az alábbi?


#include <stdio.h>

const char f[] = "\x55\x48\x89\xe5\x48\x89\x7d\xf8\x48\x89\x75\xf0\x48\x8b\x45\xf8\x8b\x10\x48\x8b\x45\xf0\x8b\x00\x89\xd1\x29\xc1\x89\xc8\xc9\xc3";

int main() {
    int (*func)() = (int (*)()) f;

    int x=112, y=120;
    printf("%d\n",(int)(*func)(&x,&y));
    return 0;
}

A GCC ezt is lefordítja, csak hogy fusson is (x86_64), kell egy -zexecstack kapcsoló. Ha ezt a kapcsolót el akarod hagyni, akkor a Rust példában látható mmap-os trükk C-ben is működik.