Uploaded avatar of iHiD

Itt a Nibbly november

@iHiD
Majdnem 3 éve ezelőtt
Videó

Bevezetés

Sziasztok! Üdv a novemberben. Remélem, jól vagytok.

Őrült mozgalmas októberünk volt. Nemrég indítottunk egy nagy fejlesztést a közösségi megoldásokhoz. Mostantól kiszűrjük az ismétlődőket, így a hasonló megoldások csak egyszer jelennek meg, emellett új rendezési lehetőségeket, valamint kód szerinti keresést is kaptok, és ha megnézed a C#-ot, láthatod, hogy a különböző programozási fogalmak szerinti szűrést is hozzáadtuk. Így olyan megoldásokat kereshetsz, amelyek biteltolást, rekurziót vagy bármi mást használnak, ami épp érdekel. Ezt a közösségi héten más kurzusokra is kiterjesztjük.

De egyelőre koncentráljunk a #12in23-ra. Október izgalmas hónap volt, az objektumorientált nyelvekkel ismerkedtünk. Ez a hónap viszont kemény lesz. Az assembly nyelvekre összpontosítunk, azon belül is a MIPS assemblyre, az x86-64 assemblyre és a WebAssemblyre. Ahogy megszokhattad, Erik most is végigvezet minket azon, mi teszi ezeket a nyelveket érdekessé és egyedivé.

A jelvények

Ahogy mindig, most is megszerezheted a Nibbly November jelvényt, ha ezeken a nyelveken teljesítesz bármelyik 5 feladatot. Ott van még az Egész éves jelvény is, amiért tudom, hogy sokan dolgoztok. Ehhez 5 kiemelt feladatot kínálunk, amiket teljesíthetsz. Ezek a következők:

  • Bitszámlálás: számold meg egy szám 1-es bitjeit
  • Gabonaszemek: számítsd ki, hány szem gabona van egy sakktáblán, ahol minden mezőn duplázódik a szemek száma
  • Ellenállás színe: alakítsd át egy ellenállás színcsíkját a numerikus értékévé
  • Rotációs rejtjel: valósítsd meg a rotációs rejtjelet (más néven Caesar-rejtjel)
  • Nukleotidszámlálás: számítsd ki, hogy egy DNS stringben hányszor fordul elő az egyes nukleotidok mindegyike

Háttér

Miért Nibble November a neve?

Nos, ahogy valószínűleg tudod, egy byte 8 bit. A nibble pedig 4 bit. A név akkor kezd értelmet nyerni, ha a byte szóban az y-t i-re cseréled, amiből bite lesz. A nibble tehát egy kis falat.

Mi az az assembly nyelv?

Kezdjük az alapokkal. A CPU utasításokat hajt végre, például „adj össze két számot” vagy „tolj el biteket balra”, és így tovább. Ezeket az utasításokat gépi kódú utasításoknak nevezzük, és nem mások, mint bitek meghatározott sorozatai. Egy program végrehajtása „egyszerűen” (idézőjelben) annyi, hogy a CPU feldolgozza és végrehajtja ezeket a bitsorozatokat.

Mivel az utasításokat közvetlenül bitsorozatként leírni nehézkes és hibára hajlamos, Kathleen és Andrew Donald Booth már 1947-ben kitalált egy emberbarátabb nyelvet a gépi kódú utasítások leírására. Az ilyen, gépi kódú utasításokat reprezentáló nyelvet assembly nyelvnek nevezzük. Ezt az assembly nyelvet aztán egy „assembler” alakítja át gépi kódú utasításokká.

Az assembly nyelvek érdekes tulajdonsága, hogy közvetlenül egy CPU-architektúrához kötődnek, bár általában operációs rendszertől függetlenek.

Apropó, ha emlékszel a lyukkártyákra, azokra a nagy kartonlapokra, amelyeket a legkorábbi számítógépeknél használtak a programok végrehajtásához, nos, azok is egyfajta assembly nyelvnek számítottak!

Miben tér el az assembly nyelv azoktól a nyelvektől, amelyekben ma programozunk?

A legfontosabb különbség, hogy az assembly nyelvek nagyon alacsony szintűek. Sok olyan absztrakciót fogsz hiányolni, amit megszoktál. Osztályoknak vagy objektumoknak nyoma sincs. Ciklusok? Azokat ugrásokkal kell kézzel megírnod. Függvények? Azok nincsenek! Számomra nagyon alázatra nevelő volt assembly kódot írni, mert az ember rájön, mennyivel könnyebbé teszik a modern nyelvek az életét. De az is hihetetlenül hasznos, ha assembly kódot írsz, mert sokkal jobban megérted, hogyan is működnek valójában a dolgok.

