@t[Hardver, szoftver]~~META:date created = 2007-01-27~~ Régóta visszatérő kérdés, hogy mit jelent ez a két szó és mi a különbség a kettő között. Vizsgáljuk meg egy kicsit ezt a témakört és ami még eszünkbe jut róla. ==== A hardver és a szoftver ==== Azt szoktuk mondani, hogy a hardver a „vas”, a dolgoknak az a része, amit kézbe lehet fogni, a boltban meg lehet venni – és közben nem vesszük észre, hogy félrevezetjük szegény felhasználót. Hiszen a szoftvert (más néven: //program//ot) is megvesszük a boltban, kézbe fogjuk: CD-n vagy DVD-n, régebben floppylemezen, még régebben magnókazettán, újabban SD-kártyán. No meg le is töltjük a netről, persze, de ettől a különbség még nem tudatosul. A különbség az, hogy a hardver //anyagból// van, a szoftver pedig nincsen. Legfeljebb az //adathordozó// van anyagból, ami a szoftvert tárolja, de nem azonos magával a szoftverrel. Ahogy a CD-lemez (hanglemez, magnókazetta) sem azonos a rajta levő Beethoven-szimfóniával. Már csak azért sem, mert a szimfónia már jóval azelőtt is létezett, hogy Edison feltalálta a hangrögzítést. Kotta formájában akkor is meg lehetett venni, de a kotta se volt azonos a szimfóniával. A kotta és a magnószalag között látszatra elég sok különbség van, de igazából mindkettő egyfajta utasítássorozat, egy zenemű reprodukálásához szükséges használati utasítás, amit egyezményes nyelven írtak meg. A fő különbség az, hogy a kottát embereknek szánták, a magnószalagot pedig egy elektromágneses olvasófej számára. Hasonlók a szoftverek terén is vannak. A számítógép éppen abban különbözik minden más szerkezettől, hogy maga a gép (a hardver) nem tud semmit. Mint az újszülött, vagy mint egy olyan szakács, aki a szerződés aláírása utáni percben beismeri, hogy egyetlen ételreceptet sem ismer. Ami azt illeti, az ételreceptek éppenséggel programok. //Hozzávalók: 1 finomra vágott vöröshagyma, 2 evőkanál dijoni mustár, 2 evőkanál citromlé, 1 dl tejföl, csipetnyi pirospaprika, só, bors. Elkészítés: A hagymát és mustárt összekeverjük egy tálban, hozzáadjuk a citromlét, sót, borsot, majd habverővel összekeverjük. Folyamatosan keverve hozzáöntjük a tejfölt, meghintjük paprikával, ízlés szerint ízesítjük. Salátára öntjük.// Ez a vinaigrette mártás elkészítésének programja, azazhogy receptje. Ha ezt elolvassa és megjegyzi egy olyan szakács, aki korábban nem tudott vinaigrette mártást készíteni, akkor most majd tudni fog. Fordítsuk le mindezt számítástechnikai nyelvre. A szakács a hardver. A recept a program. A szakácskönyv, ahol a recept le van írva (én egy [[http://konyhaweb.hu|online szakácskönyvből]] vettem), az adathordozó. Amikor a szakács elolvassa a receptet és elsajátítja azt, az a program betöltése. Amikor pedig nekiül vinaigrette mártást készíteni, akkor lefuttatja a programot. //A Neumann-elv// Nézzük meg a szakácsunkat részleteiben. Neumann János, a számítógépek atyjának is nevezett magyar matematikus az 1940-es években dolgozta ki a modern számítógépek alapelvét, ami azóta se változott. Eszerint a számítógép a következő részekből áll: – egy központi egységből, amely a programot végrehajtja; – egy memóriából, amely a programot és az adatokat együtt tárolja; – egy vagy több bemeneti egységből, amikkel az adatokat bejuttatjuk a gépbe; – egy vagy több kimeneti egységből, amikkel a gép közli a műveletek eredményét. A memória fontos tulajdonsága, hogy programot és adatot vegyesen tárol. Azazhogy tulajdonképpen kizárólag adatot tárol, mert a program is adatokból áll. A számítógép központi egysége (amit //processzor//nak, angol rövidítéssel //CPU//-nak [Central Processing Unit, központi feldolgozó egység] hívnak) abban különbözik a szakács központi egységétől, hogy kizárólag számokkal tud dolgozni. A számítógépek azért tudják együtt tárolni a programokat és a legkülönbözőbb fajta adatokat, mert mindent átváltoztatnak számmá. ==== Számítógép a parkban ==== Egy szép nagy park és egypár iskolai osztály remekül alkalmas a számítógép működésének modellezésére. Ha az olvasó tanár, netán katonai osztagot parancsnokol, ki is próbálhatja. Első kísérletünkben felsorakoztatunk nyolc embert, a nyakukba akasztott piros táblákon számokkal. Ezekkel: 1, 2, 4, 8, 16, 32, 64, 128. Az 1-es ember áll a szélen, a jobb kezénél a 2-es, és így tovább. A kilencedik embernek sapka van a fején, és az a dolga, hogy a sor előtt járkáljon és rámutogasson az emberekre. Ha valakire rámutat, az fölemeli vagy leengedi a jobb karját. A tizedik ember a Főnök, aki időnként mond egy egész számot 0-tól 255-ig. A sapkás a számot hallva végigmegy a sor előtt, a 128-astól indulva. Minden embernél a következőt csinálja: 1. ha az ember nyakában lógó szám kisebb, mint a hallott szám, akkor az emberrel fölemelteti a karját, különben leengedteti; 2. ha fölemeltette a karját, akkor az ember nyakában lógó számot kivonja a hallott számból; 3. továbblép a szomszéd emberhez, és az 1. lépéstől újrakezdi a kivonás eredményével. Miután mind a nyolc ember karját beállította, a sapkás félreáll. Ekkor a nyolc ember karja a Főnök által mondott számot mutatja: ha összeadjuk a számot mindazok tábláján, akiknek fönt van a karja, megkapjuk a számot. @png[blexbit213p] = 213 A nyolc piros táblás embert //bit//nek hívjuk: ők egy-egy kettes számrendszerbeli számjegyet mutatnak. Akinek lent van a karja, az 0-t jelent – akinek fent, az 1-es számjegyet képvisel. Második kísérletünkhöz már három ilyen sor kell. A piros táblások előtt fölállítjuk a zöld táblásokat, azok előtt pedig a kékeket: @png[blexbit213p] = 213 @png[blexbit117z] = 117 @png[blexbit0k] = 0 A képen a Főnök 213-at állított be a pirosaknak, 117-et a zöldeknek, a kékek pedig még várnak. A Főnök most azt mondja: **ÉS!** Ezt hallva a sapkás végigmegy a kék sor előtt, és mindegyik ember mögé benéz. Ha két felnyújtott kart lát, akkor a kék emberrel is fölemelteti a karját; ha csak egyet vagy egyet sem, akkor leengedve hagyja. Ez lesz az eredmény: @png[blexbit213p] = 213 @png[blexbit117z] = 117 @png[blexbit85k] = 85 A kék sor most a 85-ös számot adja ki. A Főnök most azt mondja: **VAGY!** A sapkás megint végigmegy a kék sor előtt. Most azt figyeli, hogy lát-e legalább egy felnyújtott kart a kék mögött (a kék nem számít). Ha igen, akkor felnyújtatja a kék karját; ha nem, akkor leengedteti. Ez lesz az eredmény: @png[blexbit213p] = 213 @png[blexbit117z] = 117 @png[blexbit245k] = 245 A kék soron a 245-ös számot látjuk. Ilyen és hasonló műveletek segítségével bármilyen számítást elvégezhetünk (de lehet, hogy nagyon sok kell majd belőlük). De most lépjünk egy szinttel följebb. A harmadik kísérletben egy sort állítunk föl tíz emberből, akik mellükön az 1, 2, 3, 4 stb. számokat viselik. Ők a //memóriacellák.// Egy ember, aki a //programozó// névre hallgat, egy jegyzettömb minden lapjára felír valamit, aztán a lapot átadja a memóriacelláknak, sorban egymás után. Kicsit odébb egy nagy tábla is van, amire írni lehet, és egy papírkosár. Most a sapkás emberen a sor, akinek az a dolga, hogy az 1. memóriacellától kezdve sorban kérje el a papírt mindenkitől, és hajtsa végre, ami rá van írva. (De a papírt mindig adja vissza.) Nézzük, mit fog csinálni egy elképzelt esetben. Az 1-es számú embertől kapott cédulán ez áll: //legyen 8=1.// Ezt úgy kell érteni, hogy a 8. ember kapjon egy cédulát, amin az 1-es szám áll. A sapkás ráírja a jegyzettömbjére az 1-es számot, letépi a cédulát, átadja a 8. embernek, aztán folytatja munkáját a 2-es emberrel. Az ő papírján ez van: //legyen 9=2.// A sapkás felírja a 2-es számot, a cédulát odaadja a 9. embernek, és visszatér a 3. emberhez. A 3. ember papírján ez áll: //legyen 10=8+9.// Ami nem azt jelenti, hogy össze kell adni nyolcat és kilencet, hanem a 8. és a 9. ember papírján szereplő számokat kell összeadni, és az eredményt egy cédulán átadni a 10. embernek. A sapkás szépen visszaballag a 8. és a 9. emberhez, megnézi a céduláikat (mintha nem ő írta volna fel azokat fél perccel korábban), összeadja a számokat, és az eredményt, 3-at egy cédulán odaadja a 10. embernek. Következik a 4. ember. //Írd le 10-et.// Ami most sem a 10-es számot, hanem a 10. ember cédulájának tartalmát jelenti. A sapkás visszamegy a 10. emberhez, megnézi a céduláját, a rajta levő 3-as számot fölírja a táblára, és folytatja a munkát. Az 5. ember papírján ez áll: //legyen 8=9.// A sapkás megnézi a 9. ember papírját, amin a 2-es szám van, ezt lemásolja, átadja a 8. embernek, aki az előző papírját (amin 1-es volt) bedobja a papírkosárba. A 6. ember cédulájának szövege: //legyen 9=10.// A sapkás megismétli az előző műveletet, csak most eggyel odébb. A 7. ember utasítása: //ha 10 kisebb a 300-as számnál, akkor folytasd 3-tól, különben állj le.// A sapkás megnézi, mi áll a 10. ember céduláján. Még mindig 3, az összeadás végeredménye. Ez kisebb 300-nál (amit most konkrét számként, nem memóriacella sorszámaként kell érteni), tehát a sapkás visszamegy a 3. emberhez. //Legyen 10=8+9,// ez áll a papíron, mint legutóbb. Most a 8. embernél 2 van, a 9-nél 3, a 10. ember papírjára tehát 5 kerül. 4. ember: //írd le 10-et.// A sapkás megnézi a 10. ember papírját és felírja a táblára az 5-ös számot a korábban odaírt 3-as alá. 5. ember: //legyen 8=9.// A sapkás lemásolja a 9. ember papírjáról a 3-as számot, és odaadja a 8-nak, aki kidobja a korábbi papírt. 6.: //legyen 9=10.// 7.: //ha 10 kisebb a 300-as számnál, akkor folytasd 3-tól, különben állj le.// A 10. ember céduláján most 5 áll, tehát megint folytatni kell 3-tól. Ahogy a sapkás ide-oda járkál a 3., 4., 5., 6. és 7. ember utasításait végrehajtva, olvasgatja és cserélgeti a cédulákat a 8., 9. és 10. ember kezében, a táblára szép sorban a következő számok kerülnek: 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 és 377. Amikor ezt az utolsó számot is felírta, a 7. emberhez érve azt találja, hogy a 10. embernél levő szám 377, nagyobb 300-nál, ezért befejezi a munkát. Mit csináltunk most? Írtunk egy //program//ot (az első hét ember céduláján vannak), amely kiírja (a táblára) a Fibonacci-sorozatot. (Ez egy matematikai sorozat, amely az 1-es és 2-es számokkal kezdődik, a harmadiktól kezdve pedig minden elem az előző két elem összege. Itt csak a 3-astól kezdve írtuk ki őket.) A program hét //utasítás//ból áll, amik külön cédulákon vannak. Az első két utasítás az //inicializálás,// vagyis a programban használt //változók// értékeinek beállítása. A 8., 9. és 10. memóriacellát használtuk változónak, ezek értéke folyamatosan változott a program végrehajtása során. A program további része egyetlen //ciklus// volt, vagyis olyan programrész, amit sokszor egymás után, ciklikusan kell ismételni. És láttunk példát //elágazás//ra is: a 7. ember céduláját, ahol össze kellett hasonlítani két értéket, és az eredménytől függően kétféleképpen cselekedni (folytatni a 3. embertől vagy abbahagyni). És megint látjuk a különbséget hardver és szoftver között. A hardver: az emberek. A sorban álló tíz ember jelképezi a memóriát, a sapkás pedig a processzort. A szoftver pedig a papírok tartalma. ==== A gépi kód és az assembly ==== A valódi számítógép is nagyjából úgy hajtja végre a programokat, ahogy a parkban láttuk. A Fibonacci-sorozatos programunk jól mutatja a számítógép gondolkodásmódját. //A gép nem emlékszik.// Ha az olvasó és baráti köre csakugyan megvalósítaná a példát, a sapkás ember emlékezne, hogy legutóbb milyen számokat írt a változókat képviselő emberek céduláira, és nem szaladgálna folyton oda, hogy megnézze azokat. A processzor erre nem képes, neki tényleg minden egyes alkalommal meg kell nézni minden egyes memóriacellát. //A gép nem gondolkodik.// Egy valódi sapkás ember a ciklus többedik ismétlésénél már tudná, mi a dolga, és nem olvasgatná a program minden egyes utasítását újra meg újra; sőt valószínűleg rájönne, hogy a Fibonacci-sorozatot kell felírnia a táblára, és magától csinálná. A processzor minden egyes alkalommal minden egyes utasítást úgy hajt végre, mintha akkor látná először. Nincsen emlékezete. A processzor persze nem magyar nyelvű feliratokat olvasgat a céduláin, hanem számokat. Sorban nézi meg a memóriacellákat, akárcsak a mi sapkás emberünk, és a bennük talált számokat utasításként értelmezi. Minden szám más utasítást jelent. Ezek a számok a processzor anyanyelve, amit //gépi kód//nak hívnak. Így például a PC processzora a 120-as számot úgy értelmezi, hogy a B regiszterben levő számot másolja át az A regiszterbe. A regiszterek speciális memóriacellák, amik magában a processzorban találhatók. 121 azt jelenti, hogy a C regisztert kell átmásolni az A-ba, 122 a D regiszter, és így tovább. Ilyen másolásokból nagyon sokféle van. Vannak matematikai műveletek is, például 128 azt jelenti, hogy A és B tartalmát össze kell adni és az eredményt A-ba tenni. 144 viszont kivonja A-ból B-t és ennek az eredményét teszi vissza A-ba. Vannak növelő és csökkentő utasítások: 4 azt jelenti, hogy B értékét eggyel meg kell növelni, 5 pedig azt, hogy csökkenteni. Megvannak a fölemelt karú emberkékkel bemutatott logikai műveletek is, például 160 azt jelenti, hogy A és B tartalmán ÉS műveletet kell végezni és az eredményt A-ba tenni. Ha egy programot így, csupa számokkal írunk le, akkor kicsit nehezen érthető. Főleg azért, mert az utasítások egy része több byte-ból áll (például 221 és 9 azt jelenti, hogy az IX és a BC regiszterek tartalmát össze kell adni és az eredményt IX-be tenni), és számos utasítást egy vagy több byte követ, amikkel csinálni kell valamit (például a 62-es számot egy byte követi, amit bele kell tölteni az A regiszterbe). Mindezek miatt a gépi kód egyetlen byte-járól se tudhatjuk, hogy micsoda: utasítás, utasítás második byte-ja vagy olyan érték, amivel csinálni kell valamit //(operandus).// Például a 223, 5, 71 számsor, ha így hajtjuk végre, azt jelenti: vond ki A tartalmából az 5-ös számot és a C jelzőbit értékét, majd pedig A-t másold át B-be. De ha az 5-östől kezdjük, akkor azt jelenti: eggyel csökkentsd B értékét, majd pedig A-t másold át B-be (felülírva az előző utasításban csökkentett értéket). A gépnek persze mindegy. A programozó viszont szeretne kiigazodni a programon, amit ír. Ezért kitalálta az //assembly//t, ami nem más, mint a gépi kód átalakítása olvasható szöveggé. Számok helyett rövidített angol szavakat írunk, amiket //mnemonik//nak (emlékeztetőnek) hívunk. Egy regiszter átmásolása egy másik regiszterbe például a Z80-as processzoron így íródik: LD A, B = a B regisztert másold át az A-ba. Az LD a //load,// töltés rövidítése. Összeadás (angolul addition): ADD A, B. Kivonás (subtraction): SUB A, B. Növelés (increase): INC A. Csökkentés (decrease): DEC B. Az ÉS művelet: AND A, B. A PC-k processzorán LD helyett MOV-ot használunk, de ez végül is mindegy, hiszen a processzor úgyse érti. Neki le kell fordítani. Írtak olyan programokat, amik a szövegszerkesztőben megírt assembly nyelvű programot le tudják fordítani gépi kódra. Nem nehéz feladat, hiszen minden mnemoniknak egy utasításkód felel meg, csak ki kell deríteni, hogy mikor melyik. Ez a fordítóprogram az //assembler.// errwrp: lda errsin        ora a        jz errwr3        mvi e, 1ah        call redout        lhld redbp        mov a, l        cpi redbuf and 0ffh        cnz redwrt        lxi d, redfcb        call close2 errwr3: lda errf        ora a        jnz errab2        inr a        sta nomore        ret Így néz ki egy programrészlet egy modern assembler nyelvén, ahol a felhasználó //címké//ket definiálhat, amikre hivatkozni lehet. A gépi kód (avagy az assembly – a kettő végül is ugyanaz, csak az írásmódja más) a processzor anyanyelve, ami azt jelenti, hogy az egyetlen nyelv, amit a számítógép megért. Bármilyen nyelven írnak programot, azt le kell fordítani gépi kódra ahhoz, hogy a számítógép végrehajthassa. A programozók ma már ritkán dolgoznak assemblyben, inkább magas szintű programnyelveket használnak – de ez már egy másik történet. @blogf[!]