Érdekes tény: a RollerCoaster Tycoon forráskódjának 99%-a kézzel írt assembly kód volt! Ez lenyűgöző teljesítmény, amit még inkább értékelni fogsz, ha magad is foglalkoztál egy kicsit assemblyvel.

Írnak még az emberek assembly kódot?

Hát, kevesebben, mint régen. Régen gyakran előfordult, hogy a kézzel írt assembly felülmúlta a fordító által generált gépi kódot (ez is az egyik oka annak, hogy a C++ nyelv lehetővé teszi assembly kód közvetlen beágyazását), de a fordítók mára olyan jók lettek a gépi kód generálásában, hogy ez már ritkán igaz. Mindezek ellenére az assembly nyelvvel még mindig találkozhatsz teljesítménykritikus vagy erőforrás-korlátozott környezetekben.

Áttekintések

MIPS

  • A MIPS (Microprocessor without Interlocked Pipelined Stages) a redukált utasításkészletű számítógép (RISC) utasításkészlet-architektúrák egy családja
  • A MIPS Computer Systems fejlesztette, és először 1985-ben jelent meg
  • Több verzió létezik: MIPS I, II, III, IV, V és MIPS32/64. Az első két verzió csak 32 bites volt, a MIPS III viszont bevezette a 64 bites támogatást.
  • Számos opcionális kiterjesztés, például SIMD utasítások és tömörítés
  • Nagy hatással volt a későbbi RISC-architektúrákra
  • A MIPS 2021-ben bejelentette, hogy a MIPS architektúrát már nem fejlesztik tovább, és áttértek a RISC-V-re (amely nyílt forráskódú, jogdíjmentes architektúra)
  • Leginkább beágyazott rendszerekben (pl. routerekben) és szerverekben használják (a Silicon Graphics gépei használták, amelyek híresen filmek trükkfelvételeihez kellettek), a NEC Cenju-4 szuperszámítógépben, a Tesla Model S autójában és a NASA New Horizons űrszondájában, de arra is, hogy egyetemeken assemblyt tanítsanak vele, valamint több játékkonzolban (pl. az eredeti PlayStation, a PlayStation Portable és a Nintendo 64)

x86-64 assembly

  • Az AMD tervezte, és 1999-ben jelent meg AMD64 architektúraként
  • Az x86 utasításkészlet 64 bites változata, amely 1978-ig nyúlik vissza, amikor az Intel kiadta a 8086-os mikroprocesszorát. Ez egy 16 bites processzor volt, de később a 80386 hozzátette a 32 bites utasításokat, és az az utasításkészlet vált az x86 szinonimájává.
  • A 64 bit legfőbb hozadéka a nagyobb memóriacímzés volt (a 32 bites címzés 4 GB-ra korlátozódik), ami szűk keresztmetszetté vált. A 64 bit elméletileg 16 exabájt címzésére képes, de jelenleg csak 48 bitet használnak, amivel 256 TB címezhető (szükség esetén később bővíthető)
  • Az AMD64 kiterjeszti az x86 utasításkészletet, és úgy tervezték, hogy egy kompatibilitási mód révén teljesen kompatibilis legyen a meglévő 16 és 32 bites alkalmazásokkal
    • Az Intel az AMD bevonása nélkül tervezte meg az IA-64-et. Ez egy új, nagyon más és visszafelé nem kompatibilis 64 bites utasításkészlet volt. Végül az AMD64 győzedelmeskedett, és az Intel is megvalósította a saját változatát (csak kisebb szemantikai eltérésekkel)
  • Mindenhol használják. A munkaállomásoktól a szerverekig (a szuperszámítógépeket is beleértve), a beágyazott rendszerektől a játékkonzolokig (pl. PS5 és Xbox Series X).

WebAssembly

  • A W3C tervezte, amely a webes technológiák szabványügyi szervezete
  • A tervezési célok:
    • Gyors, biztonságos és hordozható
    • Hatékony és hordozható reprezentáció
  • Régen a weben a gyors végrehajtást általában speciális böngészőbővítményekkel érték el, mint a Flash és a Silverlight, mivel a JavaScript maga nem igazán alkalmas nagy teljesítményt igénylő számításokra. E bővítmények legnagyobb hátránya az volt, hogy általában sok biztonsági problémával küszködtek, és nem voltak szabványosítva.
    • A Mozilla megtervezte az asm.js-t, a JavaScript egy részhalmazát, amelynek célja az volt, hogy kódot lehessen futtatni a böngészőben kiváló teljesítménnyel, amit a típuskonzisztenciával (a típusok dinamikus változtatásának mellőzésével) és a szemétgyűjtés hiányával ért el. A nyelvek ezután asm.js-re fordíthattak, és így is jó teljesítményt értek el a weben. Mégis JS volt, így korlátozott volt, mit lehetett vele elérni. Ezért jött egy új nyelv javaslata: a WASM.
  • Assembly-szerű nyelv, amennyiben végrehajtandó utasítások halmazát nyújtja. Döntő különbség, hogy nincs egy adott CPU-hoz kötve, így platformfüggetlen, és minden platformhoz szükség van egy megvalósításra (egy virtuális gépre). Ez azt jelenti, hogy a WebAssembly valójában bytecode, nem gépi kód
  • Statikusan típusos (döntő különbség a JS-hez képest)
  • Általában ahead-of-time vagy just-in-time fordítást használ (de értelmezhető is)
  • Nyílt szabvány, és két dolgot határoz meg:
    • egy bináris formátumot
    • egy szöveges formátumot (amit a bináris formátumra fordítanak)
  • Minden nagyobb böngészőben van megvalósítása
  • Számos nagy teljesítményt igénylő weboldal használja, például a Google Earth, a Figma, a Unity és az Autocad. Egyre inkább teret nyer a szerveroldalon is, például mikroszolgáltatások futtatására, SaaS-platformokon (pl. CloudFlare workerek) vagy Dockerben

És programozási szempontból miben térnek el?

MIPS

  • Load-store architektúrát használ (más néven register-register), ahol az utasítások vagy memóriaelérést, vagy aritmetikát végeznek, de kizárólag a regiszterekben lévő adatokon dolgoznak

x86-64 assembly

  • Register-memory architektúrát használ, amely lehetővé teszi, hogy a műveleteket memórián (vagy memóriából) és regisztereken is elvégezzék

WebAssembly

  • Veremalapú programozást használ (regiszterek nélkül), azzal a lehetőséggel, hogy adatot olvasson és írjon memóriából és memóriába

Mi teszi nagyszerűvé ezeket a nyelveket?

MIPS

  • Kicsi. A MIPS utasításkészlet összes utasítása elfér egyetlen oldalon
  • A bevett hívási konvenciók segítenek eldönteni, hogyan használd a rendelkezésre álló regisztereket, pl. melyiket argumentumok átadására és melyiket eredmények visszaadására.
  • Stabil. Az utolsó verzió 2014-ben jelent meg
  • Széles körben dokumentált, különösen a tudományos irodalomban
  • Rengeteg valós felhasználás. Több milliárd eszköz

x86-64 assembly

  • Bár az x64 kiterjesztése, sok új funkciót adtak hozzá, többek között:
    • 64 bites egész számok támogatása
    • további regiszterek
    • SSE utasítások (vektorutasítások)
    • relatív adatelérés (hatékonyabb megosztott könyvtárak használatakor)
    • No-Execute bit (biztonsági funkció, amely megakadályozza a kód végrehajtását a memória bizonyos lapjain)
  • Ismerős. Mivel az x86 utasításkészletet terjeszti ki, viszonylag könnyen megtanulható azoknak, akik ismerik az x86 utasításkészletet Kiterjedt és részletes dokumentáció
  • Stabil. Bár rendszeresen érkeznek új verziók, a mag rendkívül stabil és visszafelé kompatibilis marad

WebAssembly

  • A veremalapú WebAssembly virtuális gép karcsú és egyszerű a fizikai processzorok assembly nyelveihez képest (a RISC-et is beleértve). Ez viszonylag könnyűvé teszi, hogy ráfordítsunk.
  • A WebAssembly szöveges formátum S-kifejezés-„cukorral” ér el egy ismerős imperatív stílust, amit aztán veremalapú kóddá alakítanak. Az S-kifejezéseket használó formát „cukrozott formának” nevezik, és ez „cukortalanítódik” a másik formára, amely megfelel a binárisban lévőnek. Az S-kifejezéseket mindenki ismerősen fogja látni, aki valaha dolgozott LISP-pel
  • Erős interoperabilitás a JavaScripttel. Egyszerű adatot átadni a JavaScriptből és a JavaScriptbe. Fontos fenntartás: a WASM (még) nem teszi lehetővé a DOM elérését
  • Folyamatosan fejlődik. Nemcsak a WASM virtuális gépeket fejlesztik, hanem maga a szabvány is aktív fejlesztés alatt áll. Rengeteg új funkciót terveznek és dolgoznak ki, például SIMD-vel kapcsolatos utasításokat, szemétgyűjtést, szálakat, farokhívás-optimalizációkat és még sok mást
  • Biztonságos. A kód ellenőrzésen esik át, és homokozóban fut, ami a JavaScripthez vagy a natív assembly nyelvekhez képest nagyobb fokú statikus ellenőrzést nyújt. A szemantika jól definiált, így könnyű ellenőrizni és következtetni vele kapcsolatban

Kiemelkedő tulajdonságok

MIPS

  • Hatékonyság. A MIPS processzorok nagyon hatékonyak, ami kiválóvá teszi őket beágyazott rendszerekhez.
  • Teljesítmény. Kiváló teljesítmény, ezért használták a MIPS-et szuperszámítógépekben
  • Könnyen megtanulható. Kevés utasítással, és mindegyik csak egy egyszerű dolgot tesz, ez könnyen megtanulhatóvá teszi. Kiváló oktatási célokra.

x86-64 assembly

  • Nagy teljesítményű. Az x86-64-et évtizedek alatt csiszolgatták, rengeteg utasítással, amelyek a teljesítményt segítik. Erre példa a SIMD (Single Instruction, Multiple Data), vagyis olyan utasítások, amelyek... nos, lehetővé teszik, hogy egy utasítás párhuzamosan több adaton fusson.
  • Mindenütt jelen van. Az x86-64-et futtató eszközök mindenhol megtalálhatók. Az Intel és az AMD CPU-i is megvalósítják. Jó ideje ez a de facto szabvány
  • Rendszeresen frissül. Pl. új vektorutasítások, az SSE3-5-tel, AVX-szel, AVX-512-vel és egyebekkel

WebAssembly

  • Hatékony. A bináris formátum tömör, és egyetlen gyors menetben dekódolható, ellenőrizhető és lefordítható. Emellett streamelhető, ami lehetővé teszi, hogy a dekódolás, az ellenőrzés és a fordítás a lehető leghamarabb elkezdődjön, még azelőtt, hogy minden adat megérkezett volna. Ráadásul párhuzamosítható is. Ez ideálissá teszi nagy teljesítményű webalkalmazásokhoz.
  • Kiváló fordítási cél. Lehetővé teszi, hogy sok nyelv kódja fusson a weben. A legtöbb jelentős nyelv támogatja a WebAssembly binárisokra fordítását, ami azt jelenti, hogy a kódod a weben futhat anélkül, hogy JavaScriptet kellene írnod. Néhány nyelv nem a kódodat fordítja WebAssemblyre, hanem magát a futtatókörnyezetet, amely aztán változatlan bytecode-ot futtathat.
  • Könnyű élesíteni és futtatni. Mindössze egy virtuális gépre van szükség, amely értelmezni tudja a bytecode-ot, és minden nagyobb böngésző tartalmaz egyet.
  • Nincs a webhez kötve, szerveroldalon is futtatható. A WebAssembly System Interface (WASI) egy interfész (ABI és API), amelyet úgy terveztek, hogy bármely platformra hordozható legyen. Hasonló a POSIX-hez (a Unix-rendszerek szabványos interfészeihez), és olyan dolgokat nyújt, mint az I/O. A biztonság a tervezésének kulcsfontosságú része, ami magában foglalja a homokozást és a képességközpontú felépítést (például fájlokhoz vagy socketekhez kifejezetten engedélyt kell kérni). A WASI-ban az is benne rejlik, hogy könnyen összekapcsolhatók legyenek a nyelvek. Solomon Hykes, a Docker társalapítója 2019-ben ezt írta: „Ha a WASM+WASI létezett volna 2008-ban, nem kellett volna megalkotnunk a Dockert”

Melyiket válaszd

  • Ha még soha nem dolgoztál assembly nyelvvel, valószínűleg a WebAssembly a legkönnyebb kezdés. Ha viszont olyan assembly nyelvet szeretnél tanulni, amely gépi kódra fordul, próbáld ki a MIPS assemblyt
  • Ha x86-64-es gépen dolgozol (nagyon valószínű), próbáld ki az x86-64 assemblyt
  • Ha ismered a LISP-et, értékelni fogod, hogy a WebAssembly S-kifejezéseket használ
  • Ha webalkalmazásokkal dolgozol, a WebAssembly a leglogikusabb választás
  • Ha fontos neked a teljesítmény, az x86-64 és a MIPS kiváló választás. Ha pedig a webes teljesítmény érdekel, próbáld ki a WebAssemblyt
1. Nov 2023 · Hasznosnak találtad?