Számítógép architektúra kidolgozott tételsor
Szegedi Tudományegyetem Szeged, 2007.
Tartalomjegyzék 1.
Fordítás, értelmezés ........................................................................................................................ 4
2.
Numerikus adatok ábrázolása: fixpontos ábrázolás, konverzió számrendszerek között. Negatív számok ábrázolásai. ......................................................................................................................... 5
3.
Lebegőpontos számok. IEEE 754 szabvány. ..................................................................................... 8
4.
Hamming távolság. Hibaészlelő, hibajavító kódok. ....................................................................... 10
5.
Digitális logikai szint. Kapuk. Boole algebra. Boole függvények megvalósítása, áramköri ekvivalenciája. A Boole algebra legfontosabb azonosságai, dualitás. ........................................... 12
6.
Kombinációs áramkörök, multiplexer, demultiplexer, dekódoló, összehasonlító, programozható logikai tömbök. .............................................................................................................................. 15
7.
Aritmetikai áramkörök. Léptető, fél és teljes összeadó, ALU, átvitel továbbterjesztő és kiválasztó összeadás. ...................................................................................................................................... 17
8.
Nem kombinációs áramkörök. Óra, tárolók, flip-flop-ok............................................................... 20
9.
Processzor szintű párhuzamosítás ................................................................................................. 24
10. Gyorsító tár (cache). Találati és hiba arány. Közös és osztott gyorsító tár. Direkt leképezésű és halmaz kezelésű gyorsító tár. Memóriába írás. ............................................................................. 26 11. Operandus megadás módjai. Közvetlen operandus, direkt, regiszter, regiszter-indirekt, indexelt, bázis-index címzés ......................................................................................................................... 29 12. Sínek. Sín Protokoll. Master – szolga. Sín vezérlő, vevő, adóvevő. Sín szélessége. Sokszorozott sín. Sín időzítés: szinkron, aszinkron sín, teljes kézfogás. Sín ütemezés. Sín műveletek. ............. 31 13. Általános soros sín ......................................................................................................................... 34 14. PCI Express ..................................................................................................................................... 37 15. A CPU részei, feladatai. CPU, adatút. Három, kettő, egy és nulla címes utasítások...................... 41 16. Mikroarchitektúra szint. Az ALU-val végezhető műveletek. Memória műveletek. ALU és az adatút vezérlése. Mikroutasítások: Mic-1. Mic-1 működése. ................................................................... 43 17. A Mic-1 memória ciklusa. .............................................................................................................. 47 18. MPC új értékének kialakulása Mic-1-en. ....................................................................................... 48 19. A WIDE utasítás hatása és működése Mic-1-en. ........................................................................... 49 20. Parallel Input/Output (PIO), valódi és memória leképezett I/O eszközök. Teljes és részleges címdekódolás. Programozott és megszakítás vezérelt I/O. DMA. ................................................ 50 21. Utasítás szintű párhuzamosítás, csővezeték (pipelining). ............................................................. 52 22. Utasítás betöltő egység. Mic – 2.................................................................................................... 54 23. Csővonalas terv: a Mic-3................................................................................................................ 56 24. Egy hétszakaszú szállítószalag: a Mic-4 csővezetéke..................................................................... 57
2.
25. Elágazás, eltolási rés, statikus és dinamikus elágazás jövendölés ................................................. 60 26. Sorrendtől eltérő végrehajtás, szuperskaláris architektúra, függőségek, regiszter átnevezés, feltételezett végrehajtás................................................................................................................ 62 27. Feltételes végrehajtás, predikáció ................................................................................................. 64 28. A Pentium 4, az UltraSPARC III és az I-8051 mikroarchitektúrája. ................................................ 65 29. A Pentium 4, az UltraSPARC III és az I-8051 mikroarchitektúrájának összehasonlítása ................ 70 30. Gépi utasítási szint. Memória modellek, memória szemantika. A Pentium 4, az UltraSPARC III és az I-8051 regiszterei....................................................................................................................... 71 31. A Pentium 4, az UltraSPARC III, az I-8051 utasítás formátumai, címzési módjai........................... 75 32. Veremcímzés. Fordított lengyel (postfix) jelölés. Dijkstra algoritmusa. Postfix alakú formulák kiértékelése ................................................................................................................................... 79 33. Vezérlési folyamat. Szekvenciális vezérlés, elágazás, ciklus szervezés, eljárás, rekurzív eljárás, korutinok, megszakítás, csapda ..................................................................................................... 81 34. Operációs rendszer szintje. Virtuális memória. Lapméret, elaprózódás. Szegmentálás. A Pentium 4 és az UltraSPARC III virtuális memóriája..................................................................................... 84 35. Terminál. Modemek, jelzési, adatátviteli sebesség. ...................................................................... 90 36. ADSL, kábeles internet................................................................................................................... 93 37. Az Intel 8086/88 utasításai (adatmozgató, aritmetikai, logikai, string-kezelő, bitléptető/forgató, vezérlésátadó, processzor-vezérlő, input/output utasítások, program megszakítás, szemafor). 97 38. Pszeudo operátorok. Egyszerű adatdefiníciós utasítások. Struktúra, rekord (definíció, hívás, mezőre hivatkozás) ...................................................................................................................... 103 39. Eljárás (deklaráció, hívás). Paraméter átadás/átvétel különböző módjai. .................................. 106 40. Lokális adatterület, rekurzív és reentrant eljárások. ................................................................... 108 41. Feltételes fordítás ........................................................................................................................ 109 42. Makró (definíció, hívás), blokk ismétlés ...................................................................................... 110 43. Címkék, változók, konstansok, kifejezések .................................................................................. 115 44. Szegmens definíció, szegmens csoport, aktív szegmensek kijelölése, globális szimbólumok..... 119 45. Egyszerûsített lexikális elemzõ .................................................................................................... 121 46. Két menetes assembler fordító ................................................................................................... 125 47. Az include utasítás. Az include utasítás feldolgozása a fordítás során. ....................................... 127 48. Makró generátor.......................................................................................................................... 128 49. Szerkesztő .................................................................................................................................... 129 50. Time sharing (időosztás). binding (cím hozzárendelés), dinamikus szerkesztés ......................... 131 51. Programok hangolása .................................................................................................................. 133
3.
1.
Fordítás, értelmezés
A probléma két oldalról is megközelíthető. Mindkettő az ember számára a gépi nyelvnél kényelmesebben használható új utasításrendszer tervezésére épül. Az új utasítások együttese is egy nyelvet alkot – nevezzük ezt L1-nek -, ugyanúgy, ahogy a beépített utasítások nyelvet alkotnak – legyen ez utóbbi L0. A kétféle megközelítés abban különbözik egymástól, hogy a számítógép hogyan hajtja végre az L1 nyelven írott porgramokat, miközben csak a saját, L0 gépi nyelvén írt programokat képes végrehajtani. Az L1 nyelvű program végrehajtásának egyik módja az, hogy először minden utasítását helyettesítjük az L0 nyelv utasításainak egy vele ekvivalens sorozatával. Az így nyert program teljes egészében az L0 utasításaiból áll. Ekkor az eredeti L1 nyelvű program helyett a számítógép ezt az L0 nyelvű programot hajtja végre. Ezt a módszert fordításnak nevezzük. A másik módszer szerint megírunk egy L0 nyelvű programot, amely az L1 nyelvű programokat bemenő adatokként kezeli, és úgy hajtja végre azokat, hogy minden utasításukat elemzi, és a vele ekvivalens L0 nyelvű utasítássorozatot azonnal végrehajtja. Ez a módszer nem igényli, hogy először egy új, L0 nyelvű programot állítsunk elő. A módszert értelmezésnek, a végrehajtó programot pedig értelmezőnek nevezzük. A fordítás és az értelmezés módszere hasonló. Végül is mindkettő az L1 utasításait az L0 utasításaiból álló sorozatok végrehajtásával teljesíti. A különbség csak az, hogy a fordítás esetében először az egész L1 nyelv programot átírjuk L0 nyelvűvé, majd az L1 programtól megszabadulunk, és az L0 programot töltjük a számítógép memóriájába, és azt hajtjuk végre. A végrehajtás során az újonnan előállított L0 program az, ami fut, és ami a számítógépet vezérli. Az értelmezés esetében L1 minden utasításának elemzését és dekódolását az utasítás azonnali végrehajtása követi. Nem keletkezik lefordított program. A számítógépet az értelmező vezérli, számára az L1 nyelvű program csak adat. Mindkét módszert – és egyre gyakrabban a kettő kombinációját is – széles körben alkalmazzák.
4.
2.
Numerikus adatok ábrázolása: fixpontos ábrázolás, konverzió számrendszerek között. Negatív számok ábrázolásai.
A legtöbb számítógép egy szám tárolására szóló memóriája fix méretű, rögzítették a számítógép tervezésekor. Bizonyos erőfeszítésekkel a programozó tudja a számokat ábrázolni az eredeti fix méretnél kétszer, háromszor, sőt többször nagyobb helyen is, de ez nem változtatja meg a probléma természetét. A számítógépes erőforrásnak ez a véges természete csak azokkal a számokkal enged foglalkozni, amelyek fix számú számjeggyel ábrázolhatók. Ezeket a számokat véges pontosságú számoknak hívjuk. Fixpontos számok például az előjeles, kétjegyű decimális számok. Ábrázolási tartomány: -99 ; +99 Pontosságuk (két szomszédos szám különbsége): 1 Maximális hiba: (az ábrázolási tartományba eső) tetszőleges valós szám, és a hozzá legközelebb lévő ábrázolható szám maximális különbsége: 1/2. Az ember általában tízes számrendszert használ, de a számítógépek használatánál kényelmesebb nem tízes alapú, hanem más rendszereket használni. A legfontosabb alapszámok a 2, a 8 és a 16. Ezen alapszámokra épülő számrendszereket sorrendben kettesnek (bináris), nyolcasnak (oktális) és tizenhatosnak (hexadecimális) nevezzük. A decimális számok 10 decimális jegyből épülnek fel: 0 1 2 3 4 5 6 7 8 9. Szemben a bináris számokkal, amelyek nem tíz jegyet használnak, hanem szerkeszthetünk meg: 0 1.
2 jegyből
Az oktális számok 8 oktális jegyből épülnek fel: 0 1 2 3 4 5 6 7. A hexadecimális számoknál 16 jegy szükséges. Így 6 új szimbólum bevezetésére van szükség. Kényelmes bevezetni az A-tól F-ig nagybetűket, amelyek a 9-et követő hat számjegy számára szolgálnak. Így a számok a következő jegyekből épülnek fel: 0 1 2 3 4 5 6 7 8 9 A B C D E F. Az alábbi táblázat a 4 számrendszerbeli megfelelőket mutatja be: Decimális 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Bináris 0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
Oktális 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17
5.
Hexadecimális 0 1 2 3 4 5 6 7 8 9 A B C D E F
Nagyon fontos az egyes számrendszerek közötti konverzió. Bináris ->Oktális: Osszuk hárombites csoportokra a számot. Az első 3 bit közvetlenül balról (vagy jobbról) a decimális pont után (ezt gyakran bináris pontnak hívjuk) alkot egy csoportot, a tőlük balra eső 3 bit a következő csoportot és így tovább. Minden egyes ilyen hárombites csoportot direkt módon konvertálhatunk egy egyszerű oktális számjegyre 0-tól 7-ig. Lehet hogy szükséges egy vagy két kezdő vagy záró 0-val kitölteni a hárombites sorozatokat. Pl.:
0 001 100 101 001 000 . 101 101 100 1
4
5
1
0 . 5
5
4
Oktális -> Bináris: Minden oktális számjegyet cseréljünk le egy vele ekvivalens hárombites számra. Hexadecimális -> Bináris: Hasonló az oktálisból binárisba történő konverzióhoz, kivéve, hogy minden hexadecimális jegy megfelel egy négybites csoportnak az előzőekben használt három bit helyett. Pl.:
7
B
A
3 . B
C
4
0111 1011 1010 0011 . 1011 1100 0100 Bináris -> Hexadecimális: Mint a binárisból oktálisba, csak 3 helyett 4 bites csoportokat kell létrehozni. Decimális -> Bináris: Pl.:
23,375 átszámítása kettes számrendszerbe. Egész rész: /2 23 11 5 2 1
Tört rész: marad 1 1 1 0 1
egész 0 1 1
101112
*2 0.375 .750 .500 .000
0,0112
23,375 = 10111,0112 Véges tizedes tört nem biztos, hogy binárisan is véges!
6.
Bináris -> Decimális: A legegyszerűbb módszer, amikor összegezzük a kettő azon hatványait, ahol 1-es volt a kitevőben. Pl.: 10110 = 24 + 22 + 21 = 16 + 4 + 2 = 22. A negatív számok megjelenítésére négy különböző módszert is használnak. 1. Előjeles nagyság (signed magniture) Ebben a rendszerben a legbaloldalibb bit az előjelbit (a 0 +, és az 1 -), és a maradék bitek jelzik a szám abszolút értékét. 2. Egyes komplemens (one’s complement) Az egyes komplemensnek is van előjelbitje, amelynél a 0 jelenti a pozitív, 1 a negatív számot. Azért, hogy negáljuk ezt a számot, minden 1-est 0-ra cseréljük, és minden 0-t 1-esre. Ez természetesen az előjelbitre is vonatkozik. Az egyes komplemens képzése elavult rendszer. Pl.: +25 =00011001, - 25 =11100110. Jellemzők: a nulla kétféleképpen ábrázolható, a legkisebb szám -127, a legnagyobb 127. 3. Kettes komplemens (two’s complement) A kettes komplemens szintén tartalmaz előjelbitet, amely 0 a pozitív, 1 pedig a negatív számok esetében. Egy szám átváltásánál negálni kell az eredeti számot, valamint hozzá kell adni egyet. Pl.: +25 =00011001 -25 =11100110 egyes komplemens, -25 =11100111 kettes komplemens. Jellemzők: a nulla egyértelműen ábrázolható, a legkisebb szám -128, a legnagyobb 127. 4. Többletes A negyedik rendszer, amit m bites szám esetében 2m-1-többletesnek hívunk, úgy tárol egy számot, mint saját magának és a 2m-1-nek az összegét. Például egy 8 bites számra m = 8, a rendszert 128 többletesnek nevezzük, és egy számot úgy tárolunk, mint a valódi számot plusz 128. Így a -3 megfelelője: -3 + 128 = 125, azaz a -3-at egy nyolcbites számként ábrázolva 125-öt jelent (01111101). A -128-tól +127-ig elhelyezkedő számokat így meg tudjuk feleltetni 0-tól 255-ig terjedő számoknak, amelyeket 8 bites pozitív számként fejezhetünk ki. Érdekességképpen igaz, hogy ez a rendszer azonos a kettes komplemenssel fordított előjelbittel. Pl.: +25 = 10011001 25 + 128 = 153 - 25 = 01100111 - 25 + 128 = 103 Jellemzők (128 többlet esetén): a nulla egyértelműen ábrázolható, a legkisebb szám -128, a legnagyobb 127.
7.
3.
Lebegőpontos számok. IEEE 754 szabvány.
A lebegőpontos számok: A nagyság és a pontosság szétválasztásának módja, hogy a számokat a jól ismert tudományos jelöléssel fejezhetjük ki:
n f * 10 e ahol az f a törtrész (fraction), vagy mantissza (mantissa) és az e egy pozitív vagy negatív szám, amelyet kitevőnek vagy exponensnek (exponent) hívunk. Ennek a jelölésnek a számítógépes verzióját lebegőpontos számnak (floating point) hívjuk. 3,14 = 0,314 x 101
Pl.:
vagy
0,000001 = 0,1 x 10-5 = 1,0 x 10-6
A kitevő nagysága a nagyságrendet tartalmazza, a pontosságot pedig a törtrész jegyeinek a száma határozza meg. Mivel különböző módon fejezhetünk ki egy adott számot, az egyik formát általában szabályosnak nevezzük a sok forma közül. A leggyakrabban a törtrész első számjegye az adott szám első, nullától különböző számjegye (normalizált alak). 254 = 0,0254 x 104 = 0,254x103 (= 2,54x102)
Pl.:
Megjegyzések:
A nulla ábrázolásához külön megállapodásra van szükség (általában csupa nulla számjegyből áll). A lebegőpontos ábrázolásoknál is meghatározható a legkisebb és a legnagyobb ábrázolható szám, továbbá a legkisebb és legnagyobb hiba.
Feladat: Ábrázoljuk nyolcas számrendszerben 254 10et: előjelbittel kezdve, a kitevő legyen 1 jegyű (3 bites), 4-többletes, a törtrész 4 jegyű. Megoldás: 254/8 6 31/8 7 3/8 3 3768, normalizált alak: 0,376x8 3, a megoldás: 0 111 011 111 110 000 2 = 0737608 + törtrész 4-többletes kitevő Máté: Architektúrák
1. előadás
43
8.
Az IEEE 754-es lebegőpontos szabvány: Körülbelül 1980-ig minden számítógépgyártónak saját lebegőpontos formája volt, természetesen mindegyik más és más. Ennél is rosszabb, hogy néhányan valóban rosszul kezdték a lebegőpontos számítási módszereket, amelyeknek néhány finomságát az átlag hardvertervező nem ismeri. Ezért az 1970-es évek végén az IEEE felállított egy bizottságot a lebegőpontos számítások szabványosítására. Ez a munka vezetett el az IEEE 754-es szabványhoz. A szabvány 3 formát (pontosságot) definiál, az egyszeres pontosságot (32 bit), a dupla pontosságot (64 bit) és a kiterjesztett pontosságot (80 bit). A kiterjesztett arra szolgál, hogy csökkentse a kerekítési hibákat. Ezt főleg a lebegőpontos aritmetikai egységben használják. Mind az egyszeres, mind a dupla pontosságú forma a kettes alapot használja a törtrészben, és a többletes jelölést a kitevőben. Mindkét forma egy előjelbittel kezdődik, ahol a 0 a pozitívat, 1 a negatívat jelöli. Ezután következik a kitevő, amely 127-többletes kitevőt használ a szimpla pontosságban és 1023-többletest a dupla pontosságban. A minimum (0) és a maximum (255 és 2047) kitevőket nem használjuk a normalizált számoknál, ezek használata speciális. Végül a törtrészek következnek, 23 illetve 52 biten.
IEEE 754 standard single 32 bites, double 64 bites (, extended 80 bites). típus
előjel
kitevőrész
| törtrész |
single
1 bit
8 bit 127-többletes
23 bit
double
1 bit
11 bit 1023-többletes
52 bit
single: Ha 0 < a kitevőrész < 255, a szám normalizált. Normalizált tört vezető 1-es bitje nincs ábrázolva! Máté: Architektúrák
1. előadás
Máté: Architektúrák
44
Normalizálatlan számok (IEEE 754, single) Ha a kitevőrész = 0 A bináris pontot 0 előzi meg (nincs ábrázolva). Az ábrázolt szám: ± (törtrész) * 2-127 -128 -127 Pl.: 2 = 2 * 0,100 ... 00002 = = 0000 0000 0100 ... 0000 2 = 0040 000016 - 2-150 = - 2-127 * 0,000 ... 00012 = = 1000 0000 0000 ... 0001 2 = 8000 000116 2-127 = 2-127 * 1,000 ... 00002 = 0000 0000 0111 ... 1111 2 = 007F FFFF16 ± kitevőrész 0. törtrész Máté: Architektúrák
1. előadás
Normalizált számok (IEEE 754, single) 0 < kitevőrész < 255 kitevőrész = kitevő + 127, 127 többletes. Lehetséges kitevők: -126, -125, ... , +127. Közvetlenül a törtrész elé kell képzelni egy 1-est (implicit bit) és a bináris pontot. Az ábrázolt szám: ± (1 + törtrész) * 2kitevő Pl.: 1 0011 1111 1000 ... 0000 2 = 3F80 000016 0,5 0011 1111 0000 ... 0000 2 = 3F00 000016 -1,5 1011 1111 1100 ... 0000 2 = BFC0 0000 16 ± kitevőrész 1. törtrész 1. előadás
45
Normalizálatlan számok (IEEE 754, single) Ha a kitevőrész = 255 Túl nagy számok (túlcsordulás): • (végtelen): pl. 1/0, • NaN (Not a Number): pl. /
Máté: Architektúrák
1
9.
1. előadás
47
4.
Hamming távolság. Hibaészlelő, hibajavító kódok.
Az elektromos hálózatban keletkező áramlökések és egyéb okok miatt a számítógépek memóriái néha hibáznak. Ezeknek a hibáknak a kiszűrésére bizonyos memóriák hibafelismerő vagy hibajavító kódot alkalmaznak. Ezek használata esetén minden memóriabeli szót kiegészítenek speciális bitekkel. Egy szó kiolvasása során a kiegészítő biteket ellenőrzik, hogy a hiba kiderüljön. Tegyük fel, hogy egy memóriabeli szó m adatbitből áll, ehhez adunk még r redundáns vagy más néven ellenőrző bitet. A teljes hossz legyen n (vagyis n = m + r). Egy n bites (m adatbitet és r ellenőrző bitet tartalmazó) egységet gyakran n bites kódszónak neveznek. Ha adott két szó, mondjuk 10001001 és 10110001, akkor megállapíthatjuk, hogy hány bitpozíción térnek el. Az ellenőrző kódszavak 3 bitpozíción különböznek. Az eltérő bitpozíciók számának megállapításához egy egyszerű logikai KIZÁRÓ VAGY műveletet kell végezni a két kódszón, majd megszámolni az eredmény 1-es bitjeit. Az eltérő bitpozíciók számát a két kódszó Hamming távolságának nevezzük. Ennek az a jelentősége, hogy ha 2 kódszó távolsága d, akkor d darab egyszeres bithibának kell előfordulnia, ahhoz hogy az egyik kódszó a másikba alakulhasson. Például az 11110001 és a 00110000 Hamming távolsága 3, mert 3 egyszeres bithiba szükséges ahhoz, hogy az egyik a másikba alakulhasson. Egy m bites memóriaszó esetén mind a 2m bitminta előfordulhat, de a redundáns bitek kiszámításának szabálya miatt a 2n kódszó közül csak 2m érvényes. Ha egy memóriaolvasás érvénytelen kódot ad, akkor a számítógép azonnal tudja, hogy memóriahiba lépett fel. Az ellenőrző biteket kiszámító algoritmus ismeretében meghatározható az összes érvényes kódszó listája, majd ebben a listában meg lehet keresni azt a két kódszót, amelynek a Hamming távolsága minimális. Ez az érték a teljes kódolás Hamming távolsága. Egy kódolás hibafelismerő és hibajavító képessége a Hamming távolságtól függ: d egyszeres bithiba felismeréséhez d+1 távolságú kódolás kell, mert ebben az esetben d egyszeres bithiba semmiféleképpen nem alakíthat át egy érvényes kódszót egy másik érvényes kódszóvá. Hasonlóképpen, d egyszeres bithiba javításához 2d+1 távolságú kódolás kell, mert így az érvényes kódszavak olyan távol vannak egymástól, hogy még d egyszeres bithiba esetén is az eredeti kódszó minden más kódszónál közelebb van, így egyértelműen meghatározható. Egyszerű hibafelismerő kódolásra példaként tekintsük azt a kódolást, amikor az adatbitekhez egyetlen paritásbitet adunk. A paritásbit értékét úgy határozzuk meg, hogy a kódszóban páros (vagy páratlan) számú 1-es legyen. Ennek a kódolásnak a távolsága 2, mert minden egyes bithiba hibás paritású kódot eredményez. Egyetlen bithiba felismeréséhez lehet használni. Ha hibás paritású szó kerül kiolvasásra a memóriából, akkor hibaüzenetet kapunk.
10.
Egy hibát javítani képes, kódoláshoz szükséges ellenőrző bitek száma: Szó hossza 8 16 32 64 128 256 512
Ellenőrző bitek 4 5 6 7 8 9 10
Teljes hossz 12 21 38 71 136 265 522
Hozzáadott bitek %a 50 31 19 11 6 4 2
Tetszőleges hosszúságú memóriaszavak hibajavító kódolására használt Hamming algoritmus, mellyel az elméleti alsó korlát számolható ki: A kódolás során r redundáns bitet adunk egy m bites szóhoz, így a kódszó teljes hossza n = m + r bit lesz. A biteket nem 0-val, hanem 1-gyel kezdődően sorszámozzuk, a legnagyobb helyi értékű lesz az 1-es sorszámú. Minden olyan bit paritásbit lesz, amelynek sorszáma 2 hatványa; a többi adatbit. Például egy 16 bites kódszóhoz 5 paritásbitet adunk. Az 1, 2, 4, 8, 16 pozíción vannak a paritásbitek, a többi mind adatbit. A memóriaszó összesen 21 bites. Ebben a példában páros paritást fogunk használni. Minden paritásbit meghatározott bitpozíciókat ellenőriz; a paritásbit értékét úgy állítjuk be, hogy az ellenőrzött pozíciókon lévő 1-esek száma páros legyen. Az egyes paritásbitek által ellenőrzött bitpozíciók: 1.bit: 2.bit: 4.bit: 8.bit: 16.bit:
1, 3, 5, 7, 8, 9, 11, 13, 15, 17, 19, 21 2, 3, 6, 7, 10, 11, 14, 15, 18, 19 4, 5, 6, 7, 12, 13, 14, 15, 20, 21 8, 9, 10, 11, 12, 13, 14, 15 16, 17, 18, 19, 20, 21
11.
5.
Digitális logikai szint. Kapuk. Boole algebra. Boole függvények megvalósítása, áramköri ekvivalenciája. A Boole algebra legfontosabb azonosságai, dualitás.
A digitális logikai szint a számítógép hierarchiáját bemutató táblázat legalján található, ez alkotja a számítógép igazi hardverét. Az alapelemek, amelyekből minden digitális számítógép felépül, meglehetősen egyszerűek. Digitális áramköröket készíthetünk néhány nagyon egyszerű elem különböző kombinálásával. A digitális áramkör egy olyan áramkör, amelyben csak két logikai érték van jelen. Tipikusan a 0 és az 1 Volt közötti jel reprezentál egy értéket (bináris 0) és a 2 és 5 Volt között ábrázol egy másik értéket (bináris 1). Más feszültségek nem megengedettek. A pici elektromos eszközök, amelyeket kapuknak hívunk, kétértékű jelek különböző függvényeit tudják kiszámítani. Ezek a kapuk alkotják azt a hardverbázist, amelyből minden digitális számítógép felépül. Minden modern digitális logika végül is azon a tényen alapul, hogy egy tranzisztor úgy tud működni, mint egy nagyon gyors bináris (kétállapotú) kapcsoló. Az alábbi ábrán bemutatunk egy bipoláris tranzisztort (a kör), mely be van ágyazva egy egyszerű 0 + Vcc Vki áramkörbe. A tranzisztornak három Bázis kapcsolata van a külvilággal: a Kollektor + Vcc 0 kollektor, a bázis és az emitter. Amikor Vbe a bemenő feszültség, Vbe bizonyos érték Emitter alatt van, a tranzisztor zárt állapotban NEM (NOT) kapu, inverter Tranzisztor van, és úgy viselkedik mint egy végtelen Szimbolikus jelölése: A X Igazság X A ellenállás. Ez azt okozza, hogy az 0 1 tábla: áramkör outputja, Vki közel van a Vcc erosíto Inverziós gömb értékéhez, ami egy külsőleg vezérelt 1 0 Máté: Architektúrák 2. eloadás 29 fezültség, tipikusan +5 Volt az ilyen típusú tranzisztoroknál. Amikor Vbe meghaladja a kritikus értéket, a tranzisztor kinyit, és úgy viselkedik, mint egy vezeték, és ezzel azt okozza, hogy a Vki -t lehúzza a földhöz (lecsökkenti a megállapodás szerinti 0 Voltra). Nagyon fontos dolog, hogy amikor a Vbe alacsony, akkor a Vki magas, és fordítva. Ez az áramkör így egy fordító (inverter), amely a logikai 0-t logikai 1-gyé konvertálja, és a logikai 1-et pedig logikai 0-vá.
NEM (NOT) kapu (3.1. ábra). + Vcc + Vcc
+ Vcc
Az ábrán két tranzisztor van egymás után sorba kötve. Ha V1 és V2 is magas, mindkét tranzisztor vezetni fog, és Vki alacsony lesz. Ha valamelyik bemenet alacsony, a megfelelő tranzisztor zárva lesz, és a kimenet pedig magas. Tehát a Vki akkor és csak akkor lesz alacsony, ha mind a V1, mind a V2 magas.
NEM-ÉS (NAND) kapu Igazság tábla:
+ Vcc Vki V2
A 0 0 1 1
B 0 1 0 1
X 1 1 1 0
Szimbolikus jelölése V1
A B
Máté: Architektúrák
2. eloadás
X 12. 30
NEM-VAGY (NOR) kapu Igazság tábla:
A 0 0 1 1
+ Vcc Vki
B 0 1 0 1
X 1 0 0 0
Szimbolikus jelölése V1
V2
A
Az alábbi ábra két tranzisztor párhuzamos kapcsolását tartalmazza a soros helyett. Ebben a felépítésben, ha valamelyik bemenet magas, akkor a megfelelő tranzisztor vezet, és a kimenetet levezeti a földbe. Ha a két bemenet alacsony, akkor a kimenet magas marad.
X
B Máté: Architektúrák
2. eloadás
31
Ez a három áramkör vagy azonos megfelelőik alkotják a három legegyszerűbb kaput. Neveik rendre: NEM (NOT), NEM-ÉS (NAND) és NEM-VAGY (NOR) kapuk. Az ÉS (AND) és VAGY (OR) kapuk működését nem részletezem, a fentiekhez nagyon hasonló. VAGY kapu ÉS kapu Igazság tábla:
A 0 0 1 1
Szimbolikus jelölése
B 0 1 0 1 A
Igazság tábla:
X 0 0 0 1
A 0 0 1 1
Szimbolikus jelölése
X
2. eloadás
A
X 0 1 1 1 X
B
B Máté: Architektúrák
B 0 1 0 1
Máté: Architektúrák
32
2. eloadás
33
A kapuk kombinációjából felépíthető áramkörök leírásához egy új típusú algebra szükséges, amelynek változói és függvényei vannak, és csak 0 és 1 értéket vesznek fel. Egy ilyen algebrát Boolealgebrának hívnak, felfedezőjéről George Boole, angol matematikusról elnevezve. Csakúgy mint a hagyományos algebrában, itt is függvényeket értelmezünk. A Boole függvényeknek egy vagy több bemeneti változója van és egy eredmény keletkezik, amely csak ezen változó(k) értékétől függ. Mivel az n változós Boole függvénynek csak 2n lehetséges kombinációja van, a függvényt teljesen leírhatjuk egy 2n sorral rendelkező táblázattal, ahol egy-egy sor megmondja a bemeneti értékek különböző kombinációja mellett a függvény értékét. Ezt a táblázatot igazságtáblázatnak nevezzük.
13.
Pl. 3 változós többségi függvény (3.3. ábra): értéke 1, ha legalább két operandus 1 Igazság tábla:
A 0 0 0 0 1 1 1 1
Bool algebrai alakja:
M A BC AB C ABC ABC A fölülvonás a NEM (negáció), az egymás mellé írás az ÉS, a + a VAGY muvelet jele.
Máté: Architektúrák
B 0 0 1 1 0 0 1 1
C 0 1 0 1 0 1 0 1
2. eloadás
• • • • •
M 0 0 0 1 0 1 1 1
Boole függvény megvalósításának lépései: igazságtábla, M A BC AB C ABC ABC negált értékek, ABC ABC ÉS kapuk bemenetei, ÉS kapuk, VAGY kapu, kimenet. A 0 0 0 0 1 1 1 1
35
B 0 0 1 1 0 0 1 1
C M 0 0 1 0 0 0 1 1 0 0 1 1 0 1 1 1
Máté: Architektúrák
M A B C 2. eloadás
36
Definíció: Akkor mondjuk, hogy két boole függvény ekvivalens, ha az összes lehetséges bemenetre a két függvény azonos kimenetet ad.
NAND és NOR elonye: teljesség (3.4. ábra). NOT
Két boole függvény ekvivalenciája könnyen ellenorizheto az igazság táblájuk alapján. Pl.: AB + AC és A(B + C) ekvivalens (3.5. ábra). Az elso függvény megvalósításához két ÉS és egy VAGY kapura van szükség, a másodikhoz elegendo egy ÉS és egy VAGY kapu. AND
OR
Máté: Architektúrák
2. eloadás
Máté: Architektúrák
37
Néhány azonosság (3.6. ábra) Szabály
ÉS forma 1A = A
0+A=A
Null
0A = 0
1+A=1
Idempotens
AA=A
A+A=A
Inverz
AA=0
A+A=1
Kommutatív
AB=BA
A+B=B+A
Asszociatív
(AB)C=A(BC)
(A+B)+C=A+(B+C)
Disztribúciós
A+BC=(A+B)(A+C)
A(B+C)=AB+AC
Abszorpciós
A(A+B)=A
A+AB=A
De Morgan
AB=A+B
Máté: Architektúrák
38
Disztribúciós szabály: A+BC=A+(BC)=(A+B)(A+C)
VAGY forma
Identitás
2. eloadás
Jelölje az ÉS muveletet 8 , a VAGY muveletet 7 , akkor A 7 (B 8 C) = (A 7 B) 8 (A 7 C)
A+B=AB 2. eloadás
39
Máté: Architektúrák
14.
2. eloadás
40
6.
Kombinációs áramkörök, multiplexer, demultiplexer, dekódoló, összehasonlító, programozható logikai tömbök.
A digitális technika nagyon sok alkalmazása megkívánja, hogy egy áramkör többszörös bemenettel és többszörös kimenettel rendelkezzen, és benne a kimeneteket csak a pillanatnyi bemenetek határozzák meg. Az ilyen áramkört kombinációs áramkörnek hívjuk. Most vizsgáljunk meg néhány gyakran használt kombinációs áramkört. A digitális logika szintjén a multiplexer egy olyan áramkör, amely 2n adatbemenettel, 1 adatkimenettel és n darab vezérlőbemenettel rendelkezik, az utóbbiak kiválasztanak egy adatbementet. A kiválasztott adatbemenetre azt mondjuk, hogy útképzéssel irányított vagy „kapuzott” (gated) a kimenetre. • Multiplexer: 2n adatbemenet, n vezérlo bemenet, 1 kimenet. Az egyik adatbemenet kapuzott (gated) a kimenetre (3.11. ábra). D0
D0
D1
D1
D2 D3 D4 D5 D6 D7
D2 D3 D4 D5 D6 D7
F
F
A BC
Sematikus rajza
AB C Máté: Architektúrák
2. eloadás
44
n vezérlo bemenetu multiplexerrel tetszés szerinti n változós bool függvény megvalósítható az adatbemenetek megfelelo választásával. Pl. a 3 változós többségi függvény: 3.12. ábra Igazság tábla:
A
B
C
M
0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1
0 0 0 1 0 1 1 1
Vcc
D0 D1 D2 D3 D4 D5 D6 D7
F
A BC
Párhuzamos-soros átalakítás: vezérlo vonalakon rendre: 000, 001, … 111. Máté: Architektúrák
2. eloadás
Az alábbi ábra egy nyolc bemenetes multiplexer vázlatos ábráját mutatja. A három vezérlővonal, az A, B és C egy hárombites számot kódol, amely meghatározza, hogy a nyolc bemenő vonal közül melyiket kapuzzuk a VAGY kapukra és ennek megfelelően a kimenetre. Bármilyen értékek vannak a kontroll vonalakon, hét ÉS kapunak mindig 0 lesz a kimenete, egy kapunak pedig vagy 0 vagy 1 lesz a kimenete a kiválasztott bemeneti vonal értékétől függően. Az n vezérlőbemenetű multiplexerekkel könnyedén lehet megvalósítani n változós bool függvényeket. Egy másik alkalmazásuk: párhuzamosból sorosba történő adatkonverterként való használat. A 8 bites adatot elhelyezzük a bemeneti vonalakon, és ezután a vezérlővonalakkal sorban lépegetünk 000-tól 111-ig , ezzel a 8 bitet egymás után helyeztük el az egyetlen kimenetre.
45
A demultiplexer a multiplexer inverze, amely egy egyedi bemenő jelet irányít a 2 n kimenet valamelyikére az n vezérlővonal értéktől függően.
15.
Dekódolónak nevezzük azt az áramkört, amely n bites számot használ bemenetként, és ki tudunk vele választani (be tudjuk állítani 1-re) pontosan egyet a 2n kimenet közül. • Demultiplexer: egy egyedi bemenetet irányít az n vezérlo bemenet értékétol függoen a 2n kimenet egyikére D0
D0
D1
D1
D2 D3 D4 D5 D6 D7
D2 D3 D4 D5 D6 D7
• Dekódoló: n bemenet, 2n kimenet. Pontosan egy kimeneten lesz 1 (3.13. ábra). Demultiplexerrel: a bemenetet igazra állítjuk.
demultiplexer
multiplexer Máté: Architektúrák
2. eloadás
D0
D0
D1
D1
D2 D3 D4 D5 D6 D7
D2 D3 D4 D5 D6 D7
dekódoló
demultiplexer 46
Máté: Architektúrák
2. eloadás
47
Egy másik hasznos áramkör az összehasonlító, amely két bemeneti szót hasonlít össze. Az alábbi ábrán ábrázolt egyszerű összehasonlító két bemenettel dolgozik, A és B, mindegyik 4 bit hosszú, és 1-et ad eredményül, ha a bemenetek azonosak, és 0-t ha különbözők. Az áramkör KIZÁRÓ VAGY kapun alapul (a kizáró vagy tagadása). • Összehasonlító (comparator): (3.14. ábra). KIZÁRÓ VAGY kapu Igazság tábla: A 0 0 1 1
B 0 1 0 1
X 0 1 1 0
Szimbolikus jelölése
A
X
B
• Programozható logikai tömbök: PLA (3.15. ábra) (Programmable Logic Array). 6 kimenet
A0
Ha ezt a biztosítékot kiégetjük, akkor nem jelenik meg #B az 1-es ÉS kapu bemenetén
B0 A1 B1 A2
B3
2. eloadás
49
A
4 bites összehasonlító Máté: Architektúrák
5
1
24 bemeno vonal
A3
1
50 bemeno vonal
0
A=B
B2
0
B
Ha ezt a biztosítékot kiégetjük, akkor az 1-es ÉS kapu kimenete nem jelenik meg az 5-ös VAGY kapu bemenetén
L
12 bemeno jel 48
Máté: Architektúrák
2. eloadás
49
Egy nagyon általános lapka a programozható logikai tömb, vagy PLA szolgál a szorzatösszeg képzésére. A fenti ábra egy egyszerű példát mutat be, ennek a lapkának 12 változó számára van bemeneti vonala, és 6 kimeneti vonala is van. A kis négyzetek a biztosítékokat tartalmazzák, amelyek kiégetésével meghatározható a végrehajtandó funkció. Az olvadóbiztosítékokat két mátrixban helyezték el: a felső az ÉS kapuk, az alsó a VAGY kapuk számára.
16.
7.
Aritmetikai áramkörök. Léptető, fél és teljes összeadó, ALU, átvitel továbbterjesztő és kiválasztó összeadás.
Aritmetikai áramkörök ezek már kombinációs MSI áramkörök, aritmetikai műveleteket lehet velük végezni
Léptetőregiszter 8 bites (8 bemenet, 8 kimenet) egyszerű léptető D0,…,D7: bemenő bitek S0,…,S7: kimenő bitek C: vezérlővonal
a kimenő bitekben a bemenő bitek pontosan 1 bittel vannak eltolva a vezérlővonal határozza meg a léptetés irányát, 0: balra, 1: jobbra minden bithez ÉS kapupárok tartoznak, kivéve a végeken ( S0, D7) amikor C=1, minden kapupár jobb oldala aktivizálódik, és a megfelelő bemenő bitet küldi a kimenetre. (D0 > S1, D1 > S2, D2 > S3, …) mivel a jobb oldali ÉS kapu kimenete össze van kötve a tőle jobbra eső VAGY kapu bemenetével, jobbra léptetés hajtódik végre. C=0 esetén az ÉS kapupár baloldali tagja kapcsolódik be és bal oldali léptetés megy végbe ugyanezen a módon Fél összeadó áramkör (half adder)
Az „Összeg” kimenethez A és B KIZÁRÓ-VAGY (XOR) eredménye kerül Az „Átvitel” kimenethez pedig A és B ÉS (AND) ereménye kerül
17.
Teljes összeadó áramkör (full adder)
Két „fél összeadó” áramkörből épül fel Azért van szükség erre, mert ha pl. két darab 1 bájtos (8 bites) bemenő értéket akarnánk összeadni, akkor az alsó biteken való összeadást még jól elvégezné, de amikor a felső bitekbe lép az összeadás (felső 4-be), akkor ott nem kezeli az alsó bitekből érkező átvitelt. Olyankor újrakezdené az összeadást ezzel elveszítve egy lehetséges átviteli értéket, vagyis a 2x4 bitet (alsó és felső) külön-külön adja össze, a köztük levő átvitelt pedig nem kezelné (alsó bitekben keletkezőt nem vinné át a felső bitekbe).
Átvitelt kezelő / továbbterjesztő összeadó áramkör (ripple carry adder) Ahhoz viszont, hogy pl. két szavas (= word = 2 byte = 16 bit) bemenő értéket adjunk össze a fenti (Teljes összeadó) áramkört 16-szor meg kell ismételnünk. Ez úgy néz ki, hogy a fenti ábra 16-szor egymás mellé van pakolva, az egész balról-jobbra halad, a bal oldali áramkör a jobb oldalihoz úgy kapcsolódik, hogy a bal oldali „Átvitel ki” a tőle jobbra levő „Átvitel be” részhez van kapcsolva, a legjobboldalibb (a legutolsó) áramkörnél pedig az „Átvitel be” bitet 0-nak vesszük.
Átvitel-kiválasztó összeadó áramkör (carry select adder) Az előző áramkörnél legrosszabb esetben, ha pl. 1b-t és 1111 1111b-t hozzáadjuk egymáshoz, akkor látjuk, hogy az átvitelt folyamatosan át kell adnia a következő bitnek, és a legfontosabb, hogy az alsó és felső bitek között is az áramköröknek, hogy ne vesszen el sehol az átvitel.
18.
Az átvitel-kiválasztó áramkör ennél a megoldásnál 2-szer gyorsabb, ugyanis ha pl. egy 32 bites összeadót nem 1 felső 16 bitesre és 1 alsó 16 bitesre bontunk, hanem 1 alsó 16 bitest és 2 felső 16 bitest csinálunk (ezzel megduplázva a felső összeadó hardverét) megtehetjük azt, hogy egy időben elindítjuk mind a 3 összeadót, mert ugye a sima átvitelt kezelő áramkörnél először végig kell futnia az alsó 16 bitesnek, hogy meglássuk van-e átvitel, amit a felső 16 bitesbe át kell adni. E helyett a 2 felső 16 bitest elindítjuk egyszerre az alsó 16 bitessel együtt, az egyik felső 16 bites összeadót „Átvitel be” = 1 értékkel, a másikat pedig „Átvitel be” = 0 értékkel. Amikor pedig lefutott mind a 3 áramkör, az alsó 16 bites összeadás végeredménye már ismert lesz, azaz ilyenkor már ki tudjuk választani, hogy melyik felső 16 bites összeadás végeredményét használjuk fel, attól függően, hogy volt-e átvitel vagy nem. Ezzel megfelezve a végrehajtási időt az átvitelt kezelő áramkörhöz képest. Aritmetikai-logikai egység (ALU)
Ez a példa a következő funkciók bármelyikét végre tudja hajtani: ÉS, VAGY, NEGÁCIÓ, + (összeadás), ez F0, F1 bemenő értékeitől függ (00, 01, 10, 11). Dekódoló: 2 bites, a négy művelet számára létrehozza az engedélyező jeleket Logikai egység: (szaggatott négyzet) a négy művelet itt végződik el, közülük csak egy haladhat át a legutolsó VAGY kapun. Mivel pontosan egy dekódolókimenet értéke lehet 1, így ezért a 4 ÉS kapuból csak pontosan egy fog működni, a többi 3 kimenete 0 lesz, függetlenül A és B értékétől. Normál esetben az ENA és ENB értéke 1, hogy engedélyezze a bemeneteket, INVA pedig 0. Ebben az esetben A és B a logikai egységbe módosítás nélkül kerülnek be. Teljes összeadó: A és B összegét számolja ki átvitellel együtt. Ezek az áramkörök Bitszeletek néven ismertek (bitslices) Ezek segítségével bármilyen hosszúságú ALU-t lehet építeni, pl. egy 8 bites ALU:
19.
8.
Nem kombinációs áramkörök. Órák, tárolók, flip-flop-ok.
Óra Célja, hogy a digitális áramkörökben az események történésének sorrendjét felügyelje. Az óra ebben az értelemben egy áramkör, amely a pulzusok egy sorozatát bocsájtja ki egy pontosan meghatározott pulzusszélességgel, és két egymás utáni pulzus közötti időintervallummal rendelkezik. A ciklusidő két egymást követő pulzus élei közötti időintervallum. A pulzus frekvenciája általában 1 és 500 MHz közöt van, ennek megfelelően az órajel 1000 ns-tól 2 ns-ig terjedhet. Az óra frekvenciáját általában egy kristályoszcillátor vezérli. Ha több eseménynek kell lefutnia egy órajel alatt egy adott sorrendben, akkor az órajelet alciklusokra kell osztanunk. Lényege, hogy az alapáramkört megcsapoljuk, és beszúrunk egy áramkört ismert késleltetéssel, így készíthetünk másodlagos órajelet, amely fáziseltolással keletkezik az elsődlegesből.
SR-Tároló Ahhoz, hogy legalább 1 bites memóriát készítsünk, szükségünk van egy áramkörre ami valahogyan visszamelékszik az előző bemeneti értékre. Egy ilyen áramkört 2 NEM-VAGY kapuból építhetünk. S: R: Q, #Q: Stabil állapot:
Set (bemenet) Reset (bemenet) két kimenet, amelyek egymás fordítottjai a két kimenet 1,0 vagy 0,1
20.
Az ilyen tárolókat SR-tárolóknak (Set Reset latch) hívjuk. A fenti két ábrán látható, hogy milyen két értéke lehet Q-nak és #Q-nak, ha S = R = 0; ha viszont S = 1 és R = 0, akkor az S utáni NOR kapu vagy 1,0 vagy 1,1 lesz Q-tól függően, de amint a táblázatból látjuk az eredményen ez nem változtat. Ha S = 0, R = 1, akkor az R utáni NOR kapu vagy 0,1 vagy 1, 1 #Q-tól függően, amelyek kimenete a NOR kapuból szintén ugyanaz. Tehát a Q, #Q értékeitől függetlenül működnek a beállító bemeneti értékek: ha S = 1, akkor Q = 1 lesz, ha R = 1, akkor Q = 0 lesz. Az áramkörnek pedig mint tudjuk két stabil állapota is van, amikor S = R = 0, azaz a két fajta beállítási értékre emlékezni fog.
Időzített SR-Tároló Módosított SR-tároló, az állapotváltozás csak egy bizonyos időpillanatban fog töténni. Az áramkör további bemenete: órajel, ami alaphelyzetben 0.
Amikor óra = 0, az ÉS kapuk kimenete 0 lesz, tehát a stabil állapotban marad az áramkör; amikor óra = 1, az ÉS kapuk kimenete már S és R bemeneti értékétől függnek majd. (pl: S = 1, óra = 1, R = 0, akkor a fenti kapu 1,1, tehát 1 megy tovább, a lenti ÉS kapu 1,0, tehát 0 megy tovább kimenetnek).
Időzített D-Tároló Módosított SR-tároló, lényege, hogy az SR-tároló bizonytalanságát kiküszöböli, ugyanis van egy eset, amikor S = R = 1, ilyenkor az SR-tárolóban a Q, és #Q értékét 0,0-ra kényszeríti ez a két bemenet, ezután az áramkör automatán átáll valamelyik stabil pozicióra, de ezt nem tudhatjuk pontosan, hogy melyikre. Lényege, hogy csak 1 bemenete van, D így a NEM kapuval kiküszöbölhető a probléma, mindig ellentétes értékek lesznek a két ÉS kapunál. Ez már egy igazi 1 bites memória, a tárolt érték Q-ban lesz elérhető.
Flip-flop Célja: egy meghatározott időpontban vegyünk mintát az áramkör egy adott vonaláról. Akkor nem fordul elő, amikor az órajel állása 1, csak akkor, amikor 0-ból 1-be (felfele él) vagy 1ből 0-ba (lefele él) megy.
21.
A flip-flop és a tároló közti különbség, hogy az előző élvezérelt (edge triggered), míg az utóbbi szintvezérelt (level triggered).
A fenti áramkörnek lényege, hogy létre tudunk vele hozni egy rövid impulzust az órajel felmenő részénél. a, b, c, d pontoknál mérjük a feszültséget, amikor a-nál a hosszú órajel impulzus megérkezik, akkor c-be is eljut, valamint b-be is, de ott már egy NEM kapun keresztül. a NEM kapuk (más fajta NEM kapu is van) sajátossága, hogy miután megérkezik az órajel hozzájuk egy kicsit késleltetve (1-10 ns) váltanak át az inverzzé. Tehát, amikor a-n van órajel, akkor egyidöben eljut c-hez és a NEM kapuhoz. Mivel a NEM kapu késleltetve vált át, abban a pici időben még a b-n is lesz órajel, de amint letelt az a késleltetési idő, átvált az inverzre, vagyis 0-ra és akkor már nem fog működni az ÉS kapu.
És ezt az értéket le tudjuk tárolni egy D-tárolóban, ezért hívják a fenti áramkört D-flip-flop-nak. Tárolók és flip-flop-ok. CK: clock / órajel (a) CK=1 (b) CK=0 esetén írja be D-t
(c) CK emelkedő élénél (d) CK lefelé menő élénél
(a,b: tároló)
(c,d: flip-flop)
22.
A következő ábrán látható két függtlen D-flip-flop:
Következő ábra: közös CK-val vezérelt 8 bites D flip-flop S: set R: reset
PR: preset CLR: clear
23.
9.
Processzor szintű párhuzamosítás
Bevezető A számítógép-tervezők ma már ahelyett, hogy a processzorok órajelét növelnék vagy a lapkák gyorsaságát növelnék a számítógép teljesítménye növelésének érdekében, inkább a párhuzamosságban látják a teljesítmény növekedésének a kulcsát (vagyis hogy több műveletet egyszerre eltudjunk végezni, ne pedig egyet-egyet nagyon gyorsan). Processzorszintű párhuzamosság Lényege, hogy több processzor dolgozik egyszerre ugyanazon a feladaton. Tömbszámítógépek: Egy tömbprocesszor nagyszámú egyforma processzorból áll, ezek ugyanazt a műveletet végzik el különböző adathalmazokon. A lenti képen egy 8x8 –as processzor/memória párból álló négyzetháló látható.
Itt a processzorok az alattuk levő memóriából olvassák ki az utasításokat, amiket egy előzőleges inicializációs fázisban töltöttek fel. Vektorprocesszor Vektorregisztereket használ, ezek több hagyományos regiszterből állnak. Ezeket egymás után sorosan tölti fel a memóriából, majd páronként úgy adja őket össze, hogy egy szállítószalagos összeadóba irányítja őket a vektorregiszterekből. Multiprocesszorok Egy tömbprocesszor feldolgozóegységei nem függetlenek egymástól, mert közös vezérlőegységük van. Ezekben viszont több teljes processzor van, közösen használják a memóriát, együttműködésüket viszont szoftveresen kell megoldani. Többféle implementációjuk is létezik:
24.
(a)
(b)
a: egy sínre vannak csatlakoztatva a processzorok (gond vele: ha több processzor egyszerre próbálja elérni a közös memóriát, akkor ütközések keletkezhetnek). b: saját lokális memóriával rendelkeznek a processzorok, ide azokat az adatokat tárohatják, amelyeket nem kell megosztaniuk a többi processzorral. Multiszámítógépek Kisebb számú processzorokból álló gépek gyártása még megoldható (<=64), de nagyobb számúaknál már a processzorok és a memória összeköttetése nehéz. E nehézségek miatt inkább nagyszámú összekapcsolt számítógépek rendszerét építettek, amelyeknek csak lokális memóriája van. Ezek a multiszámítógépek. E számítógépek processzorai üzenetekkel kommunikálnak. Összeköttetésük csak ritkán „minden gépet mindennel” kötésben van, inkább 2 és 3 dimenziós hálókat, fákat, gyűrűket terveznek. Ma már a multiprocesszor és a multiszámítógép hibrid keverékén dolgoznak.
25.
10. Gyorsító tár (cache). Találati és hiba arány. Közös és osztott gyorsító tár. Direkt leképezésű és halmaz kezelésű gyorsító tár. Memóriába írás. Gyorsító tár / Cache A gyorsító tárra alapvetően azért van szükség, mert a processzorok gyorsabbak, mint a memóriák, ennek oka: a fejlesztők tudnának építeni olyan gyors memóriákat, mint a processzorok, de azok jóval nagyobb helyet foglalnának (lapkák mérete és száma), valamint sokkal drágábbak lennének. A cél (amit a cache megvalósít): a kis méretű, gyors memória. A cache a központi memória egy kisebb része, amit a CPU lapkájára helyeztek. Lényege, hogy a leggyakrabban használt memóriaszavakat a gyorsító tárban tartjuk, s amikor a processzornak szüksége van egy szóra, akkor először a gyorsító tárban keresi, ha ott nincs, akkor történik csak memóriaolvasás. Ha a szavak jelentős része a gyorsító tárban van, akkor az elérési idő nagymértékben csökkenhet. Lokalitási elv: Ha egy hivatkozás a memória A címére történik, akkor a következő valószínűleg valahol A közelében lesz. (Ugyanis a programok a futásidejük nagy részében egymás utáni memóriacímekről dolgoznak, kivéve a vezérlésátadó utasítások és eljáráshívások.) Ha A nincs a gyorsító tárban, akkor az A-t tartalmazó (adott méretű) blokk (gyorsító sor – cache line) kerül beolvasásra a memóriából a gyorsító tárba. Találati és hibaarány
Jelöljük c-vel a gyorsító tár elérési idejét, m-mel a központi memória elérési idejét! Találati arány (h): az összes hivatkozás mekkora hányadát lehetett a gyorsító tárból kielégíteni. Hibaarány (1-h): az összes hivatkozás mekkora hányadát nem lehetett a gyorsító tárból kielégíteni. Átlagos elérési idő: c + (1 – h) m
Gyorsító tár és gyorsító sor mérete Gyorsító sor: gyorsító táron belüli blokkok. A gyorsító sorokat azért alkalmazzák, mert ha keresünk egy szót a memóriában, sokkal hatékonyabb egy n hosszú sort beolvasni, mint n-szer beolvasni egy szót. A gyorsító tár mérete minél nagyobb, annál jobb, de egyben sokkal drágább is. A gyorsító sor mérete is szintén annál jobb, minél nagyobb, de itt viszont a beolvasási időt növeli meg nagyban. A kettő összhangja a legfontosabb. Osztott és közös gyorsító tár Az adatok és az utasítások közös (egyesített) vagy külön (osztott) tárban vannak. Az közös gyorsító tár (az utasítások és az adatok ugyanazt a gyorsító tárt használják) egyszerűbb szerkezetű és automatikusan egyensúlyban tartja az utasítások és az adatok mozgatását. Ma mégis az osztottat használjuk, ezt Harvard-architektúrának nevezzük. Az osztott gyorsító tár lehetővé teszi az utasítás előolvasó és az operandus-beolvasó párhuzamos működését, a közös nem. Mivel az utasításokat általában nem módosítják végrehajtás közben, az utasításokat tároló gyorsító tár tartalmát soha nem kell visszaírni a memóriába.
26.
Direkt leképezésű gyorsító tár Legegyszerűbb gyorsító tár
A fenti gyorsító tárnak 2048 bejegyzése (sora), gyorsító tár vonala van. Valid: jelzi, hogy ebben érvényes adat van-e vagy nem. Amikor boot-olunk, minden érvénytelennek van jelölve. Tag: egyedi 16 bites érték, ami a megfelelő memóriavonalat azonosítja, ahonnan az adat jött. Data (bejegyzés): 32 bájtos gyorsító vonal, a memóriában levő adat másolata. A gyorsító tárban az adatok tárolásához és kinyeréséhez 4 alkotóelemre tagoljuk a címet:
Tag: a gyorsító tárban tárolt Tag megfelelője. Line: jelzi, melyik gyorsító tár bejegyzés tartalmazza a megfelelő adatokat. Word: megmondja, hogy egy vonalon belül melyik szóra történt hivatkozás. Byte: ha csak egyetlen bájtra érkezik kérés, megmondja hogy a szón belül melyik bájtra van szükség. Amikor a CPU előállít egy memóriacímet, a hardver kiveszi a címből a 11 Line bitet, és felhasználja indexelésre a gyorsító tárban, hogy megtalálja a 2048 bejegyzés egyikét. Ha a bejegyzés érvényes, akkor a memóriacím Tag mezője és a gyorsító tár bejegyzésének Tag mezője összehasonlításra kerül. Ha megegyeznek, akkor a gyorsító tár bejegyzés tartalmazza a keresett szót. Ezt gyorsító tár találatnak nevezzük. Ha a gyorsító tár bejegyzése érvénytelen, vagy a címkék nem egyeznek meg, akkor a keresett bejegyzés nincs a gyorsító tárban, ez a gyorsító tár hiány.
Halmazkezelésű gyorsító tár Ha egy program erősen használja a 0-65536 címeken levő szavakat, állandó összeütközésbe kerül amiatt, hogy minden hivatkozás feltételezhetően kilöki a másikat a gyorsító tárból. Ennek a megoldása az, ha két vagy több vonalat is megengedünk minden gyorsító tár bejegyzésen. Egy olyan gyorsító tárat, amelynek minden egyes címhez n lehetséges bejegyzése van, n utas halmazkezelésű gyorsító tárnak nevezünk.
27.
A fenti kép egy 4-utas gyorsító tár. Ha a gyorsító tár vonal által mutatott sorban A, B, C, D bejegyzés egyikében V = 1 és a hozzá tartozó Tag megegyezik a címben levő Tag-gel akkor az adat a gyorsító tárban van. Amikor új bejegyzést hozunk létre, a bent lévő tételek közül az LRU (Least Recently Used) algoritmust használva a legrégebben használt elemet dobja el. Memóriába írás Stratégiák: o Írás áteresztés: az írás a memóriába történik. Ha a cím a gyorsítóban van, oda is be kell írni, különben el kellene dobni a gyorsító sort. o Késleltetett írás: (write deferred, write back) ha a cím bent van a gyorsító tárban, akkor csak a gyorsító tárba írunk, a memóriába csak gyorsító sor cserénél. o Írás allokálás: (write allocation) ha a cím nincs a gyorsító tárban, akkor előtte betölthetjük – többnyire ezt alkalmazzák késleltetett írás esetén.
28.
11. Operandus megadás módjai. Közvetlen operandus, direkt, regiszter, regiszter-indirekt, indexelt, bázis-index címzés A legtöbb utasításnak van operandusa, ezért kell valamilyen módszer az operandus helyének megadására. Ezt nevezzük címzésnek, és ezt fogjuk a következőkben viszgálni. Közvetlen operandus megadás Az operandus specifikációjának a legegyszerűbb módja, ha az operandust közvetlenül az utasításban adjuk meg, nem pedig a címét vagy más információt, amely leírja, hogy az operandus hol található. Az ilyen operandust közvetlen operandusnak nevezzük, mert automatikusan betöltődik az utasítással, tehát azonnal hozzáférhető felhasználásra. A közvetlen címzésnek az a lényege, hogy nem kíván külön memóriahivatkozást az operandus kiolvasására. A hátránya, hogy ily módon csak konstanst lehet megadni. Továbbá, az értékek száma korlátozott a mező méretével. Mégis sok architektúra használja ezt a technikát kis egész konstansokkal. Pl.
MOV AL, 14h
Direkt memória címzés A memóriabeli operandus megadása egyszerűen teljes címének megadásával megtehető. Ezt a módot direkt címzésnek nevezzük. Mint a közvetlen címzés, a direkt címzés használata is korlátozott: az utasítás minden végrehajtása ugyanazt a memóriamezőt érinti. Tehát amíg az érték változhat, a hely nem, vagyis a direkt címzés csak olyan globális változók elérésére használható, amelyek címe fordításkor ismert. Azonban sok program használ globális változókat, így ez a módszer széles körben használatos. A címrészen az operandus logikai címe (eltolás, displacement) szerepel. Pl. MOV AX, Szam ahol Szam egy változó, mivel nem adtuk meg a szegmens nevét, így az alapértelmezett szegmenset fogja használni, azaz DS:Szam. Fontos még, hogy úgy címezzünk hogy a két operandus mérete összhangban legyen. Regiszter címzés A regiszter címzés alapvetően azonos a direkt címzéssel, azzal a különbséggel, hogy memóriacím helyett regisztert határoz meg. Mivel a regiszterek (a gyors elérés és a rövid cím miatt) nagyon fontosak, a legtöbb számítógépen ez a címzési mód a leggyakoribb. Sok fordítóprogram alaposan megnézi, hogy mely változókat használják a legtöbbet (pl. ciklusváltozók), és ezeket regiszterekbe tölti. A címzés során az átmásolni kívánt adat egy általános célú regiszterben van. Pl. MOV AX, BX
29.
Regiszter indirekt címzés Ebben a címzési módban is a memóriából olvassuk a specifikált operandust, vagy oda írjuk, mint a direkt címzés esetén, de nem közvetlenül a címe van adva az utasításban. Helyette a címet egy regiszter tartalmazza. Ha egy címet ilyen módon adunk meg, mutatónak hívjuk. A regiszter-indirekt címzés nagy előnye, hogy úgy hivatkozik a memóriára, hogy annak címét nem kell az utasításban tárolni. Továbbá, az utasítás különböző végrehajtása más-más memóriamezőre hivatkozhat. Az indexelt címzés azon speciális esete, amikor nem adunk meg displacement-et. Ennél a címzési módnál az SI, DI és a BX regiszter használható. Pl. MOV AX, [BX] MOV AX, [SI] Indexelt címzés Gyakran jól használható, ha ismerjük egy memórai címét egy regiszter tartalmához képest. Láttunk már erre példát az IJVM esetén, ahol a lokális változókat az LV regiszterhez képest címzik. Azt a címzési módot, amikor a hivatkozott memória címét egy regiszter értéke és egy konstans határozza meg, indexelt címzésnek nevezzük. Az operandusban lévő 8 vagy 16 bites számot (eltolás) hozzáadja SI vagy DI tartalmához, ez lesz az operandus logikai címe. Pl. MOV AX, 10h[SI] Bázis-index címzés Néhány gép rendelkezik olyan címzési móddal, amely úgy határozza meg a hivatkozott memória címét, hogy összeadja két regiszter tartalmát, és (esetleg) ehhez hozzáad egy eltolási értéket. Ezt a módot bázis-index címzésnek nevezik. Az egyik regiszter a bázis, a másik az index. A bázis-index címzés a legösszetettebb adatcímzési mód. BX, SI vagy DI regiszter valamelyikét használhatjuk. Pl. MOV AX, 10h[BX][SI] MOV AX, [BX+SI+10h]
30.
12. Sínek. Sín Protokoll. Master – szolga. Sín vezérlő, vevő, adóvevő. Sín szélessége. Sokszorozott sín. Sín időzítés: szinkron, aszinkron sín, teljes kézfogás. Sín ütemezés. Sín műveletek. Sínek A sín (bus) egy közös elektronikus pálya a különböző eszközök között, amelyek összekötik a CPU-t a memóriával és a B/K berendezésekkel. A korai személyi számítógépeknek egyetlen sínje (system bus) volt, míg a mai számítógépekben már egy speciális sín áll rendelkezésre a CPU és a memória, és legalább egy másik sín a B/K berendezések számára. Ahhoz, hogy a különböző kiegészítő kártyákat csatlakoztatni tudjuk a rendszerhez, nagyon jól definiált szabályokat kell meghatározni a sín működéséről, amelyeket sín protokollnak nevezünk. Számos sínt széles körben használnak a számítástechnika világában: Omnibus (PDP-8), Unibus (PDP-11), Multibus (8086), IBM PC (PC/XT), ISA (PC/AT), EISA (80386), Microchannel (PS/2), PCI (sok PC–nél), SCSI (sok PC–nél és munkaállomásnál), NUBUS (Macintosh), Universal Serial Bus (modern PC-knél), FireWire (szórakoztató elektronikában), VME (fizikai laboratóriumi berendezéseknél), Camac (nagy energiájú fizikában). Néhány sínhez csatlakoztatott berendezés aktív (master) és ezáltal kezdeményezni tudja a sínátviteleket, míg mások passzívak (slave) és várják a kéréseket. Amikor a CPU megrendel a lemezvezérlőtől egy blokkolvasást vagy írást, a CPU úgy viselkedik, mint egy mester, a lemezvezérlő pedig, mint egy szolga. Azonban később a lemezvezérlő mesterként viselkedhet, amikor kiad egy parancsot a memóriának, hogy fogadja el azt a szót, amelyet a lemezmeghajtóból olvasott be. A bináris jelek, amelyeket a számítógép berendezései kibocsátanak, gyakran nem elég erősek, hogy elegendő áramot adjanak a sínnek, ezért a legtöbb sínmester összekapcsolódik a sínen egy lapkával, amelyet sín vezérlőnek (bus driver) hívnak – ez lényegében egy digitális erősítő. Hasonlóan a legtöbb szolga egy sínvevőn (bus receiver) keresztül kapcsolódik a sínre. Azoknál a berendezéseknél, amelyeknél mind a mester, mind pedig a szolga tevékenységére szükség van, egy kombinált lapka áll a rendelkezésünkre, amelyet sín adóvevőnek (bus transceiver) nevezünk. Ezek a sínhez kapcsolódó lapkák gyakran háromállapotú (tri-state) berendezések, azért hogy le tudjanak kapcsolódni a sínről, ha már nem szükségesek, vagy némiképp eltérő módon rákapcsolódjanak – ezt nyitott gyűjtőnek (open collector) hívjuk. Sínszélesség A sín szélessége az egyik legnyilvánvalóbb tervezési paraméter. Minél több címvezetéke van a sínnek, annál nagyobb memóriát tud a központi egység közvetlenül megcímezni. Ha egy sínnek van n címvezetéke, akkor azt a CPU 2n különböző memóriarekesz megcímzésére tudja használni. Nagy memória használatához a sínek sok címvezetéket igényelnek. A szélesebb sínek több vezetéket igényelnek, mint a keskenyek. Ezenkívül több fizikai helyet is folglalnak, valamint nagyobb csatlakozókra van szükségük. Mindezek a tényezők egyre költségesebbé teszik a síneket.
31.
Két módon tudjuk egy sín sávszélességét megnövelni: vagy csökkenteni kell a sínciklus idejét (több adatátvitel/s), vagy növelni kell a szélességet (több bitet kell átvinni egyszerre). Ugyan egy sínt fel is lehet gyorsítani, de ez nehéz, mivel az egyes vezetékeken a jelek kissé eltérő sebességgel haladnak – ez a probléma sínasszimetriaként (bus skew) ismert. Minél gyorsabb egy sín, annál nagyobb az asszimetria. Az idők folyamán mind a címvezetékek, mind az adatvezetékek száma is megnőtt, de mindezek némi kompatibilitási problémákat okoztak. Hogy megkerüljék a túl széles sínek problémáját, elkezdték alkalmazni a multiplexelt sínt (multiplexed bus). Ennél a konstrukciónál nincs külön cím és adatvezeték hanem mindezt egyetlen vezetékkel oldották meg. Sínek időzítése A sínek két diszjunkt kategóriába csoportosíthatók, az időzítésüktől függően. A szinkron sínnek van egy vezetéke, amelyre egy kristályoszcillátor van kapcsolva. Ezen a vezetéken általában 5 Mhz és 100 Mhz közé eső frekvenciájú négyszög hullámokból álló jel halad. Minden síntevékenység ezeknek a négyszög hullámoknak a többszöröséig tart, ezeket hívják sín ciklusoknak (bus cycles). Az aszinkron sínnek ilyen fő órajel generátora nincs. A sínciklusok igény szerint bármilyen hosszúságúak és nem kell, hogy minden lehetséges eszközpár között azonosak legyenek. Ahhoz hogy ne csak a CPU legyen a sínmester, hanem bármely eszköz lehessen sínmester egy sínütemezési (bus arbitration) mechanizmusra van szükség, hogy elkerülhessük a káoszt. Szinkron sín Andrew S. Tannenbaum: Számítógép architektúrák - 198. o. Aszinkron sín Andrew S. Tannenbaum: Számítógép architektúrák - 201. o. Sínütemezés A sín ütemezési mechanizmus lehet centralizált vagy decentralizált. Sok CPU–ba be van építve egy ütemező, de gyakran egy külön lapkára van ehhez szükség. Az ütemező számára nincs semmilyen mód arra, hogy megtudja hány eszköz kéri a sínt. Az egyetlen dolog amit meg tud különböztetni, az hogy van kérés vagy nincs. Amikor az ütemező egy sínkérést észlel, a sínhasználatra egy használati engedélyezés jelet ad ki. Ez az utasítás keresztül fut az összes B/K eszközön sorban, amikor az ütemezőhöz legközelebb álló eszköz észleli az engedélyezést, ellenőrzi hogy ő adta-e ki a kérést. Ha igen akkor átveszi a kérést és nem továbbítja tovább az engedélyezést a többi eszköz számára. Viszont ha nem ő adta ki a kérést akkor továbbítja az engedélyt a következő eszköz számára. Ezt a módszert láncolásnak (daisy chaining) nevezzük. Annak érdekében, hogy elkerüljük az ütemezőtől számított távolságon alapuló implicit prioritásokat, sok sínnek több prioritási szintje van. Minden egyes szint tartalmaz egy sínhasználat kérése és egy sínhasználat engedélyezése vezetéket. Ha több prioritási szinten is érkezik be kérés, az ütemező a sínhasználati engedélyt a legnagyobb prioritásúnak fogja adni, az azonos prioritású eszközök között pedig a láncolás működik. Bizonyos ütemezőknek van egy harmadik vezetéke, amelyet egy eszköz akkor állít be, ha fogadta az engedélyt, és átvette a sínt. Amint ezt a nyugtázó
32.
vezetéket beállították, a kérés- és engedélyezés vezetékeket már lehet negálni. Ennek következtében további eszközök kérhetik a sínt, mialatt az első eszköz már használja. Mire az aktuális adatátvitel befejeződik, a következő sínmester már ki van választva. Amint a nyugtázás vezetéket negálták, azonnal el is kezdhet dolgozni, ekkor egy újabb ütemezési forduló kezdődik. Annak érdekében, hogy a CPU-nak ne kelljen versenyeznie a sínen lévő B/K eszközökkel, a memóriát egy a B/K eszközöktől elkülönített sínre teszik. A decentralizált sínütemezés esetében minden eszköz minden kérésvezetéket figyel, így minden sín ciklus végén minden eszköz tudni fogja, a kérő eszköz volt-e a legnagyobb prioritású és hogy megkapja-e a sínhasználat engedélyezését a következő ciklusban. Ez az ütemezési módszer több vezetéket igényel, viszont megtakarítható az ütemező várható költsége, ezen kívül az eszközök számát korlátozza a kérési vezetékek számára. Sínműveletek Rendszerint egyszerre egy szót visz át a sín, azonban amikor gyorsítótárat használnak, egy egész sor beolvasása lenne szükséges. Ebben az esetben a blokkátvitel hatékonyabb lehet, mint az egyes szavak átvitele. Amikor egy blokkátvitel megkezdődik, a sínmester megadja a szolgának az átvinni kívánt szavak számát és ezután minden egyes órajel-periódusban vissza fog adni egy szót, amíg csak a számláló el nem fogy. Egy többprocesszoros rendszerben, amelyben két vagy több CPU van rákapcsolva ugyanarra a sínre, biztosítani kell, hogy egy időben csak egy CPU használhasson valamilyen kritikus adatstruktúrát a memóriából. Egy tipikus megoldás erre a célra az, ha van a memóriában egy olyan változó, amely 0, ha egyik CPU sem használja az adatstruktúrát és 1, ha használatban van. Ha viszont mindkét CPU azt látja, hogy a kontrollváltozó értéke 0, akkor mindegyik átállítja 1-re, és azt gondolja, hogy ő az egyetlen CPU, amely használja. Egy ilyen eseménysorozat káoszhoz vezethet. A többprocesszoros rendszerekben gyakran alkalmazunk ún. módosítás-visszaírás sínciklust, amely lehetővé teszi, hogy bármely CPU beolvasson egy szót, megvizsgálja, és visszaírja a memóriába anélkül, hogy lekapcsolódna a sínről. Ez a fajta sínciklus megelőzi azt, hogy egy konkurens CPU használni tudja a sínt, és így befolyásolhassa az első CPU működését. Létezik egy speciális sínművelet, amely a megszakítások kezelésére szolgál. Amikor a CPU utasít egy B/K eszközt, hogy tegyen meg valamit, általában egy megszakítást vár visszajelzésként, amikor a feladat elkészült. A megszakításkérés jelzéséhez szükség van a sínre. Mivel több eszköz kérhet megszakítást egyszerre, ezért ütemezési problémák merülnek fel. Szokásos megoldás az, hogy az egyes eszközökhöz prioritásokat rendelünk és egy központi ütemező használatával pedig a leginkább kritikus eszközök számára magas prioritást adunk.
33.
13. Általános soros sín A PCI sín és a PCI Express kiválóan alkalmazható nagy sebességű perifériák számítógéphez kapcsolásához, azonban túlságosan drágák az alacsony sebességű perifériák, például az egér vagy a billentyűzet számára. Történelmileg minden szabványos B/K eszköz egyedi módon kapcsolódott a számítógéphez, amelyben az új eszközök számára volt néhány szabad ISA vagy PCI-csatlakozó. Ez a megoldás már a kezdetektől problémás volt. Például az új perifériák gyakran saját ISA vagy PCI kártyával kaphatók. Általában a felhasználó felelős a kártyán lévő kapcsolók és vezetékáthidalások (jumper) helyes konfigurálásáért, valamint azért, hogy e beállítások ne kerüljenek konfliktusba más kártyákkal. Azután a felhasználónak fel kell nyitnia a számítógép házát, gondosan behelyezni az új kártyát, visszazárni a házat, majd újraindítani a számítógépet. Sok ember számára ez az eljárás nehézkes és hibalehetőségeket rejt magában. Ráadásul az ISA- és PCI-csatlakozások száma meglehetősen korlátozott (általában kettő vagy három). A „csatlakoztasd és működik” kártyák ugyan kiküszöbölik a vezetékáthidalásokkal való vesződést, azonban továbbra is a felhasználónak kell felnyitnia a számítógépet, és betennie a kártyát, valamint a síncsatlakozások száma is korlátozott. 1993-ban hét vállalat – a Compaq, DEC, IBM, Intel, Microsoft, NEC és a Northern Telecom – képviselői összeültek, hogy megvitassák a problémát, és a számítógépek és az alacsony sebességű perifériák összekapcsolásának jobb módját dolgozzák ki. Azóta már cégek százai csatlakoztak hozzájuk. Az eredményül kapott szabványt, az USB-t hivatalosan 1998-ban jelentették be, és már széles körben alkalmazzák személyi számítógépekben. Néhány cél azok közül, amelyeket az USB-t eredetileg kidolgozó és a munkát elindító cégek fogalmaztak meg: A felhasználóknak ne kelljen minikapcsolókat (switch), vezetékátkötéseket (jumper) beállítaniuk sem a bővítőkártyákon, sem a készülékekben. A felhasználóknak ne kelljen felnyitniuk a számítógép házát, hogy egy új perifériát csatlakoztathassanak. Egyetlen fajta kábel legyen, amely az összes készülék számára alkalmas. A perifériák az elektromos energiát is ezen a kábelen keresztül kapják. Egyetlen számítógéphez legalább 127 eszközt lehessen csatlakoztatni. A rendszer ki tudjon szolgálni valós idejű perifériákat is (hang, telefon). A készülékeket úgy is lehessen telepíteni, hogy a számítógép közben működik. Ne kelljen újraindítani a számítógépet a készülék csatlakoztatása után. Az új sín és a rajta lévő eszközök előállítási költsége ne legyen magas. Az USB-szabvány kielégíti mindezeket az elvárásokat. Olyan alacsony sebességű eszközök számára tervezték, mint a billentyűzet, egerek, állóképkamera, fényképszkenner, digitális telefon stb. Az USB 1.0-ás verziójának sávszélessége mintegy 1,5 MB/s, amely elegendő a billentyűzet és az egerek számára, az 1.1-es verzió pedig 12 MB/s sebességgel működik, amely elegendő a nyomtatók, digitális fényképezőgépek és sok más eszköz számára. Ezeket a viszonylag alacsony határértékeket a költségek alacsony szinten tartása miatt választották.
34.
Egy USB-rendszer egy központi csomópontból (root hub) áll, amely a rendszersínre csatlakozik. Ez a csomópont több csatlakozót tartalmaz a külső B/K eszközök vagy újabb csomópontok számára, amelyek további csatlakozási lehetőségeket biztosíthatnak, így az USBrendszer topológiája egy olyan fa, amelynek a gyökere a számítógép belsejében lévő központi csomópont. A kábelek végén két különböző csatlakozó van, egyik csak a B/K eszközbe, a másik csak az elosztóba dugható be, ezzel meggátolható, hogy véletlenül két csomópont két csatlakozója legyen összekötve a kábellel. A kábel négy vezetékszálat tartalmaz: kettőt az adatok, egyet a tápfeszültség (+5 V) és egyet a föld számára. A jeltovábbító rendszer a 0-kat feszültségátmenetként, az 1-eket pedig a feszültségátmenet hiányaként továbbítja, így egy hosszú 0 sorozat szabályos impulzusfolyamot generál. Egy új eszköz csatlakoztatásakor a központi csomópont érzékeli az eseményt és megszakítást kezdeményez. Ezután az operációs rendszer lekérdezi, milyen eszközről van szó, valamint hogy mekkora USB-sávszélességre van szüksége. Ha az operációs rendszer úgy dönt, hogy van elegendő sávszélesség az eszköz számára, akkor az eszköznek címet, egyedi azonosító számot (1-127) ad, majd ezt a címet és más paramétereket tölt a B/K eszközben lévő konfigurációs regiszterekbe. Ilyen módon az új eszközök menet közben csatlakoztathatók a számítógéphez anélkül, hogy a felhasználónak bármit is konfigurálnia kellene, vagy új ISA vagy PCI kártyákat kellene a számítógépbe helyeznie. A még konfigurálatlan eszköz címe kezdetben 0, tehát megcímezhető. A kábelezés megkönnyítése érdekében sok USB-eszköz beépített csomópontot tartalmaz, amelybe további USB-eszközök dughatók. Például egy USB-monitor rendelkezhet két csatlakozóval: a bal, illetve a jobb oldali hangszóró számára. Logikailag az USB-rendszer úgy tekinthető, mint bitcsatornák halmaza a központi csomóponttól az eszközökig. Minden eszköz legfeljebb 16 alcsatornára oszthatja fel a csatornáját a különböző jellegű adatok számára (például hang, video). Minden egyes csatornán vagy alcsatornán az adatok a központi csomópontból az eszköz felé vagy fordított irányban áramolnak. Két B/K eszköz között nincs adatforgalom. Pontosan 1,00 +- 0,05 ms-ként a központi csomópont egy új üzenetváltási keretet (frame) küld szét, amelynek segítségével minden B/K eszközt szinkronizál. Egy üzenetváltási keret mindig egy bitcsatornához kapcsolódik, és csomagokból áll, amelyekből az elsőt minden esetben a központi csomópont küldi az eszköznek. A keretben lévő többi csomag iránya lehet ugyanilyen vagy az eszköztől a központi csomópont felé haladó. Az USB négyféle keretet különböztet meg: vezérlési, izoszinkron, tömeges adat és megszakítási kereteket. A vezérlési keret az eszközök konfigurálására szolgál, parancsok küldésére vagy az eszközök állapotának lekérdezésére. Az izoszinkron kereteket a valós idejű eszkzök használják, például a mikrofonok, hangszórók és telefonok, amelyeknek pontosan meghatározott (időnként feltétlenül) adatokat kell küldeniük vagy fogadniuk, bár a jeleknek jól kiszámítható késleltetése van. Hiba esetén az adatokat nem kell megismételni. A tömeges adatkeretek nagy tömegű adat átvitelére szolgálnak a számítógéptől az eszközhöz, például a nyomtatókhoz, vagy fordítva, de valós idejű továbbításra nincs szükség. Végül, a megszakítási keretekre azért van szükség, mert az USB nem támogatja a megszakításokat. Például ahelyett, hogy a billentyűzet minden
35.
billentyű lenyomásakor megszakítást okozna, az operációs rendszer le tudja kérdezni 50 ms-ként és össze tudja gyűjteni a billentyűlenyomásokat. Egy keret egy vagy több csomagot tartalmaz, valószínűleg mindkét irányúból néhányat. Négy különböző csomag van: token, adat, kézfogás és speciális. A token csomagok a központi csomópont felől érkeznek az eszközökhöz, és a feladatuk a rendszer irányítása. A keret kezdete csomag (SOF) az első minden keretben; ez jelzi a keret kezdetét. Ha nincs teendő, a SOF lehet az egyetlen csomag a keretben. Az IN token csomag egy lekérdezés, az eszköztől kér bizonyos adatokat. Az IN csomagban lévő mezők azonosítják a bitalcsatornát, így az eszköz tudja, milyen adatokat kell visszaküldenie (ha több adatfolyama is van). Az OUT token csomag azt jelzi, hogy utána adatok következnek az eszköz számára. A negyedik token csomagtípus a SETUP, és az eszközök konfigurálására használják. A token csomagon kívül még háromfajta csomag van. Ezek a DATA, a kézfogás és a speciális csomag. Egy 8 bites szinkronizációs mezőből, egy 8 bites csomagtípusból (PID) és a hasznos adatból, valamint egy 16 bites CRC kódból áll, a hibás átvitel detektálására. Háromfajta kézfogás csomag van: az ACK, a NAK és a STALL. Miután az USB-szabványt 1998-ban véglegesítették, az USB tervezőinek további feladatuk már nem volt, így az USB egy új, nagy sebességű, USB 2.0-nak nevezett verzióján kezdtek el dolgozni. A szabvány hasonlít a régebbi 1.1-es verzióhoz és visszafele kompatibilis is vele, azonban egy új, harmadik sebességet (480 Mbps) vezet be a két meglévő mellé. Vannak még további kisebb különbségek is, mint például az interfész a központi csomópont és a vezérlő között. AZ USB 1.1-ben kétféle interfész volt. Az elsőt, az UHCI-t, az Intel tervezte és a terhek zömét a szoftverkészítőkre hárította. A másikat, az OHCI-t a Microsoft tervezte, és a terhek zömét a hardverfejlesztőkre hárította. Az USB 2.0-nál megegyeztek egyetlen új interfészben, amelynek a neve EHCI. Most, hogy az USB 480 Mbps sebességgel működik, nyilvánvalóan versenytársa az IEEE 1394 szabványú sínnek, amelyet közismerten FireWire-nek neveznek, és ami 400 Mbps sebességgel működik. Bár majdnem minden új Pentium rendszer az USB 2.0-val kapható, mégsem valószínű, hogy az IEEE 1394 eltűnik, mert a szórakoztató-elektronikai ipar támogatja. A kézi kamerákat, DVDlejátszókat és más hasonló eszközöket a belátható jövőben ezután is ellátják majd 1394-es interfésszel, mivel az eszközök gyártói nem akarják vállalni egy olyan szabványra történő áttérés költségeit, amely alig valamivel jobb, mint amijük jelenleg van. A vásárlók szintén nem szeretnek áttérni másik szabványra.
36.
14. PCI Express Bár a PCI sín megfelelően működik a legtöbb napi alkalmazásban, a nagyobb B/K sávszélesség iránti igény beleszemetelt az egykor szép, tiszta belső PC-architektúrába. A 3.53. ábrából világosan látszik, hogy ma már nem a PCI sín az a központi elem, amely a PC részeit összekapcsolja. A csatoló lapka vette át ezt a szerepet. A probléma lényege, hogy egyre nagyobb számú B/K eszköz van, amely túl gyors a PCI sínhez. A sín órajel-frekvenciájának megbütykölése nem jó megoldás, mivel akkor megjelennek a sínaszimmetria problémái, az áthallás a vezetékek között és a kapacitáshatások, és csak még rosszabb lesz a helyzet. Minden olyan esetben, amikor egy B/K eszköz túl gyors kezd lenni a PCI sínhez, az Intel egy újabb speciális portot ad a csatoló lapkához, lehetővé téve, hogy ez az eszköz kikerülje a PCI sínt. Nyilvánvaló azonban, hogy ez nem egy hosszú távra szóló megoldás. A másik probléma a PCI sínnel az, hogy a bővítőkártyák mérete elég nagy. Nem férnek be egy hordozható asztali számítógépbe (laptopba) vagy egy tenyér számítógépbe (palmtopba), a gyártók pedig még kisebb eszközöket szeretnének előállítani. Ezenkívül, néhány gyártó újra szeretné strukturálni a PC-t: a CPU-t és a memóriát egy lezárt dobozba tennék, a mágneslemezegységet pedig a monitor belsejébe. PCI kártyákkal ez lehetetlen. Több megoldást is bejelentettek már, a legvalószínűbb nyertes azonban a PCI Express. Nem sok köze van a PCI sínhez, valójában egyáltalán nem is sín, de a piaci szakemberek nem szeretnék a jól ismert PCI nevet elveszíteni. Már egy ideje kaphatók olyan PC-k, amelyek ilyet tartalmaznak. Most nézzük meg, hogyan működik. A PCI Express architektúra A PCI Express megoldás lényege, hogy szabaduljunk meg a párhuzamos síntől, annak sok sínmesterétől és szolgájától, és térjünk át jól megtervezett, nagy sebességű közvetlen soros kapcsolatokra. Ez a megoldás gyökeresen szakít az ISA/EISA/PCI síntradícióval. Sok üzletet a lokális hálózatok világából, különösen a kapcsolt Ethernet-hálózatoktól kölcsönöztek. Az alapötlet a következő: a PC legbelül CPU, memória- és B/K vezérlőlapkákból áll, amelyeket össze kell kapcsolni. A PCI Express egy általános célú kapcsolót biztosít a lapkák összekötéséhez soros kapcsolat segítségével. Egy tipikus ilyen konfigurációt mutat be a 3.57. ábra. Ahogyan az a 3.57. ábrán is látszik a CPU, a memória és a gyorsítótár hagyományos módon kapcsolódik a csatoló lapkához. Ami új, az a kapcsoló, amely a csatoló lapkához kapcsolódik. Mindegyik B/K lapkának saját egyedi összeköttetése van a kapcsolóhoz. Mindegyik kapcsolat két egyirányú csatornából álló pár; az egyik csatorna a kapcsolóhoz, a másik pedig a kapcsolótól szállít adatokat. Mindegyik csatorna két vezetéket jelent, egyik a jel, a másik a föld számára, amely így nagy zajtűréssel rendelkezik a nagy sebességű átvitel során. Ez az architektúra a jelenlegit egy sokkal egységesebb modellel váltaná fel, amelyben minden eszközt azonos módon kezelnek.
37.
A PCI Express a régi PCI sín architektúrától három fontos dologban tér el. Kettőt már láttunk: a központosított kapcsoló a több leágazású sín helyett, valamint a keskeny közvetlen soros kapcsolat a széles, párhuzamos sín helyett. A harmadik ennél kifinomultabb. A PCI sín mögött rejlő elképzelés az, hogy a sínmester parancsot ad a szolgának, ha egy szót vagy egy adatblokkot be akar olvasni. A PCI Express modellje ezzel szemben az, hogy egyik eszköz egy adatcsomagot küld a másik eszköznek. A csomagfogalom, amely egy fejlécből és a hasznos adatból áll, a hálózatok világából származik. A fejléc vezérlési információt tartalmaz, így nincs szükség arra a sok vezérlőjelre, mint a PCI sínnél. A hasznos adat tartalmazza az átvinni kívánt adatot. Valójában egy PC a PCI Express-szel egy kicsi csomagkapcsolt hálózat. E három fő területtel szakítottak, ezeken kívül azonban vannak még kisebb különbségek is. A negyedik különbség az, hogy hibajelző kódot használnak a csomagoknál, amellyel a PCI sínnél nagyobb fokú megbízhatóságot biztosítanak. Az ötödik, hogy a kapcsolat egy lapka és a soros kapcsoló között hosszabb lehet, elérheti az 50 cm-t; ez megengedi a rendszer áttervezését. A hatodik, hogy a rendszer bővíthető, mivel egy eszköz lehet akár egy másik soros kapcsoló is, amellyel a kapcsolók fastruktúráját hozhatják létre. A hetedik különbség, hogy az eszközök melegen csatlakoztathatók, azaz csatlakoztathatók és eltávolíthatók a rendszerből, mialatt az tovább működik. Végül, a soros csatlakozók sokkal kisebbek, mint a régi PCI-csatlakozók, így az eszközök és a számítógépek sokkal kisebbek lehetnek. Mindent egybevéve, mindez jelentős eltávolodást jelent a PCI síntől. A PCI Express protokollrendszer Maradva a csomagkapcsolt hálózati modellnél, a PCI Express réteges kapcsolati protokollrendszerrel rendelkezik. A protokoll a két fél között párbeszédet irányító szabályok egy halmaza. A protokollrendszer protokollok hierarchiája, amelyben az egyes problémákkal külön rétegekben foglalkoznak. Példának vegyünk egy üzleti levelet. Vannak megállapodások a levél fejrészének tartalmáról és elhelyezkedéséről, a címzett adatairól, a dátumról, az üdvözlésről, a levél szövegéről, az aláírásról és így tovább. Vehetjük úgy, hogy ez a levél egy protokoll. Vannak további megállapodások a borítékról, például a méretéről, hogy hová kerül a feladó címe, és mi a formája, hová kerül a címzett és milyen formában, hová kerül a bélyeg és így tovább. Ez a két réteg és a hozzájuk tartozó két protokoll független. Például teljesen újraformázhatjuk a levelet, de ugyanazt a borítékot használjuk, vagy fordítva. A réteges protokollok a hatékony, moduláris tervezést szolgálják és évtizedek óta széles körben elterjedtek a hálózati szoftverek világában. Ami újdonság, hogy most a sínhardverbe is beépítésre kerültek. Vizsgáljuk meg az egyes rétegeket alulról felfelé. A legalsó réteg a fizikai réteg. Azzal foglalkozik, hogy biteket továbbít a küldőtől a fogadónak egy közvetlen kapcsolaton keresztül. Minden egyes kapcsolat egy vagy több szimplex (azaz egyirányú) csatornapárból áll. A legegyszerűbb esetben egy pár van, egy-egy csatorna mindkét irányban, de 2, 4, 8, 16 vagy 32 pár is megengedett. Egy-egy csatornát sávnak neveznek. A sávok számának mindkét irányban azonosnak kell lennie. Az első generációs termékeknek bármely irányban legalább 2,5 Gbps sebességet kell biztosítaniuk, de azt remélik, hogy a sebesség hamarosan mindkét irányban eléri a 10 Gbps-t. Az ISA/EISA/PCI sínekkel ellentétben a PCI Expressnek nincs fő órajel-generátora. Az eszközök azonnal elkezdhetnek adni, amint van elküldeni való adatuk. Ez a szabadság gyorsabbá teszi a rendszert, de egyúttal problémához is vezet. Tegyük fel, hogy az 1-es bit +3 V-tal kódolódik, a 0-s bit
38.
pedig 0 V-tal. Ha az első néhány bájt mind 0 bitekből áll, honnan tudja a fogadó, hogy adatok érkeznek. Elvégre egy 0 bit sorozat pontosan úgy néz ki, mint egy megszakadt kapcsolat. Ezt a problémát az úgynevezett 8b/10b kódolással oldották meg. A megoldás az, hogy 1 bitet használnak egyetlen hasznos bájt kódolására egy 10 bites szimbólumban. Az 1024 lehetséges 10 bites értékből kiválasztották azokat a megengedhető szimbólumokat, amelyek elegendő jelváltást tartalmaztak ahhoz, hogy bithatárra szinkronizálják a küldőt és a fogadót fő órajel-generátor nélkül is. A 8b/10b kódolás következményeként a kapcsolat teljes 2,5 Gbps kapacitása csupán 2 Gbps hasznos adatmennyiség átvitelére elegendő. Amíg a fizikai réteg a bitek átvitelével foglalkozik, addig a kapcsolati réteg a csomagok átvitelével. Fogja a tranzakciós rétegtől kapott fejlécet és hasznos adatot, egy sorszámot és egy CRCnek nevezett hibajelző kódot ad hozzá. A CRC egy bizonyos algoritmusnak a fejlécre és a hasznos adatokra történő futtatásával számítható ki. Amikor a csomag megérkezik, a fogadó is elvégzi ugyanezt a számítást a fejlécre és a hasznos adatokra, és összehasonlítja az eredményt a csomaghoz csatolt CRC-vel. Ha megegyeznek, egy rövid nyugtázó csomagot küld vissza, ezzel jelzi a csomag hibátlan megérkezését. Ha a két eredmény nem egyezik, a fogadó kéri a csomag újraküldését. Ezen a módon az adatintegritás jelentősen javult a PCI sínhez képest, amely nem biztosított lehetőséget a sínen átküldött adatok ellenőrzésére és újraküldésére. Annak elkerülésére, hogy egy gyors küldő eszköz olyan mennyiségű csomaggal árasszon el egy lassú fogadó eszközt, amelyet az nem tud kezelni, egy folyamatvezérlő mechanizmust használnak. A mechanizmus lényege, hogy a fogadó eszköz elküld a küldőnek egy bizonyos kredit értéket, a beérkező csomagok tárolására rendelkezésre álló puffer méretét. Amikor a kredit elfogy, a küldőnek be kell fejeznie a küldést, amíg új kreditet nem kap. Ezt a sémát elterjedten használják mindenféle hálózatban, hogy megakadályozzák a küldő és a fogadó eltérő sebességéből eredő adatvesztést. A tranzakciós réteg kezeli a síntevékenységeket. Egy szó beolvasása a memóriából két tranzakciót kíván: az egyiket a CPU vagy egy DMA csatorna kezdeményezi, és kér bizonyos adatokat, a másikat az adatokat szolgáltató céleszköz. Azonban a tranzakciós réteg több annál, mint egyszerű olvasások és írások kezelése. A kapcsolati réteg által biztosított nyers csomagküldést további szolgáltatásokkal egészíti ki. Először is, minden egyes sávot feloszthat nyolc virtuális áramkörre, amelyek mindegyike különböző jellegű forgalmat bonyolít le. A tranzakciós réteg meg tudja címkézni a csomagokat, aszerint, hogy a nyolc forgalmi osztály melyikéhez tartoznak, a címkében lehetnek olyan attribútumok, mint a magas prioritás, alacsony prioritás, szimatolás tiltása, soron kívüli kézbesíthetőség és még sok egyéb. A kapcsolólapka használhatja ezeket a címkéket, amikor arról dönt, melyik lesz a legközelebb továbbítandó csomag. Minden tranzakció az alábbi négy címtartomány egyikét használja: 1. 2. 3. 4.
Memóriaterület B/K terület Konfigurációs terület Üzenetterület
39.
A memória- és a B/K terület hasonló a jelenlegi rendszerekben lévőkhöz. A konfigurációs terület olyan szolgáltatások megvalósítására szolgál, mint a plug-and-play. Az üzenetterület a rengeteg létező hardvervezérlőjel szerepét veszi át. Valami ilyesmire szükség van, mivel a PCI sín vezérlőjelei közül egy sincs meg a PCI Expressnél. A PCI Express rendszer a szoftverrétegen keresztül csatlakozik az operációs rendszerhez. Képes a PCI sín emulálására, így a létező operációs rendszerek változtatás nélkül tudnak működni a PCI Express rendszert alkalmazva. Természetesen ez a módszer nem hasznosítja a PCI Express minden erejét, azonban a visszafelé kompatibilitás szükséges rossz, amit nem hagyhatunk figyelmen kívül, amíg az operációs rendszereket nem módosítják úgy, hogy teljesen használatba vegyék a PCI Expresst. A tapasztalatok szerint ez eltarthat egy darabig. Az információáramlást a 3.58. (b) ábra mutatja. Amikor a szoftverréteg parancsot kap, azt továbbadja a tranzakciós rétegnek, amely átalakítja a parancsot fejléc és hasznos adat alakúra. Ezt a két rész azután a kapcsolati réteghez kerül, amely egy sorszámot kapcsol a csomag elejéhez, és hibajelző kódot a végéhez. Az így bővített csomag kerül azután a fizikai réteghez, amely kerettel zárja le a csomag mindkét végét, hogy egy fizikai csomagot hozzon létre, amelyet aztán ténylegesen elküld. Évtizedek óta nagy sikerrel használják a hálózatok világában azt az elképzelést, hogy miden réteg a protokoll rétegeiben egyre mélyebbre haladva további kiegészítő információt ad az adatokhoz. A hálózatok és a PCI Express között az a nagy különbség, hogy a hálózatok esetében a különböző rétegekben lévő kód majdnem mindig szoftver, amely az operációs rendszer része. A PCI Expressnél ez mind az eszközben lévő hardver része.
40.
15. A CPU részei, feladatai. CPU, adatút. Három, kettő, egy és nulla címes utasítások. CPU és részei, feladatai Egy egyszerű sínalapú számítógép felépítése látható a 2.1 ábrán. A CPU a számítógép „agya”. Feladata az, hogy a központi memóriában tárolt programokat végrehajtsa úgy, hogy a programok utasításait egymás után beolvassa, értelmezi és végrehajtja. Az egyes részegységeket egy sín köti össze, amely címek, adatok és vezérlőjelek továbbítására szolgáló párhuzamos vezetékköteg. A sín lehet a CPU-t tekintve külső, amely összekapcsolja azt a memóriával és a B/K egységekkel, illetve lehet belső, ahogy azt hamarosan látni fogjuk. A CPU több különálló részegységből áll. A vezérlőegység feladata az utasítások beolvasása a központi memóriából és az utasítások típusának megállapítása. Az aritmetikai-logikai egység a program utasításainak végrehajtásához szükséges műveleteket végez, mint például az összeadás vagy a logikai ÉS. A CPU egy kisméretű, gyors memóriát is tartalmaz, amelyben részeredményeket és bizonyos vezérlőinformációkat tárol. Ez a memória több regiszterből áll, mindegyiknek meghatározott mérete és funkciója van. Legtöbbször az összes regiszter azonos méretű. Minden regiszter képes tárolni egy számot, amelynek az értéke kisebb a regiszter mérete által meghatározott maximumnál. A regisztereket nagy sebességgel lehet olvasni és írni, mivel a CPU-n belül vannak. A legfontosabb regiszter az utasítás- vagy programszámláló, amely a következő végrehajtandó utasítás címét tartalmazza. Az „utasításszámláló” név kissé félrevezető, mert semmit sem számlálunk meg vele, ennek ellenére az elnevezés általánosan elterjedt. Fontos még az utasításregiszter, amely az éppen végrehajtás alatt levő utasítást tartalmazza. A legtöbb számítógép még számos egyéb regisztert is tartalmaz, ezek némelyike általános célú, míg mások speciális célúak. A CPU felépítése Egy tipikus Neumann-elvű számítógép egy részének belső felépítése a 2.2 ábrán látható részletesebben. Ez a rész az ún. adatút, amelynek részei a regiszterek, az aritmetikai-logikai egység és az ezeket összekötő néhány sín. A regiszterek két ALU bemeneti regisztere csatlakoznak, ezeket az ábrán A-val és B-vel jelöltük. Ezek a regiszterek tárolják a bemeneti adatokat, amíg az ALU más számításokon dolgozik. Az adatút minden számítógépben nagyon fontos, ezért hosszasan fogjuk tárgyalni a könyv fejezeteiben. Maga az ALU a bemenő adatokon összeadást, kivonást és egyéb egyszerű műveleteket végez, és az eredményt a kimeneti regiszterbe teszi. Ennek a kimeneti regiszternek a tartalma visszaírható egy regiszterbe. Később, ha szükséges, a regiszter tartalma beírható a memóriába. Nem minden számítógép terve tartalmazza az A, B és a kimeneti regisztert. Az ábrán az összeadást mutattuk be. A legtöbb utasítás a következő két kategória egyikébe sorolható: regiszter-memória vagy regiszter-regiszter. A regiszter-memória utasítások segítségével tölthetünk át szavakat a memóriából regiszterekbe, ahol a soron következő utasítások például az ALU bemeneteként használhatják. Más regiszter-memória utasítások segítségével a regiszterek tartalmát írhatjuk vissza a memóriába.
41.
A másik csoportba tartoznak a regiszter-regiszter utasítások. Egy tipikus regiszter-regiszter utasítás vesz két operandust a regiszterekből, elhelyezi őket az ALU bemeneti regisztereibe, az ALU elvégez rajtuk valamilyen műveletet – például összeadást vagy logikai ÉS-t -, majd az eredményt tárolja az egyik regiszterbe. A két operandusnak az ALU-n történő átfuttatásából és az eredmény regiszterbe tárolásából álló folyamatot adatútciklusnak nevezzük, ez a legtöbb CPU lelke. Jelentős mértékben ez határozza meg, hogy a gép mire képes. Minél gyorsabb az adatútciklus, annál gyorsabban dolgozik a gép. Utasításformátumok Minden utasítás tartalmaz egy műveleti kódot és általában valamilyen kiegészítő információt, mint hogy hol vannak az operandusok, és az eredmény hova kerül. Azt az általános módszert, amely meghatározza az operandusok helyét (tehát a címüket), címzésnek nevezzük. Az utasítás mindig tartalmaz műveleti kódot, amely megmondja, hogy mit csinál az utasítás. Ezenkívül tartalmazhatja 0, 1, 2 vagy 3 operandus címét. Vannak gépek, amelyeknél minden utasítás azonos hosszúságú, mások esetén több, különböző hosszúságú utasítás lehet. Az utasítások hossza lehet a szóhosszal azonos, rövidebb vagy hosszabb is. Ha minden utasítás azonos hosszúságú, akkor könnyebbb a dekódolás, de pazarló a tárolás, mert a közös hossz megegyzeik a leghosszab szó hosszával.
42.
16. Mikroarchitektúra szint. Az ALU-val végezhető műveletek. Memória műveletek. ALU és az adatút vezérlése. Mikroutasítások: Mic-1. Mic-1 működése. Mikroarchitektúra szint A digitális logikai szint felett helyezkedik el a mikroarchitektúra szintje. Feladata a felette lévő utasításrendszer-architektúra szint (ISA-szint) megvalósítása. Ennek a szintnek a tervezése függ az ISA-szint megvalósításától, valamint a számítógép ár és teljesítmény kitűzéseitől. A mikroarchitektúrának tartalmaznia kell egy mikroprogramot a ROM-ban, melynek feladata betölteni, dekódolni és végrehajtani az IJVM utasításokat. Ez a mikroprogram hatékonyan vezérli az egyedi kapukat az aktuális hardverben. Az ALU-val végezhető műveletek Az ALU tevékenységét 6 vezérlővonal határozza meg. Közülük F0 és F1 határozza meg az ALUműveletet, ENA és ENB egyedileg engedélyezi a bemeneteket, INVA invertálja a bal oldali bemenetet, és INC a legalacsonyabb helyiértékű biten az „átvitel be” bemenet. INC beállítása gyakorlatilag 1-et hozzáad az eredményhez. Azonban az ALU vezérlővonalaknak nem mind a 64 kombinációja csinál valami hasznosat. (A 4.2. ábrán található néhány érdekesebb kombináció és a hozzá tartozó tevékenység.) ALU műveletek pl.: negálás, komplementer-képzés, összeadás, kivonás, inkrementálás, dekrementálás, logikai műveletek, stb.
Az ALU-nak két adatbemenetre van szüksége: a bal oldalira (A) és a jobb oldalira (B). A bal oldali bemenet a H (Holding) tartó regiszterhez kapcsolódik. A jobb oldali bemenet pedig a B sínhez, amelyik képes betölteni a kilenc forrás bármelyikét. A H úgy tölthető fel, hogy választunk egy olyan ALU-tevékenységet, amelyik a jobb oldali bemenetet (a B sínről) csupán átengedi az ALU kimenetére. Az egyik ilyen tevékenység az ALU bemeneteit összeadja, csak negált ENA-val, ami a bal oldali bemenetet nullává teszi. Nullát adva a B sín értékéhez, éppen a B sín értékét kapjuk. Ezt az eredmnéyt azután módosítás nélkül küldjük tovább a léptetőn, és H-ban tároljuk.
43.
A fenti függvényeken kívül két másik vezérlővonal használható egymástól függetlenül az ALU kimenetének irányítására. Az SLLB (Shift Left Logical, léptetés balra logikailag) a tartalmat 1 bájttal balra lépteti, feltöltve nullával a legalacsonyabb helyértékű 8 bitet. SRA1 (Shift Right Arithmetic, aritmetikai léptetés jobbra) a tartalmat 1 bittel jobbra lépteti, változatlanul hagyva a legmagasabb helyértékű bitet. Hangsúlyozzuk, hogy lehetséges olvasni és írni ugyanazt a regisztert egy cikluson belül. F0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1
F1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1
ENA 1 0 1 1 1 1 1 0 1 0 1 1 1 0 0 0
ENB 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0
INVA 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 1
INC 0 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0
Tevékenység A B A B A+B A+B+1 A+1 B+1 B–A B–1 -A A AND B A OR B 0 1 -1
Memória műveletek Gépünk 2 módon kommunikálhat a memóriával, egy 32 bites, szócímzésű memóriaporton, és egy 8 bites bájtcímzésű memóriaporton. A 32 bitest 2 regiszter vezérli, a MAR (Memory Address Register) és az MDR (Memory Data Register). A 8 bitest 1 regiszter, a PC vezérli, ez 1 bájtot olvas be az MBR alsó 8 bitjébe. Ez utóbbi csak adatot olvasni képes a memóriából, adatot írni nem. Ezeket a regisztereket egy vagy két vezérlőjel irányítja. Mival a MAR nem kapcsolódik a B sínre, nincs engedélyező jele sem. A H-nak sincs egyikből sem, mert mindig engedélyezett, hiszen ez az ALU egyetlen lehetséges bal oldali bemenete. Mivel az MBR nem tölthető a C sínről, ezért nincs írójele se (bár van két másik engedélyező jele). Egy memória olvasás vagy írás kezdeményezéséhez a megfelelő memóriaregisztereket fel kell tölteni, majd egy olvasó vagy író jelet kell kibocsátani a memória felé. A MAR szó címeket tartalmaz, úgy, hogy a 0, 1, 2… értékek egymást követő szavakra hivatkoznak, a PC pedig bájt címeket tartalmaz, úgy, hogy a 0, 1, 2… értékek egymást követő bájtokra hivatkoznak. Tehát pl. 2-t téve a PC-be, és elindítva egy memóriaolvasást, ki fogjuk olvasni a memória 2. bájtját, és az MBR alsó 8 bitjére tesszük. 2-t téve a MAR-ba, és elindítva egy olvasást, kiolvassa a memória 8-11. bájtjait (vagyis a 2. szót), és az MDR-be teszi.
44.
A valódi fizikai megvalósításban csak 1 tényleges memória van, és az bájtszervezésű. Megengedi a MAR-nak, hogy szavakban számláljon, mialatt a fizikai memória bájtokban számlál. Ez úgy küszöbölhető ki, hogy a MAR 0. bitje a címsín 2. vonalához kötődik, az 1. bit a 3. vonalhoz és így tovább. Az MBR előjeltelenül vagy előjelesen másolható a B sínre. Amikor előjeltelen értékre van szükségünk, akkor a B sínre kerülő 32 bites szó tartalmazza az MBR értékét az alsó 8 biten, és 0-kat a magasabb 24 biten. A másik lehetőség, hogy a 8 bites MBR-t 32 bites szóvá konvertáljuk, úgy, hogy egy -128 és +127 közötti előjeles értéknek tekintjük, és generálunk egy 32 bites szót. Ez valójában az MBR előjelbitjének a B sín felső 24 bitjére történő másolását jelenti, és előjel-kiterjesztésnek nevezzük. Ilyenkor a felső 24 bit vagy mind 0, vagy mind 1 lesz, attól függően, hogy a 8 bites MBR bal szélső bitje 0 vagy 1. Az ALU és az adatút vezérlése Lásd: Máté: Architektúrák 5. előadás Andrew S. Tanenbaum: Számítógép architektúrák 261-265. o. Mikroutasítások: Mic-1 Lásd: Máté: Architektúrák 5. előadás Andrew S. Tanenbaum: Számítógép architektúrák 261-265. o. Mic-1 működése Lásd: Máté: Architektúrák 5. előadás Andrew S. Tanenbaum: Számítógép architektúrák 261-265. o.
45.
Az adatút sok 32 bites regiszterből, sínekből, ALU-ból és léptetőből áll. Az SLL8 (Shift Left Logical) 8 bittel balra léptet, az SRA1 (Shift Right Arithmetic) pedig 1 bittel jobbra. Az ALU bemenetei a H (Holding - tartó) és a B sín. Egy adatút cikluson belül lehetséges egy regiszterből olvasni és az eredményt akár ugyanoda visszaírni. Az adatút vezérléséhez 29 jelre van szükség. Ezek közül 9 jel szolgálja a B sínre írást a regiszterekből, 6 az ALU és 2 a léptető vezérlésére kell, 9 jel a C sínről a regiszterekbe íráshoz, valamint 3 a memória eléréséhez. Utóbbiból 2 jel a szó íráshoz/olvasáshoz kell, 1 pedig bájt olvasáshoz. Összesen tehát 29 jel szükséges, azonban a B sínre csak 1 regiszter írhat egyszerre, ezért 9 helyett elég 4 jel, vagyis összesen 24 jel is elegendő. Minden mikroutasítás 36 bites. Ebből 24 bitet az adatút vezérléséhez, 9 bitet a következő utasítás címének megadásához, 3 bitet pedig a következő utasítás kiválasztásának módjára használunk. A Mic-1 többek között tartalmaz egy 512x36 bites vezérlőtárat a mikroprogramnak, egy MPC-t (MicroProgram Counter – mikroprogram-utasításszámláló) és egy MIR-t (MicroInstruction Register – mikroutasítás-regiszter). Az adatút ciklus elején MIR feltöltődik a vezérlőtár MPC által mutatott szavával, kialakul a B sín tartalma, ALU és a léptető megtudja, mit kell csinálnia. ALU és a léptető elvégzi a feladatát, a C sín, N (Negativ) és Z (Zero) megkapja az új értékét. A regiszterek feltöltődnek a C sínről. Ha az előző ciklus adatot kért a memóriából, akkor MBR/MDR megkapja az értékét. Kialakul MPC új értéke. Ezután kezdődik a memóriaciklus. A memóriaciklus MAR illetve PC feltöltése után kezdődik, ezért ha a memória címet módosította ez a mikroutasítás, akkor a memória cím a módosított MAR illetve PC regiszter értéke lesz. Olvasásnál az eredmény csak 2 ciklussal később használható, mert MDR illetve MBR csak a következő adatút ciklus vége felé töltődik fel a memóriából. MPC új tartalmának kialakítása úgy történik, hogy a 9 bites következő cím (Addr) az MPC-be kerül. JAMN vagy JAMZ esetén MPC legmagasabb bitjének és az N vagy Z bitnek logikai vagy kacsolata képződik MPC legmagasabb helyértékével. Ez egy feltételes ugrás (elágazás) a mikroprogramban. JMPC esetén MPC 8 alacsonyabb helyértékű bitjének és MBR 8 bitjének bitenkénti vagy kapcsolata képződik MPC-ben az adatút ciklus vége felé. Ilyenkor Addr 8 alacsonyabb helyértékű bitje általában 0. Ez egy feltétlen ugrás az MBR-ben tárolt címre. Ezután kezdődik az újabb mikroutasítás végrehajtása.
46.
17. A Mic-1 memória ciklusa. Lásd: Máté: Architektúrák 5. előadás Andrew S. Tanenbaum: Számítógép architektúrák 261-265. o.
47.
18. MPC új értékének kialakulása Mic-1-en. Lásd: Máté: Architektúrák 5. előadás Andrew S. Tanenbaum: Számítógép architektúrák 261-265. o.
48.
19. A WIDE utasítás hatása és működése Mic-1-en. A WIDE utasítás egy prefix utasítás, a következő utasításnak 16 bites indexe van. A WIDE a szokásos módon dekódolódik, amely a wide 1-hez vezet, ami kezeli a WIDE opcodet. Bár a „kiszélesítendõ” opcode már közvetlenül elérhetõ az MBR-ben, wide 1 elhozza az opcode utáni elsõ byte-ot, mert a mikroprogram logikája mindig elvárja azt, hogy ott legyen. Ezután egy második többirányú elágazás történik, ezúttal a WIDE-ot követõ byte-ot használva elküldésre. Mindazonáltal, mivel a WIDE ILOAD különbözõ mikrokódot követel, mint az ILOAD és a WIDE ISTORE különböző mikrokódot követel, mint az ISTORE stb. ez a második többirányú ág nem használhatja az opcode-t, mint célterület címet, mint ahogy azt a Main 1 teszi. Ehelyett a wide 1 VAGY mûvelettel összekapcsolja 0x100- t az opcode-dal, mialatt az MPC-be teszi. Eredményképpen a WIDE ILOAD megvalósítása 0x115-ön kezdõdik (0x15 helyett), a WIDE ISTORE megvalósítása pedig a 0x136-on kezdõdik (0x36 helyett) stb. Ez alapján minden WIDE utasításkód 256-tal (azaz 0x100-zal) magasabb címen kezdõdik a vezérlõ tárban, magasabban mint a megfelelõ reguláris opcode. A mikroutasítások kezdeti sorozata, mind az ILOAD-ra, mind a WIDE ILOAD-ra a 4-20-as ábrán láthatók. Amint a kód elér a WIDE ILOAD megvalósításához (0x115) a kód a normális ILOAD-tól mindössze annyiban különbözik, hogy az indexet két egymás utáni index byte összefûzésével kell megkonstruálni, ahelyett, hogy csak egy byte-on végeznénk „elõjel-kiterjesztést”. Az összefûzést és a rákövetkezõ összeadás mûveleteket részletekben kell végrehajtani, elõször az INDEX BYTE 1-et H-ba másolva és 8 bittel balra tolva. Mivel az index elõjel nélküli egészet reprezentál, az MBR-en nullafeltöltést hajtunk végre, MBRU-t használva. Ezután az index második byte-ját hozzáadjuk (az összeadás itt megfelel a konkatenáció (összefûzés) mûveletének, mivel a H alsó byte-ja nulla, így garantálva van, hogy nincs átvitel (carry) a byte-ok között) és az eredmény H-ban marad. Innentõl kezdve a mûvelet pontosan ugyanúgy folytatódhat, mint ha egy standard ILOAD-ról lenne szó. Ahelyett, hogy duplán végrehajtanánk az ILOAD záró utasításait (iload 3-tól iload 5-ig) egyszerûen leágazunk wide-iload 4-tõl az iload 3-hoz. Figyeljük meg azonban, hogy PC-t kétszer kell megnövelnünk az utasítás végrehajtása során, hogy az a következõ utasítás kódjára mutathasson. Az ILOAD megnöveli azt egyszer; a WIDE-ILOAD is megnöveli egyszer. Ugyanez a szituáció a WIDE-ISTORE-ral, miután az elsõ 4 mikroutasítás végrehajtódik (wide_istore 1-tõl 4-ig) a folytatás ugyanaz a sorozat, mint az ISTORE elsõ két utasítása után, így a wide-istore 4 leágazik az istore 3-hoz.
49.
20. Parallel Input/Output (PIO), valódi és memória leképezett I/O eszközök. Teljes és részleges címdekódolás. Programozott és megszakítás vezérelt I/O. DMA. Egy kis és közepes számítógéprendszer központi egysége lapkákból, memórialapkákból, és néhány B/K vezérlőből áll, amelyeket mind egy sín köt össze. A számítógép ezeken a lapkákon keresztül tartja fenn a kapcsolatot a külvilággal. Számos B/K lapka kapható és egyre újabbakat hoznak forgalomba. A leggyakoribbak az UART, az USART, a képernyőmeghajtó, a diszkvezérlő és a PIO lapkák. Az UART egy olyan lapka, amely egy bájtot tud olvasni az adatsínről, és bitenként továbbítja azt egy soros vonalon egy terminál felé, és soros adatokat tud fogadni a terminálról. Az USART lapkák egyrészt különböző protokollok felhasználásával szinkron átvitelt, másrészt azon felül az UART lapkák minden funkcióját meg tudják valósítani. Egy tipikus PIO (Parallel Input and Output, párhuzamos B/K) lapka az Intel 8255A, amellyel bármilyen TTL kompatibilis eszköz tud kapcsolódni (billentyűzethez, kapcsolókhoz, fényforrásokhoz vagy nyomtatókhoz). A legegyszerűbb módja a 8255A felhasználásának, hogy három teljesen független 8 bites porta osztjuk (A-ra, B-re és C-re). Mindegyik port egy 8 bites tárolóregiszterrel van kapcsolatban. Ahhoz, hogy a port kimenő vonalait beállíthassuk, a központi egység beírja a megfelelő 8 bites számot a megfelelő regiszterbe, és a 8 bites szám megjelenik a kimenő vonalakon és ott meg is marad mindaddig, amíg a regiszterbe ismételten nem írnak. Amikor a portot bemenetként használjuk, akkor a központi egység csupán a megfelelő tárolót olvassa ki. Más működési módjai közvetlen kapcsolatot is tudnak biztosítani a külső eszközökkel. Pl. Ha olyan eszköz számára küld adatokat, amely nem mindig tudja azokat fogadni, a 8255A megjeleníti az adatokat az egyik port kimenetén, majd vár egy impulzusra az eszköztől, amely így üzen vissza, hogy fogadta az adatot és szeretne még további adatokat fogadni. Az a logikai áramkör, ami ahhoz szükséges, hogy ilyen impulzusokat tárolni tudjon, és a központi egység számára hozzáférhetővé is tudja tenni, be van építve a 8255A-ba. A PIO lapka használata a következő két módszer valamelyikével történhet:
valódi B/K eszköz memória egy területe
Ha valódi B/K eszközként szeretnénk használni, akkor egy külön sínvezetékre van szükség, amellyel jelezni tudjuk, hogy egy B/K eszközt szeretnénk használni, nem pedig a memóriát. Ha a memória leképzett B/K módszert szeretnénk használni, akkor a memória 4 bájtját ki kell jelölnünk, három bájtot a három port számára és egy bájtot a vezérlőregiszter számára. Az EPROM 2 KB címterületet igényel, a RAM szintén 2 KB területet és a PIO 4 bájtot. Az EPROM a 2 KB-ig terjedő címterületet foglalja el, a RAM a 32 KB-tól 34 KB-ig terjedő területet, valamint a PIO a memória legfelső 4 bájtját 65532-től 65535-ig. Ha a másik módszert választottuk volna a PIO megcímzésére, a külön B/K címterületet, akkor az semmilyen memória címtartományt nem igényelt volna (viszont 4 bájt területet igényelt volna a B/K címtartományból).
50.
Minden olyan cím, amelynek a felső 5 bitje 0, a memória alsó 2 KB területére esik, tehát az EPROM területére. Az EPROM lapka kiválasztó vezetékét egy 5 bites összehasonlító áramkör bemenetére kell kötni, az egyik bementét pedig a 00000-ra. Ugyanezt az elvet használják a RAM esetében is, azonban a RAM az olyan bináris címekre kell, hogy válaszoljon, amelyek 1000 0xxx xxxx xxxx alakúak binárisan, ezért még egy inverterre is szükség van. Címdekódolás: A PIO címdekódolás kissé bonyolultabb. A PIO-t akkor kell használni, ha a cím 1111 1111 1111 11xx alakú. Ha azonban a számítógép csak a központi egységet, két memórialapkát, és a PIO-t használja, akkor nagy mértékben egyszerűsíthető a címdekódolás feladata, mivel csak és kizárólag az EPROM címeinek esetében fordul elő az, hogy a legfelső címvezeték az 0. A RAM kiválasztása történhet az alapján, hogy csak az 10xx xxxx xxxx xxxx alakú érvényes címek lehetnek a RAM-ban, ezért a kiválasztás céljára elegendő a felső 2 bit. Minden cím, ami 11-gyel kezdődik az a PIO címe lesz. A részleges címdekódolás esetében nem teljes címeket használunk fel a dekódolásra. Megvan az a tulajdonsága, hogy ha olvasunk a 0001 0000 0000 0000, 0001 1000 0000 0000 vagy a 0010 0000 0000 0000 címekről, ugyanazt az eredményt kapjuk. Minden olyan címzés esetében, amely a memória alsó felére mutat, az EPROM lesz kiválasztva. A részleges címdekódolást el kell kerülni, mert túlságosan nagy címterületet köt le. Teljes címdekódolás megvalósítására 8 darab 8 KB x 8 bájtos RAM-ot használunk fel. Egy olyan számítógép számára, amelyben 8 darab 2 KB x 8 bájtos memória van, egyetlen ilyen dekóder szintén elegendő, feltéve, hogy a lapkák mind a memóriatartomány különböző 8 KB méretű címterületén vannak. DMA: Ha nagyobb adatmennyiségeket kívánunk a memória egyes részei között mozgatni, vagy egy perifériális eszközrõl a memóriába beolvasni, akkor a DMA vezérlőt használja fel a számítógép ennek gyors lebonyolítására. Erre a feladatra egy "cél-processzort" kell használni, amelyik az írási és olvasási címeket automatikusan és igen gyorsan egyesével növeli, és a beolvasott adatot késlekedés nélkül írja a cél-helyre. Természetesen ezen folyamat alatt az "igazi" processzornak hallgatnia kell, nehogy a cím- vagy adatbuszon helyrehozhatatlan keveredés álljon elõ. Ezen túlmenõen van még egy igen fontos feladata: a DMA vezérlõ végzi a dinamikus RAM memória felfrissítését. Az idõzítõ 1. csatornája kb. 15 microsec.-ként jelzést küld a DMA vezérlõnek. A DMA vezérlő ezt továbbítja a DMA RQ (DMA REQEST) vezetéken a processzornak. A processzor ekkor befejezi az elkezdett processzorciklust, majd visszaüzen a DMA vezérlõnek, hogy az átveheti a buszok vezérlését. A DMA 5 processzorciklus idejéig kezeli a vonalakat. A DMA egység által végrehajtott látszólagos adatblokk-mozgások a memória egyegy részének felfrissítésével járnak. 512 ilyen felfrissítõ ciklus az egész memóriát "felújítja", a teljes memória tehát mintegy milisecundumonként felfrissítésre kerül. Ez bõven elegendõ a megbízható, hibamentes mûködéshez.
51.
21. Utasítás szintű párhuzamosítás, csővezeték (pipelining). Utasításszintű párhuzamosság A számítógép fejlesztők mindig arra törekszenek, hogy növeljék az általuk tervezett gépek teljesítményét. Az egyik módszer a chipek gyorsítására, hogy megnövelik a belső óra sebességét. Ám minden új technikának megvan a maga határa, amit a kor pillanatnyi szintje határoz meg. Összefoglalva a legtöbb computer-fejlesztő a párhuzamosság felé törekszik (két vagy több dolog egyidejű elvégzése). Ez az a módszer, amely még inkább növeli a teljesítményt egy adott órasebesség mellett. A párhuzamosságnak két fontos fajtájáról beszélhetünk: az utasítás-szintű, és a processzorok szintjén levő párhuzamosságról. Az előbbiben a gép azt hasznosítja, hogy a párhuzamosság miatt másodpercenként több utasítás adható ki. Az utóbbiban pedig összekapcsolt CPU-k dolgoznak együtt ugyanazon a problémán. Mindkét megközelítésnek megvan a maga érdeme. Ebben a részben az utasítás-szintű paralellizmussal foglalkozunk. Csővezeték Évek óta ismert, hogy a memóriából aktuálisan előkerülő utasítások nagy torlódást idéznek elő, s ezzel lassítják a végrehajtási sebességet. Hogy kezelni tudják ezt a problémát, a computereknek vissza kell térnie legalább az IBM-Kibővitésig (1959), amikor még meg volt az a tulajdonság, hogy az utasítások előre fel voltak hozva a memóriából, így kéznél voltak amikor csak szükség volt rájuk. Ezek a parancsok egy regiszterblokkba - az előtárba - voltak behelyezve. Így, amikor szükség volt egy utasításra, rendszerint elő lehetett venni az előtárból - inkább, mint arra várni, hogy feljöjjön a memóriából. Ennek eredményeképp az utasítások "származása" alapján történő csoportosítás a végrehajtást két részre bontja: előhozási és aktuális végrehajtás. A csővezeték koncepciója még tovább viszi ezt a stratégiát. A parancsok végrehajtásának két részre osztása helyett gyakran sok részre osztották, s mindegyiket a hardver meghatározott része irányította. Mindet ami képes párhuzamosan futni. Ötszakaszos pipeline: utasítást lekérdező egység -> utasítást végrehajtó egység ->
utasítást dekódoló egység -> operandus lekérdező egység -> visszaíró egység
Gondoljunk ki egy analógiát, hogy a pipelineok fogalmát tisztábbá tegyük. Képzeljünk el egy tortagyárat, ahol a sütés és a szállítás el van különítve. Tegyük fel, hogy a szállító részlegnek van egy hosszú futószalagja, mellette sorban 5 munkással (feldolgozó egységek). Minden 10 másodpercben (a ciklus) az 1. munkás egy üres dobozt rak a szalagra. Ezután a doboz a 2. munkáshoz kerül, aki belerak egy tortát. Egy kicsivel később a doboz megérkezik a 3. munkáshoz, aki lezárja. Utána folytatja útját a 4. munkáshoz, aki rak egy címkét a dobozra. Végül az 5. munkás leveszi a dobozt a szalagról és egy nagyobb tárolóegységbe rakja az áruházba történő későbbi szállításához. Alapvetően így működik a számítógépnél a pipeline: mindegyik utasítás (torta) végigmegy néhány feldolgozó lépésen, mielőtt végrehajtva kijut a végén.
52.
Visszatérve a pipelinera a 2-4. ábrához feltételezzük, hogy a ciklusidő 2 nsec volt. Így 10 nsecbe kerül egy utasításnak, hogy végighaladjon az ötszakaszos pipelineon. Első pillantásra ha egy utasításnak 10 nsec-ig tart, akkor úgy tűnik, hogy a gép 100 MIPS-el fut, de valójában ennél sokkal jobb. Minden ciklusban (2 nsec) egy új utasítást hajt végre, így a feldolgozás mértéke 500 MIPS, nem pedig 100 MIPS. A pipeline megengedi, hogy a "lappangást" (mennyi ideig tart az utasítást végrehajtani) és a processzor sávszélességét (a CPU MIPS teljesítménye) felváltva használja. Egy T nsec-es ciklusidővel és n szakaszos pipeline-nal a lappangási idő nT nsec és a sávszélesség 1000/T MIPS. (logikus, mivel az időt nsec-ban mérjük, így a CPU sávszélességét BIPS-ben vagy GIPS-ben kellene mérni, de mivel ezt senki sem teszi, így mi sem fogjuk) Szállítószalag elv Ez az elv azt a problémát enyhíti, miszerint olyan gyorsan hajthatunk végre egy-egy utasítást, amilyen gyorsan azt fel tudjuk dolgozni / végrehajtani (utasítás beolvasás, dekódolás, operandus beolvasás, utasítás végrehajtás, visszaírás). Már régóta használatos az előolvasási puffer (prefetch buffer), ami képes előre beolvasni utasításokat, hogy rendelkezésre álljanak, amikorra végre kell őket hajtani, ahelyett hogy mindig várni kelljen egy-egy memóriából való beolvasásra. Ez a módszer az utasítás végrehajtását két részre osztja: beolvasás és a végrehajtás. A szállítószalag elv ezt az elvet viszi tovább, miszerint a végrehajtás fázist még több elemre osztja szét, s minden külön részt egy-egy másik hardver elem végez egymással párhuzamosan.
(5 fázisú szállítószalag) Működés: A számítógép számára rengeteg feladatot elküldtünk, hogy végezze el, ilyenkor az első lépése, hogy az S1 hardver elem az első utasítást beolvassa (órajel: 1) mikor kész, a következő órajelnél (2) egy másik hardverelem, S2 már az elöbb beolvasott adatot dekódolja, ugyanebben az időben (órajel: 2) S1 beolvassa a következő utasítást párhuzamosan. Órajel: 3–nál S1 már a következő utasítást olvassa be, S2 az előzőleg beolvasott utasítást dekódolja, S3 pedig az előzőleg dekódolt utasításhoz beolvassa az operandusokat ugyanabban az órajelben (3). És így tovább halad, lényege, hogy egyszerre 5 fázist tud végezni…
53.
22. Utasítás betöltő egység. Mic – 2. Utasítás betöltő egység Ha egy utasításnak további mezői vannak (operandusok számára), minden mezőt határozottan be kell tölteni, egyszerre csak egy bájtot, és mielőtt felhasználnánk, össze kell rakni őket. Egy mező betöltése és összerakása bájtonként legalább egy ciklusra leköti az ALU–t, hogy megnövelje a PC-t, és azután ismét, hogy összerakja a keletkező indexet vagy eltolást. Az ALU-t szinte minden ciklusban sokféle műveletre használjuk az utasításbetöltéssel és az utasításon belüli mezők összerakásával kapcsolatban, az utasítás „valódi” munkáján felül. Annak érdekében, hogy a főciklust átlapoljuk, szükséges, hogy az ALU-t felszabadítsuk a fenti feladatok némelyikéből. A Mic-1–ben sok betöltés eltávolítható az ALU-tól egy független egység megalkotásával, amely betölti és feldolgozza az utasításokat. Ez az egység, amit IFU-nak (Instruction Fetch Unit, utasításbetöltő egység) nevezünk, amely képes függetlenül növelni a PC-t és betölteni a bájtokat a bájtfolyamból, még mielőtt szükség lenne rájuk. Az IFU felelős egy bájtfolyam betöltéséért. Ezt azzal éri el, hogy a hagyományos 4 bájtos memóriaportot használja idő előtt betöltve teljes 4 bájtos szavakat, és az egymást követő bájtokat egy léptetőregiszterbe tölti, ami egyesével vagy kettesével szolgáltatja azokat a betöltés sorrendjében. A léptetőregiszternek az a szerepe, hogy fenntart egy bájtsort a memóriából, és tölti MBR1-be és MBR2-be. Valahányszor az MBR1 kiolvasódik, a léptetőregiszter jobbra léptet egy bájtot. Valahányszor az MBR2 kiolvasódik, jobbra léptet 2 bájtot. Ezután az MBR1 és MBR2 újratöltődik a legrégebbi bájtból, illetve bájtpárból. Ha most elegendő hely marad a léptetőregiszterben egy másik teljes szó számára, akkor az IFU elkezd egy memória ciklust a beolvasásra. Hogy helyesen dolgozzunk, az IFU-nak le kell blokkolnia, amikor arra kérik, hogy tegyen meg valamit, amit nem tud, úgy mint szolgáltassa MBR2 értékét, amikor csak 1 bájt van a léptetőregiszterben és a memória még el van foglalva egy új szó betöltésével. Ezenkívül egyszerre csak egy dolgot tud csinálni, így a beérkező eseményeket sorba kell állítania. Végül valahányszor a PC megváltozik, az IFU-t frissíteni kell. Az IFU-nak saját memóriacím-regisztere van, az IMAR, melyet a memória címzésére használunk, amikor egy új szót kell betölteni. Ennek a regiszternek saját tulajdonú növelője van, így a fő ALU-ra nincsen szükség, amikor a következő szó eléréséhez növeljük azt. Az IFU-val a fő végrehajtási egység csak akkor ír a PC-be, amikor meg kell változtatni az utasításbájt folyamának soros jellegét. Mivel a mikroprogram már nem közvetlenül növeli a PC-t a műveleti kódok betöltésénél, az IFU-nak kell a PC-t időszerűen tartani. Ezt azzal éri el, hogy érzékeli, amikor az utasításfolyamból 1 bájt felhasználásra kerül, vagyis, amikor MBR1-et vagy MBR2-t (vagy az előjeltelen verziókat) kiolvassák. A PC-hez kapcsolódik egy önálló növelő, amelyik attól függően képes 1 vagy 2 bájttal növelni, hogy hány bájtot használtunk fel. Így a PC mindig a még fel nem használt első bájt címét tartalmazza. Minden egyes utasítás kezdetén az MBR tartalmazza az ehhez az utasításhoz tartózó műveleti kód címét.
54.
Mic-2 Az IFU nagyon lecsökkentheti az átlagos utasítás úthosszát: Először is, teljesen eltávolítja a főciklust, mivel minden egyes utasítás vége egyszerűen közvetlenül ágazik el a következő utasításra. Másodszor, elkerüli, hogy az ALU-t a PC növelésére kössük le. Harmadszor, csökkenti az úthosszt valahányszor egy 16 bites indexet vagy eltolást számítunk ki, mert összerakja a 16 bites értéket és ezt, mint egy 32 bites értéket, közvetlenül szolgáltatja az ALU-nak, elkerülve, hogy H-ban kelljen összerakni. Az IADD művelet betölti a veremben lévő második szót és elvégzi az összeadást. Amikor az IFU észleli, hogy az IADD-ban hivatkozunk MBR1-re, a belső léptetőregisztere mindent jobbra tol és újratölti MBR1-et és MBR2-t. Végrehajt egy átmenetet is a jelenlegi állapotából az eggyel alacsonyabba. Ha az új állapot 2, az IFU elkezd betölteni egy szót a memóriából. Mindez a hardverben történik, a mikroprogramnak semmit sem kell tennie, ezért csökkenthető az IADD öt mikroutasításról három mikroutasításra. A Mic-2 néhány utasítást jobban feljavít, mint másokat, és ebből következik, hogy nagyobb nyeresége van. Az LDC_W kilenc mikroutasításról csupán háromra változik, harmadolva a végrehajtási időt. Másrészről, a SWAP csak nyolcról hat mikroutasításra változik. Átlagos teljesítménynél valójában a gyakoribb utasításoknál kapott nyereség számít. Ezek közé tartozik az ILOAD (6 volt, most 3), az IADD (4 volt, most 3) és az IF_ICMPEQ (sikeres esetben 13 volt, most 10; sikertelen esetben 10 volt, most 8). Ahhoz, hogy megmérjük a gyorsítást, választanunk és futtatnunk kellene egy tesztágyat, de világos, hogy itt nagy a nyereség.
55.
23. Csővonalas terv: a Mic-3 A Mic-3 a Mic-2 továbbfejlesztése. Még gyorsabbá úgy tudnánk tenni, ha megpróbálnánk csökkenteni a ciklusidőt. Jelentékeny méretékben a ciklusidőt a lapkatechnológia határozza meg. Minél kisebbek a tranzisztorok és minél kisebb a köztük lévő fizikai távolság, annál gyorsabban tud az óra futni. Egy adott technológia számára az idő, amely egy teljes adatút művelet végrehajtásához szükséges, állandó. A másik választás a gyorsabbá tételre, ha párhuzamosságot viszünk a gépbe. Mint az előbb említettük, az óraciklust behatárolja az idő, amelyik szükséges a jel tovaterjedéséhez az adatúton. Három fő alkotóelem van a folyamatban levő adatút ciklushoz: Az idő a kiválasztott regiszterek rávezetéséhez az A és D sínekre. Az idő, amíg az ALU és a léptetőregiszter elvégzi a munkáját. Az idő, amíg az eredményeket visszaküldjük a regiszterekbe és eltároljuk. A Mic-3 csővonalas modell, háromsínes architektúrából áll, hozzávéve az IFU-t, és három további tárolót (regisztert), melyeket minden egyes sín közepére illesztünk. A tárolókat minden egyes ciklusban írjuk. Végeredményben a regiszterek szétválasztják az adatutat különböző részekre, amelyek most egymástól függetlenül működhetnek. Most három óraciklus kell az adatút használatához. A tárolók beillesztésének értelme kétszeres: Gyorsítjuk az órát, mert a maximális késleltetés most rövidebb. Minden egyes ciklus alatt az adatút minden részét használhatjuk. Az adatút három részre osztásával a maximális késleltetés csökken annak eredményeképpen, hogy az órafrekvencia növekedhet. Tegyük fel, hogy az adatút három időintervallumra osztásával mindegyik körülbelül harmad olyan hosszú, mint az eredeti, így az óra sebességét megháromszorozhatjuk. Az adatút most három ciklust igényel a működéséhez: egyet az A és B betöltéséhez, egyet a művelet elvégzéséhez és a C feltöltéséhez, és egyet az eredmény visszaírására a regiszterekbe. Minden egyes ilyen darabot mikrolépésnek hívunk. Ahol egy mikrolépés nem tud indulni, mert egy eredményre vár, amit az előző mikrolépés még nem hozott létre, valódi függőségnek vagy RAW függőségnek nevezzük. A függőségekre gyakran úgy hivatkozunk, hogy akadályok. A RAW egy rövidítés a Read After Write számára, és azt jelenti, hogy egy mikrolépés olvasni akar egy regisztert, melybe még nem írtunk. Elakadásnak nevezzük, amikor megállunk, hogy egy szükséges értéket megvárjunk. Habár a Mic-3 több ciklust igényel, mint a Mic-2 program, mégis gyorsabban fut. Ha a Mic-3 ciklusidejét t ns-nak vesszük, akkor a Mic-3 11t ns-ot igényel a SWAP végrehajtásához. Ellenben, a Mic-2 6 ciklust igényel, melyek mindegyike 3t, összesen 18t. A csővezeték gyorsabbá teszi a gépet, még akkor is, ha egyszer le kellett állni, hogy elkerüljünk egy függőséget. A csővezeték egy kulcsmódszer minden korszerű CPU-ban. Még egy fontos részlet, hogy bár egy egydülálló utasítás négy óraciklust igényel a végrehajtáshoz, minden egyes óraciklusban egy új utasítás kezdődik és egy régi utasítás fejeződik be.
56.
24. Egy hétszakaszú szállítószalag: a Mic-4 csővezetéke. Miden egyes mikroutasítás kiválasztja a rákövetkezőjét. A legtöbbjük éppen a következőt választja ki a folyamatban lévő sorozatban, de az utolsó, mint amilyen swap6, gyakran egy többutas elágazást csinál, ami eldugaszolja a csővezetéket, mert utána lehetetlen folytatni az előre betöltést. A kérdés kezelésének egy jobb módszerére van szükségünk. A következő (és egyben utolsó) mikroarchitektúránk a Mic-4. A fő alkotóelemeit a 4.35. ábrán mutatjuk be, de egy tekintélyes mennyiségű részlet el van nyomva az érthetőség kedvéért. Mic-3-hoz hasonlóan van egy IFU, amelyik előre betölt szavakat a memóriából, és kezeli a különböző MBR-eket. Az IFU a bejövő bájtfolyamot egy új alkatrésznek, a dekódoló egységnek adagolja. Ennek az egységnek van egy belső ROM-ja, amit az IJVM műveleti kódjával indexelünk. Minden egyes bejegyzés (sor) két részből áll: ennek az IJVM-utasításának a hossza és egy index egy másik ROM-ba, a mikroműveletek ROM-jába. Az IJVM-utasítás hosszát arra használjuk, hogy hozzájáruljunk: a dekódoló egység felismerje a bejövő bájtfolyamatban az utasításokat, így az mindig tudni fogja, hogy melyek a műveleti kód bájtok és melyek az operandusok. Ha éppen egy utasítás hossza 1 bájt (pl. POP), akkor a dekódoló egység tudja, hogy a következő bájt egy műveleti kód. Ha azonban a jelenlegi utasításhossz 2 bájt, akkor a dekódoló egység tudja, hogy a következő bájt egy operandus, melyet közvetlenül egy másik műveleti kód követ. Amikor a WIDE előtag feltűnik, a következő bájtot egy különleges széles műveleti kódra alakítjuk át, pl. WIDE + ILOAD átalakul WIDE_ILOAD-dá. A dekódoló egység elküldi a mikromüveletek ROM-jához azt az indexet, amit a saját táblázatában talált, a következö alkatrész, a sorba állító egység számára. Ez az egység néhány logikát és két belső táblázatot tartalmaz, egyet ROM-ban és egyet RAM-ban. A ROM azt a mikroprogramot tartalmazza, ahol minden egyes IJVM-utasításnak néhány egymást követő bejegyzése van, amit mikroműveletnek nevezünk. A bejegyzéseknek sorrendben kell elhelyezkedniük, így olyan trükk, mint WIDE_ILOAD2 ugrása ILOAD2-re a Mic-2-ben, nem megengedett. Minden egyes IJVM-sorozatot pontosan és teljes terjedelmében meg kell határozni, megismételve a sorozatokat bizonyos esetekben. A mikroműveletek hasonlítanak a 4.5. ábra mikroutasításaihoz, kivéve, hogy a NEXT_ADRESS és JAM mezők hiányoznak, és egy új kódoló mező szükséges az A sín bemenet elöírásához. Két új bit is kell: a Final és a Goto. A Final bit be van állítva minden egyes IJVM-mikroművelet sorozat utolsó mikroműveleténél, megjelölve azt. A Goto bit ezért van beállítva, hogy megjelölje azokat a mikroműveleteket, amelyek feltételes mikorelágazások. Ezeknek a közönséges mikroművelettől különbözö formája van, amely tartalmazza a JAM biteket és egy indexet a mikroművelet ROM-jába. Azokat a mikroutasításokat, amelyek előzőleg valamit csináltak az adatúttal és végrehajtottak egy feltételest mikroelágazást is (pl. iflt4), most két mikroműveletre kell szétdarabolnunk.
57.
A sorba állító egység a következöképpen müködik. Átvesz egy indexet a mikromüvelet ROMjához a dekódoló egységtöl. Ezután kikeresi a mikromüveletet és bemásolja azt egy belsö sorba. Majd a következö mikromüveletet is bemásolja a sorba, és ezután a következöt is. Ezt addig folytatja, amig talál egy olyat, ahol a Final bit egy. Ezt is átmásolja, és megáll. Feltéve, hogy nem talált olyan mikromüveletet, amelyben a Goto bit egy, és maradt még elegendö hely a sorban, a sorba állító egység ezután egy nyugtázó jelet küld vissza a dekódoló egységnek. Amikor a dekódoló egység felfogja a nyugtázást, a következö IJVM-utasítás indexét elküldi a sorba állító egységnek. Ilyen módon a memóriában lévö IJVM-utasítások sorozata alapvetöen átalakul mikromüveletek egy sorozatára egy sorban. Ezek a mikromüveletek táplálják a MIR-eket, amelyek jeleket küldenek az adatút vezérléséhez. Azonban, van egy másik tényező amit most figyelembe kell vennünk: a mezök az egyes mikromüveletben nem ugynabban az idöben hatnak. Az A és B mezök az elsö ciklus alatt hatékonyak, az ALU mezö a második ciklus alatt hatékony, a C mezö a harmadik ciklus alatt hat, és bármelyik memoria müvelet a negyedik ciklusban kerül sorra. Hogy teljessé tegyük ezt a munkát, négy független MIR-t vezetünk be a 4.35. ábrára. Minden egyes ora ciklus kezdetekor (a 4.3. ábrán a Δw idö), MIR3 átmásolodik a MIR4-be, MIR2 átmásolodik MIR3-ba, MIR1 átmásolodik MIR2-be, és MIR1-böl az A és B mezöket arra használjuk, hogy kihasználjuk azokat a regisztereket, amelyeket az A és B tárolokhoz vezetünk, de az ALU mezöt a MIR1-ben nem használjuk és nincs semmi máshoz hozzákapcsolva az adatútban. Egy oraciklussal késöbb, ez a mikromövelet átmegy MIR2-be, és azok a regiszterek, amelyeket kiválasztott, most biztonságosan az A és B tárolokban helyezkednek el; várva a kalandok eljövetelét. Az ALU mezöjét most arra használjuk, hogy az ALU-elvezessük. A következö ciklusban a C mezöje fogja az eredményeket visszaírni a regiszterbe. Azután átmegy MIR4-be, és elinditja valamelyik szükséges memoria müveletet, felhasználva a most betöltött MAR-t (és MDR-t egy iráshoz). A Mic-4 egy utolso szempontja most némi megbeszélést igényel: mikroelágazások. Néhány IJMV-utasítás, mint amilyen az IFLT, megkívánja, hogy a feltételes elágazás, mondjuk az N biten alapuljon. Amikor egy mikroelágazás megtörténik, a csövezeték nem folytatódhat. Hogy ezt kezelni tudjuk, hozzávettük a Goto bitet a mikromüvelethez. Amikor a sorba állító egység talál egy olyan mikromüveletet, amelyiknek ez a bitje be van állítva, miközben átmásolja azt a sorba, ráébred, hogy nehézségek következnek, és tartozkodik a nyugtázás elküldésétöl a dekódoló egységnek. Eredményként a gép elakad ezen a ponton, amíg a mikroelágazás meg nem oldódik. Elképzelhetően, néhány IJVM-utasítás az elágazáson túl már a dekódoló egységbe be lett táplálva (de a sorba állító egységbe nem), mivel nem küldött vissza nyugtázo (vagyis folytató) jelet, amikor megtalált egy Goto bittel beállított mikromüveletet. Különleges hardver és mechanizmusok szükségesek, hogy az össze-visszaságot tisztázzák és visszatáncoljanak, de ezek már túlmutatnak ennek a könyvnek a témakörén. Amikor Edsger Dijkstra megírta híres levelét „ GOTO Statement Considered Harmful” („ A GOTO utasítást károsnak tartják”) (Dijkstra, 1968 ), sejtelme se volt, hogy mennyire igaza volt. Hosszú utat jártunk be a Mic-1 óta. A Mic-1 egy nagyon egyszerü hardverdarab volt, szinte teljes szoftvervezérléssel. A Mic-4 egy erösen csövezetékezett terv hét szakasszal és sokkal bonyolúltabb hardverrel. A csövezetéket vázlatosan a 4.36. ábrán mutatjuk be, azzal, hogy a
58.
bekarikázott a 4.35. ábra alkotóelemeire hivatkoznak. A Mic-4 önmüködöen elöre betölt egy bájtfolyamota memoriábol, dekódolja azokat IJVM-utasításokká, átalakitja azokat mikromüveletek egy sorozatává egy ROM-ot használva, és sorba állítja azokat felhsználásra, amint szükséges. A csövezeték elsö három szakasza az adatút orájához köthetö, ha szükséges, de nem mindig van elvégezendö munka. Például, az IFU biztosan nem képes táplálni egy új IJVM müveleti kódot a dekódoló egységben minden oraciklusnál, mert az IJVM-utasítások különbözö ciklusokat igényelnek a végrehajtáshoz, és a sor gyorsan túlcsordúlna. Minden egyes ora ciklusban, a MIR-ek elöre lépnek, és a sor alján levö mikromüvelet bemásolodik MIR1-be, hogy elkezdje a végrehajtást. A négy MIR-böl jövö vezérlö jelek ekkor kiterjednek az adatút felé, tevékenységek bekövetkezését okozva. Minden egyes MIR az adatút különbözö részeit vezérli és ennek következtében különbözö mikrolépéseket. Ebben a tervben egy mélyen csövezetékezett CPU-nk van, amelyik megengedi, hogy az egyes lépések nagyon rövidek és ennélfogva az ora frekvencia magas legyen. Számos CPU alapvetöen ilyen módon van tervezve, különösen azok, melyeknek egy régebbi (CISC) uatsításhalmazt kellet megvalósítaniuk. Például, a Pentium II megvalósítás elviekben hasonló a Mic-4-hez bizonyos szempontból, ahogy azt késöbb látni fogjuk ebben a helyzetben.
59.
25. Elágazás, eltolási rés, statikus és dinamikus elágazás jövendölés Elágazás, eltolás rés A modern számítógépek magas szinten vannak csővezetékkel ellátva. A csúcsteljesítményű gépeknek néha 10 vagy még több szakaszos csővezetéke van. A csővezetékek legjobban lineáris kóddal dolgoznak, de a programok nem lineáris kódsorozatok. Teli vannak elágazási utasításokkal. Az utasítás-dekódoloás a második szakaszban történik /4.35. ábra/. Így a betöltő egységnek kell eldöntenie, hogy honnan töltse be a következőt, még mielőtt tudná, milyen utasítást kapott éppen. Csak egy ciklussal később tudhatja meg, hogy pont egy feltétel nélküli elágazási utasítást kapott, és akkorra már elkezdte a feltétel nélküli elágazást követő utasítást betölteni. Ennek következtében a csővezetéket alkalmazó gépek (pl. UltraSPARC III) tekintélyes részének megvan az a tulajdonsága, hogy egy feltétel nélküli elágazást követő utasítás végrehajtódik, annak ellenére, hogy logikusan nem kellene. Az elágazás utáni állapotot eltolás résnek nevezzük. A feltételes elágazások nem csak eltolás réseket hoznak létre, hanem a betöltő egység még azt sem tudja, hogy sokkal később honnan olvasson a csővezetékbe. A korai csővezetékes gépek csaknem bedugultak, amíg nem derült ki, hogy lesz elágazás vagy nem. Következésképpen a legtöbb gép, amikor talál egy feltételes elágazást, megjövendöli, hogy végre fogjuk hajtani vagy nem. Különféle módszereket gondoltak ki a jövendölésre. Egy nagyon egyszerű mód a következő. Tételezzük fel, hogy minden visszafelé történő feltételes elágazást végre fogunk hajtani, és az összes előreirányulót nem. Az első rész mellett az az érv, hogy a visszafelé elágazások gyakran egy ciklus végén helyezkednek el. A legtöbb ciklust többször hajtjuk végre, így az a feltevés, hogy egy visszafelé elágazás a ciklus tetejére végre lesz hajtva, általában jó fogadás. A második rész rázósabb. Néhány előreelágazás akkor fordul elő, amikor hibafeltételeket észlelünk a szoftverben. A hibák ritkák, így a legtöbb velük összefüggő elágazást nem hajtjuk végre. Természetesen sok olyan előreelágazás van, ami nem kapcsolódik hibakezeléshez, így a siker aránya közel sem olyan jó, mint a visszafelé elágazásnál. Ha egy elágazást pontosan megjósoltunk, akkor semmi különös tennivaló nincs. A végrehajtás éppen a célcímnél folytatódik. A nehézség akkor jön, amikor rosszul jósoltunk meg egy elágazást. Kigondolni, hogy hova kell menni nem nehéz. A nehéz rész, visszacsinálni azokat az utasításokat, amelyeket már végrehajtottunk, de nem kellett volna. Dinamikus elágazás jövendölés Világos, hogy nagyszámú pontos jövendölés teszi lehetővé a CPU-nak, hogy teljes sebességgel haladjon. Ennek következtében a jelenlegi kutatások nagy része az elágazást jövendölő algoritmusok javítását célozza. Egy közelítés az, hogy a CPU fenntart egy előzmények táblát, amelyben feljegyzi a feltételes elágazásokat, amint előfordulnak, így azok kikereshetők, ha ismét előfordulnak. Számos módszer van az előzmények tábla szervezésére. Valójában ezek pontosan ugyanazok a módszerek, mint amelyeket a gyorsítótár szervezésénél használunk. Tekintsünk egy gépet 32 bites utasításokkal, amelyek szóhatáron kezdődnek, vagyis minden memóriacím alsó 2 bitje 00. Egy direkt leképezésű 2 az n-ediken bejegyzést tartalmazó előzmények tábla esetén egy elágazási utasítás alsó n+2 bitjét kivehetjük, és 2 bittel jobbra léptethetjük. Az n bites számot indexként használhatjuk az előzmények
60.
táblához, ahol egy ellenörzést végzünk annak megállapítására, hogy az ott tárolt cím megegyezik-e az elágazás címével. Úgy mint a gyorsítótárnál nincs szükség az alsó n+2 bit tárolására, így mellözhetjük azokat. Ha találat van, a jövendölö bitet használjuk az elágazás jóslására. Ha rossz cimke van ott vagy a bejegyzés érvénytelen, akkor hiány lép fel, épp úgy, mint a gyorsítótárnál. Ebben az esetben az elöre/visszafelé elágazási szabályt alkalmazhatjuk. Ha elég nagy a táblaméret és elegendö az asszociativitás, akkor ez az elrendezés a legtöb esetben jól müködik. Viszont egy rendszeres probléma mindig elöfordul. Amikor a ciklus végül kilép, a végén az elágazás tévesen lesz megjövendölve, és a rossz jövendölés megváltoztaja az elözmények táblát úgy, hogy "nincs elágazás"-nak jelöli a következö jövendölést. Amikor legközelebb a ciklusba lépünk, az elsö ismétlés végén az elágazás rosszul lesz megjövendölve. Ha a ciklus egy külsö ciklus belsejében van, vagy egy gyakran meghívott eljárásban, akkor ez a hiba gyakran elöfordulhat. Hogy kiküszöböljük ezt a téves jövendölést, adhatunk a táblázat bejegyzésének egy második lehetöséget. Ezzel a modszerrel a jövendölés csak két egymás utáni helytelen jövendölés után változik meg. Ez a megközelítés két jövendölö bit meglétét követeli meg az előzmények táblában, egyet arra, hogy az elágazás "feltehetöleg" mit fog csinálni, és egyet arra, hogy mit csinált legutóbb. Mindeddig feltételeztük, hogy minden feltételes elágazás célpontja ismert, jellemzöen vagy egy határozott cím, ahova el kell ágazni, vagy mint egy relatív eltolás a jelenlegi utasításhoz képest. Gyakran ez a feltételezés indokolt, de néhány feltételes utasítás a célcímet regisztereken végzett aritmetikai müveletekkel számolja ki, és azután megy oda. Az olyan jövendölésnek nincs haszna, amelynél a célcím ismeretlen. Egy modszer ennek a helyzetnek a kezelésére, hogy tároljuk az elözmények táblában azt a tényleges címet, ahová legutóbb elágaztunk. Egy másik megközelítése az elágazás jövendölésnek, hogy nyomon követjük. hogy az utolsó k feltételes elágazás, ami elöfordul, vége lett-e hajtva, függetlenül attól, hogy az melyik utasítás volt. Ezt a k bites számot, amelyet az elágazási előzmények blokkos regiszterében tárolunk, összehasonlítjuk párhuzamosan az elözmények tábla minden bejegyzés egy k bites kulcsával, és ha egy találat előfordul, akkor az ott talált jövendölést használjuk. Statikus elágazás jövendölés Minden eddig tárgyalt elágazásjövendölési modszer dinamikus, azaz futásidöben hajtjuk végre, mialatt a program fut. Alkalmazkodik a program érvényes viselkedéséhez, ami jo dolog. A rossz oldal az, hogy szakosított és drága hardvert igényel, és nagyszámú lapka bonyolult összességét. Néhány gép, mint az UltraSPARC III, rendelkezik egy második feltételes elágazási utasítás halmazzal, a szokásoson felül. Az új tartalmaz egy bitet, amelyben e fordítoprogram meghatározhatja, hogy úgy gondolja, hogy az elágazás végre lesz hajtva, vagy nem. Ha ezek egyike elöfordul, a betöltö egység pontosan azt teszi, amit mondanak neki. Továbbá, nem szükséges értékes helyet pazarolni az elágazási elözmények táblában ezekre az utasításokra, így csökkennek itt az öszzeütközések. Végül az utolsó elágazásjövendölési modszerünk a metszetben ábrázoláson alapszik Ez szintén egy statikus módszer, de ahelyett, hogy a fordítoprogramnak kelljen megprobálni kiszámolni, hogy melyik elágazást hajtjuk végre, és melyiket nem, a program valójában fut, és az elágazás viselkedését megfigyeljük. Ezt az információt betápláljuk a fordítoprogramba, amely azután felhasználja az egyedi elágazás utasításokat arra, hogy a hardvernek megmondja, mit csináljon.
61.
26. Sorrendtől eltérő végrehajtás, szuperskaláris architektúra, függőségek, regiszter átnevezés, feltételezett végrehajtás Sorrendtől eltérő végrehajtás, függőségek, regiszter átnevezés Világos, hogy a számítógép-tervezés legegyszerűbb akkor, ha minden utasítást abban a sorrendben hajtunk végre, ahogyan betöltöttük azokat (pillanatnyilag feltételezve, hogy az elágazásjövendölő algoritmus soha nem ad rossz tippet). Mégis, a sorrend szerinti végrehajtás nem mindig eredményez optimális teljesítményt az utasítások közötti függőség miatt. Ha egy utasításnak egy olyan értékre van szüksége, amit az előző utasítás számit ki, akkor a második nem tudja elkezdeni a végrehajtást, amíg az első nem állítja elő a szükséges értéket. Ebben az esetben (RAW függőség) a második utasításnak várnia kell. A függőségnek más fajtái is léteznek: A RAW függőség az, ami akkor fordul elő, amikor egy utasításnak szüksége lenne egy olyan eredményt használni forrásként, amit az előző utasítás még nem állított elő. A két másik függőség kevésbé súlyos. Alapvetően forrás-összeütközések. A WAR függőségben (Write After Read; olvasás után írás) egy utasítás megpróbál felülírni egy regisztert, amelynek olvasását az előző utasítás még lehet, hogy nem fejezte be. A WAW függőség (Write After Write; írás utáni írás) hasonló. Ezek gyakran elkerülhetők, ha a második utasítás az eredményt valahova máshova teszi (esetleg ideiglenesen). Ha a fenti három függőség egyike sem áll fenn, és a szükséges működési egység elérhető, az utasítás kiosztható. Tekintsünk egy alternatív elgondolást: a sorrendtől eltérő végrehajtást. Ebben az elgondolásban az utasításokat sorrendtől eltérően lehet kiosztani, és ugyanígy sorrendtől eltérően lehet befejezni. Pl. bár I4 elakadt, dekódolhatjuk és kioszthatjuk I5-öt, mivel ez nem ellenkezik egyik függőben lévő utasítással sem. Mindamellett, utasítások átugrása egy új problémát okoz. Tegyük fel, hogy I5 használt egy olyan operandust, amelyet az átugrott utasítás, I4 számol ki. Ilyenkor ki kell bővítenünk az eredményjelzőt úgy, hogy nyomonkövesse azokat a tárolásokat, amelyeket az átugrott utasítások végeznek. Ezt egy második, regiszterként egy bites bittérkép hozzáadásával tudjuk megtenni, hogy nyomon tudjuk követni az elakadt utasítások által végrehajtott tárolásokat. Az utasítás kiosztás szabályát most ki kell terjeszteni, hogy megakadályozzuk minden olyan utasítás kiosztását, amelynek operandusa ütemjelzés szerint egy olyan utasítással tárolódik ami előtte jött, de átugrottuk. A 4.44 ábrán egy új módszert vezettünk be, a regiszterátnevezést. Az előrelátó dekódoló egység az R1 használta az I6-ban és I7-ban egy titkos regiszterre, S1-re váltja, ami nem látható a programozó számára. Most az I6-ot kioszthatjuk I5-tel párhuzamosan. A modern CPU-k gyakran titkos regiszterek tucatjait használják regiszter átnevezéssel. Ez a módszer gyakran kiküszöböli a WAR és a WAW függőségeket.
62.
Feltételezett végrehajtás A számítógépes programok alapblokkolókra bonthatók szét, ahol minden alapblokk egy lineáris kódsorozatból áll, a tetején egy belépési ponttal az alján egy kilépéssel. A gond az, hogy a legtöbb alapblokk rövid és nincs elegendő párhuzamosság bennük, hogy azt hatékonyan kihasználhassuk. Tehát a következő lépés az hogy megengedjük: az átrendezés az alapblokkok határain átnyúljon, megkísérelve ezzel minden kiosztási hely feltöltését. Egy kód végrehajtását , mielőtt még tudnánk, hogy egyáltalán szükség lesz-e rá feltételezett végrehajtásnak nevezzük. Ennek a módszernek az alkalmazása támogatást vár a fordítóprogramtól és a hardvertől is, néhány kibővítéssel az architektúrában. A legtöbb esetben az utasítások átrendezése az alapblokk határokon keresztül meghaladja a hardver képességeit, így egyértelműen a fordítóprogramnak kell az utasítást mozgatni. A feltételezett végrehajtás néhány érdekes problémát vet fel: Pl.: alapvető, hogy egyik feltételezett végrehajtásnak sincsenek visszavonhatatlan eredményei, hiszen később kiderülhet, hogy nem kellet volna azokat végrehajtani. Bonyolultabb kódsorozatoknál gyakori módszer annak megelőzése, hogy a feltételezett végrehajtás felülírja a regisztereket, mielőtt még kiderül, kívánatose, hogy átnézzük az összes célregisztert, amit a feltételezett végrehajtás használ. Szuperskaláris architektúra Egy két szállítószalagos CPU-nál az egyetlen utasítás-elolvasó egység két darab utasítást olvas be egyszerre, majd ezeket az egyik, ill. a másik szállítószalagra teszi. A szállítószalagoknak saját ALU-ja van, így párhuzamosan tudnak működni, feltéve, hogy a két utasítás nem használja ugyanazt az erőforrást, és egyik sem használja fel a másik eredményét. A szállítószalagok számának emelése négyre még elképzelhető, de ekkor már túl sok hardverelemet kell megduplázni. Ehelyett a nagy teljesítményű más megoldást alkalmaznak. Az alapötlet az, hogy csak egy szállítószalagot használnak de több funkcionális egységgel. A szuperskaláris architektúra kifejezés ennek az elrendezésnek a jelölésére 1987-ben született. A szuperskaláris processzor elvében implicit módon benne van az a feltételezés, hogy az S3 lényegesen gyorsabban tudja előkészíteni az utasításokat, mint ahogy az S4 fázis végrehajtja őket. Ha az S3 fázis 10 ns-ként produkál egy utasítást, és az összes funkcionális egység végezni tud 10 ns alatt, akkor mindig csak legfeljebb egy fog dolgozni, így az egésznek nincs semmi haszna. Valójában a negyedik fázis funkcionális egységeinek egy órajelnél jóval több időt igényel feladata elvégzéséhez, a memóriához fordulók vagy a lebegőpontos műveleteket végzők legalábbis biztosan. Lehet több ALU az S4 fázisban.
63.
27. Feltételes végrehajtás, predikáció Az IA-64 másik fontos jellemzője az a módszer, amellyel a feltételes elágazásokat kezeli. Ha mód lenne arra, hogy a legtöbbjüktől megszabaduljunk, a CPU sokkal egyszerűbb és gyorsabb lenne. Első ránézésre lehetetlen megszabadulni tőlük, mert a programok tele vannak if utasításokkal. Azonban, az IA-64 olyan technikát használ, az ún. predikációt, amely használatával nagymértékben csökkenthető a számuk. A jelenlegi számítógépek minden utasítása feltétel nélküli abban az értelemben, hogy amikor a CPU eléri, akkor feltétel nélkül végrehajtja. Nincs helye belső kérdésnek: "Tenni vagy nem tenni?" Ezzel ellentétben a predikációs architektúrákban az utasítások feltételt tartalmaznak (predikátum), amely megmondja, hogy végre kell-e hajtani az utasítást, vagy sem. Ez a paradigma, amely elmozdulást jelent a feltétel nélküli utasításoktól a predikációs utasítások felé, lehetővé teszi, hogy (sok) feltételes elágazástói megszabaduljunk. Ahelyett hogy két, feltétel nélküli utasítássorozat között kellene választani, valamennyi utasítást egyetlen predikációs utasítássorozatba fésülnek össze, különböző predikátumot alkalmazva különböző utasításokban. A predikáció működésének bemutatását kezdjük egy egyszerű példával Ez a feltételes végrehajtás (feltételes utasítás), a predikáció elődje. Az (a) ábra az if utasítást mutatja, a (b) ábrán pedig ennek három utasítássá való lefordítása látható: összehasonlítás, feltételes elágazás és mozgató utasítás. A (c) ábrán megszabadultunk a feltételes elágazástói, bevezetve egy új utasítást, a feltételes mozgatást. Ez megvizsgálja az Rl regiszter tartaimát, ha 0, akkor R3-at átmásolja R2-be, ha nem 0, akkor nem tesz semmit.
(a) if(R1==0) R2=R3; (b)
CMP R1, 0 BNE L1 MOV R2, R3
L1: (c) CMOVZ R2, R3, R1
64.
28. A Pentium 4, az UltraSPARC III és az I-8051 mikroarchitektúrája. A Pentium 4 CPU mikroarchitektúrája Kívülrő1 a Pentium 4 hagyományos CISC gépnek tűnik, nagy és nehezen kezelhető utasításrendszerrel, amely támogatja a 8, 16 és 32 bites egész műveleteket, valamint a 32 és 64 bites lebegőpontos műveleteket is. Csupán 8 látható regisztere van, és nincs két olyan, amely teljesen megegyezne. Az utasítások hossza 1 és 17 bájt között változik. Röviden, olyan örökölt architektúra, ami látszólag mindent rosszul csinál. Belülről azonban a Pentium 4 egy modern, egyszerű, mélyen csővezetékezett RISC-magot tartalmaz, mely különlegesen gyors órafrekvencián fut, és ez valószínűleg a következő években tovább növelhető. Egészen bámulatos, hogy az Intel mérnökei képesek voltak egy régi architektúrára korszerű processzort építeni. A NetBurst mikroarchitektúra áttekintése A Pentium 4 mikroarchitektúrája, melyet NetBurst mikroarchitektúrának neveznek, teljesen elszakad a Pentium Pro, Pentium II és Pentium IlI-nál használt korábbi P6 mikroarchitektúrától, és alapját képezi annak, amire az Intel a következő néhány évben építeni fog. A Pentium 4 négy fő részből áll: a memória-alrendszer, a bemeneti rész, a sorrenden kívüliséget vezérlő és a végrehajtó egység. A memória-alrendszer tartalmazza az egyesített L2 (2. szintű) gyorsítótárat és a küls6 RAMnak a memóriasínen való eléréséhez szükséges logikát. Az L2 az első generációs Pentium 4-ben 256 KB volt, a másodikban 512 KB, a harmadikban pedig 1 MB. Az L2 gyorsítótár 8 utas halmazkezelésű gyorsítótár, mely 128 bájtos gyorsítósoron alapszik. Ha egy keresett bejegyzés nem található meg az L2 gyorsítótárban, két 64 bájtos átvitelt kezdeményez a főmemóriából, hogy betöltse a szükséges blokkokat. Az L2 gyorsítótár egy visszaíró szervezésű gyorsítótár. Ez azt jelenti, hogy sor módosulásakor az új tartalom nem kerül vissza a memóriába, amíg a sor a memóriába nem töltődik. A gyorsítótárhoz kapcsolódik egy előre betöltő egység, amely megpróbálja előre betölteni az adatokat a főmemóriából az L2 gyorsítótárba, még mielőtt arra szükség lenne. Az L2 gyorsítótárból az adatok nagy sebességgel áramolhatnak más gyorsítótárakba. Egy új L2 gyorsítótár betöltése minden második óraciklusban kezdődhet, így például 3 GHz-es órajel mellett, elméletileg az L2 gyorsítótár akár 1,5 milliárd 64 bájtos blokkot is szolgáltathat másodpercenként a többi gyorsítótárnak, ami 96 GB/s sávszélességet jelent. A memória-alrendszer alatt a bemeneti rész található, amelyik betölti az utasításokat az L2 gyorsítótárból, és dekódolja a programnak megfelelő sorrendben. Minden Pentium 4 ISA-utasítást lebont RISC-szerű mikroműveletek sorozatára. Az egyszerűbb utasításokhoz a betöltő/dekódoló egység határozza meg, mely mikroműveletek szükségesek. A bonyolultabbaknál a mikroművelet sorozatot a mikro-ROM-ból keresi ki. Akár így, akár úgy, minden Pentium 4 ISA-utasítás mikroműveletek sorozatává konvertálódik a lapka RISC magja számára. Ezzel a mechanizmussal hidalták át az ősi CISC-utasításhalmaz és a modern RISC-adatút közötti szakadékot.
65.
A dekódolt mikroműveletek bekerülnek a nyomkövető gyorsítótárba, amely az 1. szintű utasítás-gyorsítótár. Azáltal, hogy a dekódolt mikroműveleteket gyorsítótárazza, és nem a feldolgozatlan utasításokat, egy nyomkövető gyorsítótárbeli utasítás végrehajtásakor nincs szükség másodszori dekódolásra. Ez a megközelítés az egyik kulcsfontosságú különbség a NetBurst mikroarchitektúra és a P6 között (az utóbbi csak a Pentium 4 utasításokat tároIta az 1. szintű utasításgyorsítótárban). Az elágazásjövendölésre is itt kerül sor. Az utasítások a nyomkövető gyorsítótárból a program által előírt sorrendben kerülnek az ütemezőbe, de onnan nem feltétlenül a program szerinti sorrendben kerülnek tovább. Ha egy nem végrehajtható mikroművelet következik, az ütemező tárolja, de folytatja az utasításfolyam feldolgozását, és a rákövetkező utasítások közül is kioszt olyanokat, melyek mindegyikének erőforrásai (regiszterek, működési egységek stb.) elérhetők. A regiszterátnevezés is itt történik, hogy késedelem nélkül továbbengedjük a WAR és WAW függőséggel rendelkező utasításokat. Habár az utasításokat sorrenden kívül is ki lehet osztani, a Pentium 4 architektúrának pontos megszakításokra vonatkozó követelménye azt jelenti, hogy az ISA utasításoknak sorrendben kell befejeződni (azaz elérhetővé tenni az eredményüket). Ezt a feladatot a befejező egység kezeli. Az ábra jobb felső negyedében találhatók a végrehajtó egységek, amelyek az egész, a lebegő pontos, és a speciális műveleteket hajtják végre. Több végrehajtó egység is létezik, és ezek párhuzamosan futnak. Adataikat a regiszterekből és az Ll adat gyorsítótárból kapják. Az UltraSPARC III Cu CPU-jának mikroarchitektúrája: Az UltraSPARC-sorozat a SPARC architektúra 9. változatának Sun megvalósítása. A felhasználó vagy a programozó szemszögéből (azaz ISA-szinten) a különböző modellek eléggé hasonlók, főleg teljesítményben és árban különböznek. A mikroarchitektúra szintjén azonban jelentősek a különbségek. A megnevezésben lévő Cu, a lapka vezetékeinél használt rézre utal, ellentétben az alumíniumvezetékezéssel, amit elődjénél használtak. A réznek kisebb az ellenállása, mint az alumíniumnak, ami vékonyabb vezetékeket és gyorsabb működést tesz lehetővé. Az UltraSPARC III Cu egy teljesen 64 bites gép, 64 bites regiszterekkel és 64 bites adatúttal, bár a 8. változatú (vagyis 32 bites) SPARC-okkal való visszafelé kompatibilitás miatt 32 bites operandusokat is tud kezelni, és valóban változtatás nélkül futtat 32 bites SPARC-szoftvert. Bár a belső architektúra 64 bites, a memóriasín 128 bit széles, a Pentium 4-hez hasonlóan, amelynek 32 bites architektúrája és 64 bites memóriasínje van, de mindkét esetben a sín egy generációval későbbi, mint maga a CPU. A Pentium 4-gyel ellentétben az UltraSPARC egy valódi RISC-architektúra, ami azt jelenti, hogy nincs szüksége arra a bonyolult mechanizmusra, ami a végrehajtáshoz átalakítja a régi CISCutasításokat mikroműveletekre. A gépi utasítások maguk a mikroműveletek. Azonban az utóbbi években grafikai és multimédia-utasításokkal egészítették ki a processzort, melyek végrehajtása speciális hardverberendezéseket igényel.
66.
Az UltraSPARC III Cu mikroarchitektúrájának áttekintése: Egészében véve, sokkal egyszerűbb, mint a Pentium 4 NetBurst mikroarchitektúrája, mert az UltraSPARC-nak egyszerűbb ISA-architektúrát kell megvalósítania. Mindemellett néhány lényeges komponens hasonlít a Pentium 4-nél használtakhoz. Ezeket a hasonlóságokat többnyire a technológia, illetve a gazdaságosság vezérelte. Például, amikor ezeket a lapkákat tervezték, ésszerűnek számított a 8-16 KB méretű L1 adatgyorsítótár, ezért lettek ekkorák. Ha valamikor a jövőben technológiai és gazdasági szempontból egy 64 MB-os L1 gyorsítótár számít majd ésszerűnek, akkor minden CPU-ban az lesz. Ezzel ellentétben a különbségek többnyire a régi CISC utasításhalmaz és a modern RISC-mag közötti különbségek áthidalásából, illetve ennek hiányából adódnak. A 32 KB-os 4 utas halmazkezelésű utasítás-gyorsítótár 32 bájtos gyorsítósort hasznáL Mivel a legtöbb UltraSPARC-utasítás 4 bájtos, így körülbelül 8K utasításnak van itt hely, ami valamivel kisebb, mint a NetBurst nyomkövető gyorsítótára. Az utasításkiosztó egység négy utasítást is elő tud készíteni óraciklusonként. Ha gyorsítótárhiány lép fel az L1 gyorsítótárban, kevesebb utasítást fog kiosztani. Ha egy feltételes elágazó utasításba ütközik, utánanéz a 16K bejegyzést tartalmazó ugrótáblában, hogy az a következő utasítást jövendöli, vagy a célcímen szereplőt. Ezen felül, az utasítás-gyorsítótárban lévő szavakhoz kapcsolt extrabit is segíti az elágazás jövendölést. Az előkészített utasítások átkerülnek egy 16 elemű utasítás pufferbe, amely kisimítja az utasítások csővezetékekbe áramlását. Az utasítás puffer kimenete bekerül az egész, a lebegőpontos és a betöltő/tároló egységekbe. Az egész aritmetikájú végrehajtó egység tartalmaz két ALU-t és egy rövid csővezetéket is az elágazó utasításokhoz. Az ISA-regiszterek és néhány firkáló regiszter is itt található. A lebegőpontos egység 32 regisztert és három külön ALU-t tartalmaz rendre az összeadás/kivonás, a szorzás és az osztás számára. A grafikai utasítások is itt kerülnek végrehajtásra. A betöltő/tároló egység kezeli a különböző betöltő és tároló utasításokat. Adatúttal rendelkezik három különböző gyorsítótárhoz is. Az adatgyorsítótár egy hagyományos 64 KB-os 4 utas halmazkezelésű L1 adatgyorsítótár, mely 32 bájtos gyorsítósort használ. A 2 KB-os előre betöltő gyorsítótár azért van jelen, mert az UltraSPARC ISA tartalmaz előre betöltő utasításokat, melyek lehetővé teszik a fordító számára, hogy adatszavakat töltsenek be, mielőtt még szükség lenne rájuk. Ha a fordító úgy gondolja, szüksége lehet egy bizonyos szóra, előre betöltő utasítást adhat ki, aminek eredményeképpen a megcímzett gyorsítósor idő előtt bekerül az előre betöltő gyorsítótárba, felgyorsítva ezzel a szó elérését, amikor néhány utasítás múlva szükség lesz rá. Bizonyos körülmények között hardveres előre betöltés is történik, hogy fokozódjon az olyan örökölt programok teljesítménye, amelyek nem végeznek előre betöltést. A tárolási gyorsítótár egy kisméretű (2 KB) gyorsítótár, melyet arra használunk, hogy összekapcsoljuk az eredmények írását, és jobban kihasználjuk az L2 gyorsítótárba menő 256 bit széles sínt. Egyedüli feladata a teljesítmény növelése.
67.
A lapka tartalmaz memóriavezérlő logikát is. Ez a logika három részre oszlik: a rendszerinterfészre, az L2 gyorsítótár-vezérlőre és a memóriavezérlőre. A rendszerinterfész 128 bit széles sínen keresztül kapcsolódik a memóriához. A külvilághoz érkező összes kérés, az L2 gyorsítótárat kivéve, ezen a felületen halad keresztül. A 43 bites fizikai memóriacímmel elméletben a főmemória egészen 8 TB-ig terjedhet, de az a nyomtatott áramkör, amire a processzort szerelték, 16 GB-ra korlátozza a memóriát. Az interfészt úgy tervezték, hogy több UltraSPARC-ot is lehessen ugyanahhoz a memóriához kapcsolni, hogy ezek multiprocesszort alkossanak. Az L2 gyorsítótár-vezérlő tartja a kapcsolatot az egyesített L2 gyorsítótárral, mely a CPU lapkáján kívül helyezkedik el. Azáltal, hogy az L2 gyorsítótár kívül van, 1, 4 és 8 MB is lehet a mérete. A gyorsítósor mérete függ a gyorsítótár méretétől, ami az 1 MB-os gyorsítótárra vonatkozó 64 bájttól a 8 MB-os gyorsítótárra vonatkozó 512 bájtig terjedhet. Összehasonlításul, a Pentium 4 L2 gyorsítótára a lapkán található, viszont helyhiány miatt 1 MB-ra korlátozódik. Két ellentétes nézet: az UltraSPARC jóval magasabb találati arányt érhet el az L2 gyorsítótárban, mint a Pentium 4 (mert nagyobb lehet a mérete), viszont az L2 gyorsítótár hozzáférése lassabb (mert nincs rajta a lapkán). A memóriavezérlő képezi le a 64 bites virtuális címeket 43 bites fizikai címekre. Az UltraSPARC támogatja a virtuális memóriát, ahol a lapok mérete 8 KB, 64 KB, 512 KB vagy 4 MB lehet. A leképezés gyorsítására speciális táblázatok, ún. TLB-k (Translation Lookaside Buffer, lapkezelő segédpuffer) állnak rendelkezésre, hogy össze lehessen hasonlítani az éppen hivatkozott virtuális címet a nemrégiben hivatkozottakkal. Három ilyen táblázat áll rendelkezésre az adatokhoz, hogy kényelmesen lehessen kezelni a különböző lapméreteket, és kettő az utasítások leképezéséhez. A 8051 CPU mikroarchitektúrája: Ez jóval egyszerűbb a Pentiumnál és az UltraSPARC-nál. Az egyszerűség oka, hogy a lapka nagyon kicsi (60000 tranzisztor), és még a csővezetékek elterjedése előtt tervezték. Továbbá az, hogy az elsődleges tervezési szempont az volt, hogy a lapka olcsó legyen, és nem az, hogy gyors. Az olcsóság és egyszerűség egymás jó barátai, míg az olcsóság és gyorsaság nem azok. A 8051-es lelke a fősín. Számos regiszter kapcsolódik hozzá, melyek többségét a programok képesek írni és olvasni. Az ACC regiszter az akkumulátor (ACCumulator), a fő aritmetikai regiszter, melyben a legtöbb számítás eredménye keletkezik. A legtöbb aritmetikai utasítás ezt használja. A B szorzás és osztás esetén kap szerepet, valamint ideiglenes eredmények tárolására is használható. Az SP regiszter a veremmutató, és mint a legtöbb gépben a verem tetejére mutat. Az IR regiszter az utasításregiszter. Az éppen végrehajtás alatt álló utasítást tartalmazza. A TMPl és TMP2 regiszterek az ALU tárolói. Egy ALU-művelet végrehajtásakor az operandusok először ezekbe a tárolókba kerülnek, az ALU csak ezután kezd működni. Az ALU kimenete bármelyik írható regiszterbe bekerülhet a fősínen keresztül. A PSW (Program Status Word, programállapotszó) -regiszterbe kerülnek a feltételkódok, melyek jelzik, ha az eredmény nulla, negatív stb.
68.
A 8051-es külön memóriával rendelkezik az adatok és a kód számára. Az adat RAM 128 (8051) vagy 256 bájtos (8052), így a 8 bites RAM ADDR regiszter elegendően széles a címzésre. A RAM címzéséhez a kívánt bájt címét a RAM ADDR regiszterbe kell tenni, és elindítani a memóriaműveletet. A kódmemória 64 KB lehet (ha lapkán kívüli memóriát használunk), így a címzéséhez használt ROM ADDR 16 bit széles. Ugyanúgy a ROM ADDR regiszter a programkódot címzi a ROM-ban. A DPTR (Double PoinTeR, dupla szélességű mutató) 16 bites regiszter a 16 bites címek kezelésére és összeállítására. A PC regiszter a 16 bites utasításszámláló, ami a következőnek betöltendő és végrehajtandó utasítás címét tartalmazza. A PC NÖVELŐ regiszter egy speciális hardver, amely pszeudoregiszterként működik. Ha belemásolják a PC-t, majd kiolvassák, az érték automatikusan növekszik. Sem a PC, sem a PC NÖVELŐ nem érhető el a fősínről. Végül, a PUFFER egy újabb 16 bites regiszter. Mindegyik 16 bites regiszter tulajdonképpen két 8 bites regiszterből áll, melyeket függetlenül is lehet kezelni, de a hatásuk 16 bites regiszterként érvényesül. A 8051 rendelkezik még a lapkán elhelyezett három 16 bites időzítővel, melyek nélkülözhetetlenek valós idejű alkalmazások esetén. Van még négy 8 bites B/K portja, melyek lehetővé teszik a 8051 számára, hogy akár 32 külső gombot, lámpát, érzékelőt, indítókart stb. vezérelhessen. Éppen az időzítők és a B/K portok teszik lehetővé, hogy a 8051 kiegészítő lapkák nélkül is használható legyen beágyazott alkalmazások esetén. A 8051 szinkronprocesszor, melynek legtöbb utasítása egy óraciklust igényel, bár némelyik többet. Minden óraciklust fel lehet osztani hat részre, melyeket állapotoknak nevezünk: 1. 2. 3. 4.
5. 6.
Betöltődik a következő utasítás a ROM-ból, rákerül a fősínre és az IR regiszterbe. Dekódolódik az utasítás és növekszik a PC. Az operandusok előkészítése történik. Az egyik operandus rákerül a fősínre, általában azért, hogy TMP1-en keresztül az ALU felhasználhassa. Az ACC regisztert is ebben az állapotban lehet átmásolni TMP2-be, így az ALU mind a két bemenete készen áll. Az ALU végrehajtja a műveletet. Végül az ALU kimenete visszakerül a fősínen keresztül a rendeltetési helyére. Eközben a ROM ADDR regiszter előkészül a következő utasítás betöltésére.
A 8051 egyetlen fősínnel rendelkezik (a lapka területének csökkentése miatt), regisztereinek halmaza heterogén, valamint három időzítő és négy port kapcsolódik a fősínre, továbbá van még néhány extra regisztere a lokális sínen. Minden adatút-ciklusban két operandus fut keresztül az ALU-n, és az eredmény visszakerül egy regiszterbe, ahogy az a korszerűbb számítógépeken is történik.
69.
29. A Pentium 4, az UltraSPARC III mikroarchitektúrájának összehasonlítása
és
az
I-8051
A három példánk nagyon különböző, de mégis van bennük némi közös. A Pentium 4-nek van egy régi CISC-utasításhalmaza, amelyet az Intel mérnökei legszívesebben bedobnának a San Franciscó-i öbölbe, ha ezzel nem szegnék meg Kalifornia vízszennyezési törvényeit. Az UltraSPARC III tiszta RISC-elképzelés, szegényes és egyszerű utasításhalmazzal. A 8051 egyszerű 8 bites processzor a beágyazott alkalmazások számára. Mégis mindegyik lelke a regiszterkészlet, és az egy vagy több ALU, amely elvégzi az egyszerű aritmetikai és logikai műveleteket a regisztereken. Ezen nyilvánvaló külső különbségek ellenére a Pentium 4-nek és az UltraSPARC III-nak nagyon hasonlók a végrehajtó egységei. Mindkét végrehajtó egység olyan mikroműveleteket fogad el, amelyek egy műveleti kódot, két forrásregisztert és egy célregisztert tartalmaznak. Mindkettő végre tud hajtani egy mikroműveletet egy ciklus alatt. Mindkettőnek nagy tudású csővezetékei, elágazásjövendölése, valamint osztott I- és D-gyorsítótára van. Ez a belső hasonlóság nem véletlen, és nem a Szilikon-völgy mérnökeinek végtelen munkaszeretetének köszönhető. Mint azt a Mic-3 és Mic-4 példákban láttuk, könnyű és természetes olyan csővezetékes adatutat építeni, amelyik vesz két forrásregisztert, átfuttatja az ALU-n, és az eredményt egy regiszterbe tárolja. A jelenlegi technológiával ez a leghatékonyabb kivitelezés. A fő különbség a Pentium 4 és az UltraSPARC III között az, ahogy ISA-utasításaikat a végrehajtó egységhez juttatják. A Pentium 4-nek szét kell bontania a CISC-utasításait, hogy - a végrehajtó egység elvárásainak megfelelően - háromregiszteres formátumúvá alakítsa őket. Nagy utasítások szétszedése csinos, formás mikroműveletekre. Az UltraSPARC III-nak nem kell semmit tennie, mert eredeti utasításai már csinos, formás mikroműveletek. Ezért van az, hogy a legtöbb új ISA RISC típusú - így könnyebb a megfeleltetés az ISA utasításhalmaz és a belső végrehajtó motor között. Tanulságos, ha végső tervezésünket, a Mic-4-et összehasonlítjuk ezzel a két valóságos példával. A Mic-4-hez leginkább a Pentium 4 hasonlít. Mindkettőnek az a feladata, hogy egy nem RISC ISA-utasításhalmazt értelmezzen. Ezt mindkettő úgy csinálja, hogy az ISA-utasításokat egy műveleti kóddal szétbontja mikroműveletekre, két forrásregiszterrel és egy célregiszterrel. Mindkét esetben a mikroműveleteket lerakjuk egy sorba, későbbi végrehajtásra. A Mic-4 elgondolás szigorú sorrend szerinti kiosztást, sorrend szerinti végrehajtást és sorrend szerinti befejezést követel, míg a Pentium 4-nek sorrend szerinti kiosztás, sorrendtől eltérő végrehajtás és sorrend szerinti befejezés a vezérelve. A Mic-4 és az UltraSPARC III valójában egyáltalán nem hasonlíthatók össze, mert az UltraSPARC III-nak RISC-utasításai vannak (vagyis háromregiszteres mikroműveletek), mint a saját ISA-utasításhalmaza. Ezeket nem kell szétbontani. Végrehajthatók úgy, ahogy vannak, mindegyik egyetlen adatút ciklussal. A Pentium 4-gyel és az UltraSPARC III-mal szemben a 8051 igazán egyszerű gép. Inkább RISC, mint CISC típusú, hiszen legtöbb utasítása egyszerű és szétbontás nélkül végrehajtható egy óraciklusban. Nincs csővezetéke és gyorsítótára, van viszont sorrend szerinti kiosztása, sorrend szerinti végrehajtása és sorrend szerinti befejezése. Egyszerűségében főleg a Mic-lgyel rokon.
70.
30. Gépi utasítási szint. Memória modellek, memória szemantika. A Pentium 4, az UltraSPARC III és az I-8051 regiszterei Gépi utasítási szint (ISA szint) Alapvetöen az ISA szint azt jelenti, ami a gépi szintű programozó számára látszik a gépből (mondjuk azt, hogy ami a fordítóprogramok kimete). ISA szintű kód készítése céljából a fordítóprogram írójának ismernie kell a memóriamodellt, hogy milyen regiszterek vannak, hogy milyen adatokat és utasításokat használhat, és így tovább. Mindezen információk összegződése alkotja az ISA szintet. E definíció szerint minden olyan kérdés, ami arra vonatkozik, hogy a mikroarchitektúra mikroprogramozott-e, csővezetékes-e, szuperskaláris-e, és így tovább, nem része az ISA szintnek, mert a fordítóprogram készítője számára nem látható. A szuperskaláris végrehajtás részletei láthatók az ISA szinten, így a szintek elválasztása nem is olyan egyszerű, mint elsőre látszik. Néhány architektúra ISA szintjét formális dokumentum definiálja, amelyet gyakran ipari konzorciumok készitenek. Mások esetén ilyen dokumentum nem létezik. Pl. mind a V9 SPARC (SPARC 9-es verzió), mind a JVM rendelkezik hivatalos dokumentációval (Weaver és Germond, 1994; valamint Lindholm és Yellin, 1997). Az a célja az ilyen definiáló dokumentumnak, hogy lehetővé tegye, hogy különböző megvalósítók olyan gépeket építsenek, amelyek ugyanazon szoftvert futtatják ugyanolyan eredményt produkálva. Az ISA szint egy másik fontos tulajdonsága, hogy a legtöbb gép legalább két módban működhet. A kernel mód az operációs rendszer futtatására szánt mód, amikor is minden utatsítás végrehajtható. A felhasználói mód a felhasználói programok futtatását célozza és nem teszi lehetővé bizonyos érzékeny utasítások végrehajtását (mint amelyek közvetlenül manipulálják a gyorsítótárat). Memória modellek Minden számítógép memóriája cellákra van osztva, és a cellák címei összefüggő tartományt képeznek. A leggyakoribb cellaméret napjainkban 8 bit, de régebben alkalmaztak 1-60 bites cellaméretet is (lásd 2.10 ábrát). Egy 8 bites cella neve bájt. A 8 bites cellaméret oka az, hogy az ASCII kód karakter 7 bit, így a paritásbittel együtt éppen belefér egy bájtba. A bájtok általában 4 bájtos vagy 8 bájtos (64 bit) csoportokba, szavakba vannak rendezve, lehetövé téve, hogy az utasítások teljes szavakon végezzenek műveletek. Sok architektúra megköveteli, hogy a szavak természetes határokhoz legyenek igazítva, pl. a 4 bájtos szavak címe 0,4,8,…stb kell legyen. Az igazítást gyakran azért követelik meg, mert a memória így hatékonyabban működhet. A Pentium 4 például, amely 8 bájtot olvas ki a memóriából, 36 bites fizikai címet használ, de csak 33 bit címe van. A legtöbb gép egyetlen lineáris címtartományt alkalmaz, ami 0-tól valami maximumig terjed, ami gyakran 232 vagy 264 bájt. Azonban néhény gép külön címtartománnyal rendelkezik az adatok, és külön az utasítások számára. Így a 8 címről történő utasítás kiolvasása más címtartományra
71.
vonatkozik, mint a 8 címről történő adat kiolvasása. Ez a séma bonyolultabb, mint amikor csak egyetlen címtartomány van, azonban két előnye is van. Először, lehetséges 232 méretü program és 232 adatok csak 32 bites címzést használva. Másodszor, mivel minden írás automatikusan az adatcímtartományra vonatkozik, nem lehet a programot ily módon felülírni, ami egy programozási hibaforrás kiküszöbölését jelenti. Memória szemantika Még egy aspektusa van az ISA szintű memória-modellnek – ez a memória szemantika. Természetes elvárás, hogy egy LOAD utasítás, amely ugyanazon címre vonatkozó STORE utasítás lett végrehajtva, éppen eltárolt adatot eredményez. Azonban, a mikroutasítások sorrendje átrendeződhet. Tehát valós a veszély, hogy a memória nem az elvárt módon viselkedik. A probléma még rosszabbá válhat multiprocesszor esetén, amikor a különböző CPU-k (esetleg átrendezett) olvasási szorzatot bocsátanak ki osztott memőriára vonatkozóan. Egy szélsőséges megoldás, ha minden memóriahivatkozást szekvencializálnak, így mindegyik előbb befejeződik, mint egy másik elkezdődne. Másik szélsőséges megoldás esetében semmi garancia nincs általánosan biztosítva. A memórihivatkozások sorrendjének kikényszerítésére SYNC utasítást kell a programnak végrehajtania, amely blokkolja minden memóriaművelet kibocsátását mindaddig, amíg az összes eddig kiadott memóriaművelet be nem fejeződött. Közbülső megoldás is lehetne a memóriamodellre, amikor is a hardver automatikusan blokkol bizonyos memóriahivatkozásokat (többek között a RAW és WAR szükséget tartalmazókat), de nem mindet. A Pentium 4 regiszterei A Pentium 4 regisztereit az 5.3. ábra mutatja. Az első négy, EAX, EBX, ECX és EDX többékevésbé általános célú regiszterek, bár mindegyiknek van sajátossága. Az EAX a fő aritmatikai regiszter, az EBX jól használható mutató (memóriacím) tárolására, az ECX-nek a ciklusszervezésben van szerepe. Az EDX a szorzás és osztás utasításoknál kell, amikor is az EXC-vel együtt tartalmazzák a 64 szorzatot, illetve osztandót. A felsorolt regiszterek mindegyikének első 16 bitje egy 16 bites, első 8 bitje pedig egy 8 bites regisztert alkot. Ezek lehetővé teszik 8 és 16 bites adatok, műveletek egyszerű elvégzését. A 8088 és 80286 csak 8, illetve 16 bites regisztert tartalmazott. A 32 bites regisztereket a 80386-tal vezették be, az E betüvel jelölve azokat, ami Extendedet jelent. A következő három szintén valamelyest általános célú regiszter, de több különlegességgel. Az ESI-t és EDI-t memóriába mutató mutatók tárolására szánták, különösen a hardveres karakterlánc műveletek esetén, amikor is az ESI a forrás (Source) karakterláncra, az EDI pedig a cél (Destination) karakterláncra mutat. Az EBP helyett is mutató-regiszter, tipikusan az aktuális veremkeret címét tartalmazza, mint az IJVM esetén az LV regiszter. Ha egy regiszter (mint az EBP) tartalma a lokális veremkeretet tartalmazza, akkor azt mondjuk, hogy keretmutató. Végül az ESP a veremmutató.
72.
A regiszterek köv. csoportja a CS és a GS nagymértékben elektronikus őskövületek, amelyeket a 8088 esetén a 220 méretű memória 16 bittel történő címzésére használtak. A következő az EIP, ami a programszámláló (Extended Istruction Pointer / kiterjesztett utasításmutató). Végül az EFLAGS regiszter látható, ami a PSW. Az UltraSPARC III regiszterei A UltraSPARC III regiszterek két csoportját tartalmazza: 32 darab 64 bites álatános célú regiszter és 31 darab lebegőpontos regiszter. Az általános célú regiszterek jelei: R0,….,R31, bár bizonyos környezetben más elnevezések is elöfordulnak. A globális változók olyan konstansok, változók és mutatók, amelyeket minden eljárás használ, bár szükség esetén elmenthetők és visszatöltheőök eljárásba való belépéskor, illetve kilépéskor. Az Ix és az Ox regisztereket paraméterek átadására használják, hogy elkerüljék a memóriahivatkozást. Három dedikált regisztert speciális célra használnak. Az FP és az SP regiszterek az aktuális keret határait tartalmazzák. Az FP regiszter az aktuális keret kezdőcímét tartalmazza és a lokális vátozók címzésére szolgál. Az SP az aktuális verem tetejére mutat és a verembe (push), illetve veremből (pop) műveletek hatására változik. Ezzel ellentétben az FP csak eljáráshíváskor és visszatéréskor változik A harmadik speciális célra használt regiszter az R31, ami az aktuális eljárás visszatérési címét tartalmazza. Az UltraSPARC ténylegesen 32-nél több általános regisztert tartalmaz, de csak 32 látszik a programozó számára egy adott pillanatban. Ezt a tulajdonságot regiszterablaknak nevezik. Regiszterablak technika: Andrew S. Tanenbaum: Számítógép architektúrák 363-365. o. Az UltraSPARC III 32 lebegőpontos regiszterrel rendelkezik, amelyek mindegyike vagy 32 bites, vagy 64 bites számot tartalmazhat. Lehetséges két regiszterben tárolni egy 128 bites számot is. Az UltraSPARC architektúrája töltés/tárolás architektúra. Ez azt jelenti, hogy csak a regiszterek és a memória közötti adatátvitelt megvalósító betöltő LOAD és tároló STORE utasítások hivatkoznak közvetlenül memóriára. Az összes többi utasítás operandusa mindig valamelyik regiszterben van (nem memóriában), vagy az utasításban van és az eredmény is mindig regiszterbe kerül. Az I-8051 regiszterei A 8051-es regiszterkezelése szokatlan. A legtöbb 8051-es program úgy készül, hogy nyolc darab 8 bites regisztert használ. Ez a természetes használata a CPU-nak, mert a legtöbb utasítás egy 3 bites mezőn határozza meg a használt regisztert. A regiszterekre R0,…,R7 nevekkel hivatkozunk. Mindamellett négy regiszterkészlete van, de egyszerre csak az egyik használható. A PSW 2 bites mezője mondja meg, éppen melyik készlet az aktuális. A több regiszterkészlet célja az, hogy lehetővé tegye a nagyon gyors megszakításfeldolgozást. Ha megszakítás keletkezik, a feldolgozó programnak nem kell elmentenie az összes reigisztert, hanem csak átvált egy másik készletre. A 8051-esnek ez a tulajdonsága lehetővé teszi, hogy másodpercenként nagyon nagy számú megszakítást tudjon feldolgozni, ami nagyon fontos tulajdonsága minden olyan processzornak, amelyet beágyazott valós idejű rendszerben akarnak használni.
73.
Egy másik sajátossága a 8051 regisztereinek, hogy a memóriában vannak. A memória 0. bájtja a 0. regiszterkészlet R0 regisztere, hasonlóan az 1. bájt az R1 regiszter és így tovább. A 8051 a négy általános regiszterkészleten kívül tartalmaz néhány speciális célú regisztert is. A PSW-ben balról jobbra haladva van az átvitelbit, kiegészítő átvitelbit, a használt regiszterkészletre utaló bitek, a túlcsordulásbit és a paritásbit. A használt regiszterkészletre utaló bitek kivételével minden bitet az arimetikai utasítások állítanak be. Az IE regiszter a megszakítások egyedi és kollektív engedélyezését és tiltását kezeli. Ha az EA bit 0, akkor minden megszakítás tiltott. Ezen bit törlése lehetővé teszi minden további megszakítás tiltását egyetlen utasítással. Az EA bit 1-re állítása engedélyez minden olyan megszakítást, amelynek egyedi bitje 1. Az E2, E3 és E0 bitek engedélyezik vagy tiltják a három időzítő csatornát. Legfeljebb három csatornához tartozó számláló futhat egyszerre, és ezek mindegyike megszakítást válthat ki, ha letelt az ideje. Az ES bit engedi vagy tiltja a soros vonali megszakítást. A további két bit a külső eszközök megszakítását engedi vagy tiltja. Az IP regiszter határozza meg a megszakítások prioritási szintjét. Két szint van: alacsony és magas. Ha alacsony prioritási szintű megszakítás kiszolgálása közben magas prioritású keletkezik, akkor az alacsony feldolgozása felfüggeszthető, de fordítva nem. A TCON regiszter vezérli a 0. és az 1. időzítőt, ezek a fő időzítők. Az O1 és O0 biteket hardver állítja be, ha a hozzá tartozó időzítő túlcsordul. Az R1 és R0 bitek a futásvezérlő bitek, amelyek lehetővé teszik, hogy a program szoftveresen ki- vagy bekapcsolja az időzítőt. A többi bit a két időzítő él- vagy szintvezérlésével kapcsolatos. Az utolsó regiszter, a TMOD az időzítők üzemmódját határozza meg (8, 13 vagy 16 bites), hogy valódi időzítő avagy számláló, továbbá a fokozatot, hogy mely hardverjelek vezérlhetik az időzítőt. Az összes eddig említett speciális regiszter és még néhány, mint az akkumulátor, a B/K portok, mind a 128-255 memóriatartományban vannak. Ezek ugyanúgy címezhetők, mint bármely memóriacella, ahogy az R0-R7 regiszterek is. Például az akkumulátor, amely szerepel szinte minden aritmetikai utasításban, a 240-es címen található. A 8052 esetén, amely valódi memóriát tartalmaz a 128-255 tartományban, a speciális regiszterek átlapolják a memóriateret. Direkt címzés esetén a 8052-es a speciális regisztereket címzi, míg indirekt hivatkozáskor (regiszterben lévő mutatóval) a RAM-on.
74.
31. A Pentium 4, az UltraSPARC III, az I-8051 utasítás formátumai, címzési módjai. A Pentium 4 utasításformátumai A Pentium 4 utasításformátumai nagyon bonyolultak és szabálytalanok, hatféle változó hosszúságú mezővel, amelyek közül öt opcionális. Ez a helyzet azért alakult ki, mert az architektúra több generáción keresztül fejlődött, és a korai fázisban nem éppen jó döntéseket hoztak. Továbbá, a visszafelé kompatibilitás kényszere miatt később nem lehetett változtatni. Általánosan érvényes, hogy ha egy kétoperandusú utasítás egyik operandusa a memóriában van, akkor a másik nem lehet a memóriában (csak regiszterben). Tehát léteznek utasítások, amelyek regiszter-regiszter, regisztermemória, memória-regiszter operandusokon dolgoznak, de nincs olyan utasítás, amelynek mindkét operandusa a memóriában lenne. A korai Intel-architektúrákban minden utasítás műveleti kódja 1 bájtos volt, bár utasítások módosítására intenzíven használták az úgynevezett prefix bájt módszert. Ez azt jelenti, hogy van egy extra bájt az utasítás elején, ami módosítja a jelentését. A prefix bájtra példa a WIDE utasítás az IJVM esetén. Szerencsétlen módon a fejlődés során egyszer csak az Intel kifogyott a műveleti kódokból, és bevezette a 0xFF kiterjesztő kódot (escape code), hogy lehetővé tegyen egy második műveletikódbájtot. A Pentium 4 egyedi bitjei nem sok információt adnak magáról az utasításról. Az egyetlen szerkezet a műveleti kód mezőjében bizonyos utasításoknál, hogy a szélső bit jelzi, hogy bájt vagy szó az operandus, egy másik bit pedig azt, hogy a memóriába vagy regiszterbe kerül a művelet eredménye. Tehát a műveleti kódot teljesen dekódolni kell annak meghatározásához, hogy milyen osztályba tartozik a végrehajtandó utasítás, vagy hogy mekkora a hossza. Ez megnehezíti a nagy hatékonyságú megvalósítást, mivel még ahhoz is intenzív dekódolást kell végrehajtani, hogy meghatározzák a következő utasítás címét. Sok memóriára hivatkozó utasításban a műveleti kód bájtot a következő bájt adja meg ténylegesen az utasítást. Ez a 8 bit egy 2 bites MOD és két 3 bites REG és R/M mezőkre oszlik. Néha az első 3 bit a műveleti kódhoz tartozik, így összesen 11 bites a kód. Azonban a 2 bites mód mező csak négyféle operanduscímzési módot határozhat meg, és az egyik operandusnak regiszternek kell lennie. Logikusan az EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP regiszterek mindegyike megadható lenne, de a módszer miatt néhány kombináció tiltott, és speciális esetekre használják. Néhány mód további bájtokat igényel, ezek az SIB (Scale, Index, Base - skála, index, bázis). Ez a séma nem ideális, de kompromisszumot képez a visszafelé kompatibilitás kényszere és az új lehetőségek bevezethetősége között. Mindezekhez vegyük még hozzá, hogy néhány utasítás 1, 2 vagy 4 további bájtot tartalmaz memóriacím (eltolás) megadására, és további 1, 2 vagy 4 bájtot a konstans számára. Az UltraSPARC III utasításformátumai Az UltraSPARC III ISA minden utasítása pontosan 32 bit és szó határra igazított. Az utasítások általában egyszerűek, és csak egy akciót határoznak meg. A tipikus aritmetikai utasítás két regisztert specifikál a bemenő operandusok és egyet az eredmény számára. Van olyan változat, amikor az egyik
75.
regiszter helyett egy 13 bites előjeles konstanst lehet megadni. A LOAD utasítás összeadja két regiszter (vagy egy regiszter és egy 13 bites konstans) tartalmát, így képezve a betöltendő cella címét. Az eredeti SPARC nagyon korlátozott utasításformákat tartalmazott. Később új formák keletkeztek. E könyv írásának idején 31 a számuk, és ez növekszik. (Mikor áll elő vajon egy cég, hogy a világ legösszetettebb RISC gépét reklámozza?) A legtöbb új változat úgy keletkezett, hogy bizonyos mezőkből néhány bitet elhagytak. Például az eredeti elágazó utasítás a 3. formát használta 22 bites eltolással. Amikor a jövendölő elágazást bevezették, a 22 bitből 3-at levágtak, egyet a jövendölésre használtak (lesz/nem lesz elágazás), kettőt pedig a feltételkód megadására alkalmaztak. Így maradt 19 bit az eltolásra. Egy másik példa erre a sok adattípus-konvertáló utasítás (például egészből lebegőpontosba). Sok ezek közül az 1b formájú variánsa: az IMMEDIATE mezőt felbontották egy 5 bites részre (a forrásregiszter specifikálására) és egy 8 bites részre (további műveleti kódokra). Minden utasítás első két bitje segít meghatározni az utasítás formáját, és megadja a hardvernek, hol találja a műveleti kód maradék részét, ha van egyáltalán. Az 1a formában regiszter mind a két forrás; az 1b-ben az egyik forrásregiszter, a másik egy -4096 és +4095 közötti konstans. A 13. bit a két forma közül választ (a jobb szélső bit a 0.). Mindkét esetben regiszter acél. 64 utasítás kódolásához elegendő hely van az 1a formában; ezek pillanatnyilag későbbi felhasználásra foglaltak. 32 bites utasítás esetén nem lehet 32 bites konstanst megadni az utasításban. A SETHI utasítás 22 bitet ad meg, a maradék 10 bitet másik utasítás adja meg. Ez az egyetlen utasítás, amelynek ez a formája. A nem jövendölő ugró utasítások 3-as formájúak, ahol a FELT mező mondja meg, hogy melyik feltételt kell ellenőrizni. Az A bit hivatott megakadályozni a késleltetési rés létrejöttét bizonyos feltételek esetén. A jövendölő ugrások formája ugyanilyen, kivéve a 19 bites eltolást, amelyet már említettünk. Az utolsó forma a CALL utasításé, amely eljáráshívást végez. Ez az utasítás speciális, mert ez az egyetlen, amelyben 30 bit kell a cím megadására. Erre az ISA-ban csak 2 bites a műveleti kód. A célcím a megadott cím négyszerese, ami azt eredményezi, hogy az adott utasítás helyétől (közelítőleg) ± 231 bájt tartományt lehet címezni. A 8051 utasításformátumai: A 8051-es processzornak hatféle egyszerű utasításformája van. Az utasítások hossza 1, 2 vagy 3 bájt. Az első forma csak egyetlen műveleti kódot tartalmaz. Például az akkumulátor tartalmát növelő utasítás használja ezt a formátumot. A 2. formátum hossza szintén egy bájt, amely 5 bites műveleti kódot és 3 bites regisztercímet tartalmaz. Ilyen formátumú sok utasítás, amely az akkumulátor és egy regiszter tartalmán végez valamilyen műveletet (például regiszter és akkumulátor tartalmának összeadása, adatmozgatás regiszter és akkumulátor között). A 3. formátumnak egy 1 bájtos operandusa van. Az operandus lehet közvetlen konstans, például amit akkumulátorba tölt, lehet eltolás, például az ugrás távolsága, vagy lehet bitsorszám, például az n. bitet beállító, törlő vagy ellenőrző utasításban. A 4. és 5. formátum ugró és szubrutinhívó utasítások formája. A 11 bites változat akkor használható, ha nincs külső memória, tehát minden programcím 4096 alatti (8051) vagy 8192 alatti (8052). 8 KB-nál nagyobb külső memória esetén a 16 bites forma szükséges. A 6.
76.
formátumú utasításoknak két 8 bites operandusa van. Sokféle utasítás ilyen formátumú, például egy 8 bites közvetlen operandusnak a lapkán lévő memóriacellába töltése. A Pentium 4 címzési módjai: A Pentium 4 címzési módjai nagyon szabálytalanok, és attól is függnek, hogy 16 vagy 32 bites az utasítás. A továbbiakban eltekintünk a 16 bites módtól, a 32 bites is eléggé rossz. A támogatott módok: közvetlen, direkt, regiszter-, regiszter-indirekt, indexelt címzés és még egy speciális mód tömb elemek címzésére. Az a gond, hogy nem minden mód alkalmazható minden utasításban, és nem minden regiszter használható minden módban. Ez nagyon megnehezíti a fordítóprogram-készítők dolgát, és gyenge kódot eredményez. Az 5.14. ábrán a MODE bájt vezérli a címzési módot. Az egyik operandust a MOD és az R/M mezők határozzák meg. A másik operandus mindig regiszter, hogy melyik, azt a REG mező tartalmazza. Az 5.27. ábra felsorolja azt a 32 kombinációt, amelyet a 2 bites MOD és 3 bites R/M mező szolgáltat. Például, ha mindkét mező 0, akkor az operandust a memóriából olvassa, amelynek címe az EAX regiszterben van. A 01 és 10 oszlopok tartalmazzák azokat a módokat, amelyekben 8, illetve 32 bites eltolást lehet megadni a (gépi) utasítás végén. Ha 8 bitest választunk, akkor a hozzáadás előtt előjelesen kiterjeszti 32 bitesre. Például az ADD utasítás az R/M=011, MOD=01 és 6 eltolás esetén kiszámít ja az EBX és 6 összegét, és az így kapott címről veszi az egyik operandust. Az EBX nem módosul. A MOD=11 oszlopnál két regiszter közül választhatunk. Szavas utasítások az első változatot, a bájtos utasítások pedig a második változatot használják. Megjegyzendő, hogy a táblázat nem teljesen szabályos. Például nem lehet az EBP indirekt és az ESP relatív címzés. Megéri ez a mód a fáradságot? Nehéz válaszolni a kérdésre. Kétségtelen, hogy ha jól használják, akkor ezzel a móddal több ciklus megtakarítható. Használatának gyakorisága függ a fordítóprogramtól és az alkalmazástól. Az a gond, hogy ennek a módnak a megvalósítása a lapka egy részét elviszi, amelyet másra is lehetne használni, ha nincs ez az utasítás. Például az 1. szintű gyorsítótár nagyobb lehetne, vagy a lapka mérete kisebb, ami nagyobb órajelsebességet engedne. Ezek azok a kompromisszumok, amelyekkel a tervezők állandóan szembesülnek. Általában intenzív tesztelést végeznek mielőtt szilikonba öntenék a tervet. Azonban nagyon jól megalapozott elképzeléssel kell rendelkezni a szimulációhoz, figyelembe véve a várható terhelést. A 8088 tervezői biztosan nem teszteltek webböngészővel. Mindazonáltal, nem sok számítógép elődjét használták webböngészésre, így a 20 évvel ezelőtti döntések teljesen hamisak lehetnek a mai alkalmazások szempontjából. Azonban a visszafelé kompatibilitás kényszere miatt nehéz kidobni azt, ami egyszer már bekerült. Az UltraSPARC III címzési módjai: Az UltraSPARC ISA minden utasítása közvetlen vagy regisztercímzést használ, kivéve azokat, amelyek memóriára hivatkoznak. Regisztermódban 5 biten van adva a regiszter. A közvetlen módban 13 bites (előjeles) adat lehet a konstans. Nincs más módú aritmetikai, logikai vagy hasonló utasítás. Háromféle utasítás hivatkozik memóriára: a betöltő (LOAD), a tároló (STORE) és egy multiprocesszorszinkronizáló utasítás. A LOAD és STORE utasítások kétféle módban dolgozhatnak. Az egyik módban
77.
két regiszter tartalmának összege adja a címet. A másik a hagyományos indexelés 13 bites eltolási értékkel. A 8051 címzési módjai: A 8051 címzési módja nagyon szabályos. Öt alapvető címzési módja van. A legegyszerűbb az implicit mód, amely az akkumulátort használja. Sok utasítás végez műveletet egy operandus és az akkumulátor tartamán, ilyen az összeadás, kivonás, ÉS, VAGY. Az akkumulátort használó utasításokban nincs speciális bit, amely azt jelezné, hogy az akkumulátort kell használni. Ezt a műveleti kód magába foglalja. A másik a regisztermód, amikor az egyik operandus regiszter. Regiszter lehet akár forrás, akár cél. A harmadik mód a direkt címzés, amikor az operandus a memóriában van, amelynek címe az utasítás része. A negyedik mód a regiszter-indirekt címzés, amikor az operandus címe regiszterben van. Mivel minden normál regiszter 8 bites, ezért az operandusnak a memória alsó 256 címén kell lennie. Az ötödik mód a közvetlen mód, amikor az operandus magában az utasításban van megadva. A 8051 speciális címzési módot tartalmaz néhány olyan utasításban, amely memóriaelérést végez. Emlékeztetünk, hogy a 8051-nek lehet 64 KB külső program és 64 KB külső adatmemóriája is. Ezért szükség van valamilyen címzési módra, amely lehetővé teszi ezek elérését. A külső memória elérését két utasítás biztosítja, a LJMP, amely 16 bites eltolási értéket tartalmaz, így lehetővé tesz bármely memóriacímre ugrást, és az LCALL, amely szintén 16 bites eltolást tartalmaz, így bármely memóriacímen lévő eljárást tud hívni. A külső adatmemória elérése más módszerrel történik. A 8051 rendelkezik egy 16 bites mutató regiszterrel, ez a DPTR, amely 16 bites memóriacímet tartalmazhat. Ezt a programok betölthetik, aztán a betöltött érték indirekt címzésre használható, így elérhető a teljes 64 KB-os tartományt.
78.
32. Veremcímzés. Fordított lengyel (postfix) jelölés. Dijkstra algoritmusa. Postfix alakú formulák kiértékelése Veremcímzés Már korábban megjegyeztük, mennyire kívánatos, hogy a gépi utasítás annyira rövid legyen, amennyire csak lehet. A végsőkig redukálva a cím hosszát, eljutunk a 0 címes utasításhoz. Mint már láttuk, 0 címes utasítás lehetséges a veremmel kapcsolatban, például ilyen az IADD. Ebben a szakaszban alaposabban megvizsgáljuk a veremcímzést. Fordított lengyel jelölés A matematikában régi hagyomány, hogy a művelet jelét az operandusok közé írják, mint x + y, nem pedig azok után, mint x y +. Ha a műveleti jel az operandusok között van infix jelölésről beszélünk. Ha a műveleti jel az operandusok után áll, akkor postfix vagy fordított lengyel jelölés az elnevezés, a lengyel logikatudós J. Lukasiewicz után, aki kimutatta ennek a jelölésnek a jó tulajdonságait. A fordított lengyel jelölésnek számos előnye van az infix jelöléssel szemben algebrai kifejezések esetén. Először is, minden formula kifejezhető zárójel nélkül. Másodszor, kényelmesen kiértékelhetők a formulák számítógéppel verem használatával. Harmadszor, az infix operátorokra elsőbbségi szabály vonatkozik, amely tetszőleges és nem kívánatos. Például tudjuk, hogy az a * b + c jelentése (a * b) + c és nem a * (b + c), mivel a szorzás nagyobb prioritású, mint az összeadás. Vajon nagyobb prioritású-e a balra léptetés, mint a logikai AND? Ki tudja. A fordított lengyel jelölés kiküszöböli ezt a kellemetlenséget. Számos algoritmus ismert infix formulák fordított lengyel jelölésre konvertálására. Az itt következő algoritmus E.W Dijkstra ötletén alapszik. Tegyük fel, hogy a formula a következő jeleket tartalmazhatja: változók, bináris (kétoperandusú) operátorok: + - * /, továbbá bal és jobb zárójelek. A formula végeinek jelzésére a formula elé és után a jelet tesszük. Példa rajzzal együtt a könyv 386. oldalán. A változók sorrendje az infix és prefix jelölésben megegyezik. A műveleti jelek sorrendje azonban nem mindig azonos. A fordított lengyel jelölésben a műveleti jelek olyan sorrendben szerepelnek, amilyen sorrendben azok végrehajtódnak a kifejezés kiértékelésekor. Infix A+B*C A*B+C A*B+C*D (A +B)/(C - D) ((A + B ) * C + D) / (E + F + G)
79.
Fordított lengyel jelölés ABC * + AB * C + AB * CD * + AB + CD - / AB + C * D + EF + G + /
Fordított lengyel jelölésű formulák kiértékelése A fordított lengyel jelölés ideális formulák számítógépes kiértékelésére verem használatával. A formula n jelből áll, mindegyik vagy operandus, vagy műveleti jel. A fordított lengyel jelölésű formulának veremmel való kiértékelése egyszerű algoritmus. Olvassuk a formulát balról jobbra. Ha az operandushoz érünk, akkor rakjuk a verembe. Ha az aktuális jel műveleti jel, akkor hajtsuk végre a megfelelő műveletet.
Az ábra a (8 + 2 * 5) / (1 + 3 * 2 - 4) formula kiértékelését mutatja JVM-ben. Az ennek megfelelő fordított lengyel jelölés a következő: 825*+132*+4-/ Az ábrán bevezettük az IMUL és IDIV utasításokat, amelyek a szorzás illetve az osztás műveletet végzik. A verem tetején lévő operandus a jobb és nem a bal operandus. Ez fontos az osztás (és kivonás) esetén, mivel az operandusok sorrendje lényeges (nem úgy, mint az összeadásnál és szorzásnál). Más szóval az IDIV utasítást körültekintően definiálták, először az osztandót kell a verembe tenni, majd az osztót, és ez után kell elvégezni a műveletet, hogy helyes eredményt kapjunk. Vegyük észre, hogy milyen egyszerű kódot generálni az (I)JVM-re fordított lengyel jelölésből: csak olvassuk balról jobbra a formulát, és jelenként kiadunk egy utasítást. Ha a jel konstans vagy változó, akkor olyan utasítást kell kiadni, amely azt a verembe teszi. Ha a jel műveleti jel, akkor a műveletet megvalósító utasítást kell kiadni. Lépés 1 2 3 4 5 6 7 8 9 10 11 12 13
A maradék formula 825*+132*+4-/ 25*+132*+4-/ 5*+132*+4-/ *+132*+4-/ +132*+4-/ 132*+4-/ 32*+4-/ 2*+4-/ *+4-/ +4-/ 4-/ -/ /
80.
Utasítás BIPUSH 8 BIPUSH 2 BIPUSH 5 IMUL IADD BIPUSH 1 BIPUSH 3 BIPUSH 2 IMUL IADD BIPUSH 4 ISUB IDIV
Verem 8 8, 2 8, 2, 5 8, 10 18 18, 1 18, 1, 3 18, 1, 3, 2 18, 1, 6 18, 7 18, 7, 4 18, 3 6
33. Vezérlési folyamat. Szekvenciális vezérlés, elágazás, ciklus szervezés, eljárás, rekurzív eljárás, korutinok, megszakítás, csapda A vezérlési folyamat A vezérlési folyamat azt a sorrendet jelenti, amelyben az utasítások végrehajtódnak dinamikusan, tehát a program végrehajtása során. Általában elágazás és eljáráshívás nélkül, egymást követő memóriahelyekről kiolvasott utasítások a kiolvasás sorrendjében hajtódnak végre. Eljáráshívás hatására a végrehajtási sorrend megváltozik, az éppen végrehajtás alatt lévő eljárás felfüggesztődik, és a hívott eljárás végrehajtása elkezdődik. A korutinok hasonlóak az eljárásokhoz, ezek is hasonlóan térítik el a végrehajtási sorrendet. A korutinok hasznosak a párhuzamos eljárások szimulálásánál. A csapdák és a megszakítások speciális feltételek bekövetkezésekor térítik el a végrehajtási sorrendet. Szekvenciális vezérlés és elágazás Miután egy utasítás végrehajtódott, a memóriában őt követő utasítás olvasódik és hajtódik végre. Minden utasítás után a programszámláló értéke megnövelődik a végrehajtott utasítás hosszával. A programszámláló értéke hozzávetőleg az idő függvényében lineárisan növekszik, az átlagos utasításhossz / átlagos utasítási idő mértékével. Ha a program tartalmaz elágazást, akkor ez az egyszerű kapcsolat az utasítások memóriabeli sorrendje és a végrehajtásuk sorrendje között nem áll fenn. Ha van elágazás, akkor a programszámláló értéke nem lineáris függvénye többé az időnek. Eljárások A programok strukturálásának legfontosabb technikáját az eljárások adják. Bizonyos szempontból az eljáráshívás ugyanúgy eltéríti a végrehajtási sorrendet, mint az ugrás, csak amikor befejezte a feladatát az eljárás, a vezérlés visszatér a hívást követő utasításra. Más szempontból azonban az eljárás törzse úgy tekinthető, mint egy magasabb szinten definiált utasítás. Ebből a szempontból az eljáráshívás egyetlen utasításnak tekinthető, még akkor is, ha az eljárás meglehetősen bonyolult. Különösen érdekes az eljárások egy speciális fajtája, a rekurzív eljárás, amely önmagát hívja vagy közvetlenül, vagy más eljárásokon keresztül. Eljárás-prológusnak nevezzük azt a tevékenységet, amely a régi veremkeret-mutató elmentését, az új veremkeret-mutató megadását és a veremmutatónak a lokális változók befogadása miatti növelését tartalmazza. Az eljárásból való visszatéréskor a vermet ki kell takarítani, ezt nevezzük eljárás-epilógusnak. Minden számítógépnek egyik legfontosabb jellemzője, hogy a prológust és az epilógust milyen gyorsan és röviden tudja elvégezni. Ha ez hosszú és lassú, akkor az eljáráshívások költségesek. A Pentium 4 ENTER és LEAVE utasításait azért tervezték, hogy a prológus illetve az epilógus nagy részét hatékonyan elvégezzék.
81.
Korutinok Néha hasznos, ha két eljárás, A és B egymást eljárásként hívja, oly módon, hogy ha B visszatér A-hoz, akkor a végrehajtás a B-t hívó utasítás után folytatódik. Ha a vezérlés A-tól B-hez kerül, akkor a végrehajtás (kivéve az első alkalmat) a legutolsó B-ből való visszatérést követő, vagyis az utolsó A-t hívó utasítással folytatódik. Az olyan két eljárást, amelyek ilyen módon működnek, korutinnak nevezzük. Korutinokat általánosan alkalmaznak párhuzamos feldolgozás szimulálására olyan gépeken, amelyekben csak egy CPU van. Mindegyik korutin peszeudo-párhuzamosan fut a másikkal, mintha saját processzora lenne. Ez a programozási stílus megkönnyíti bizonoys alkalmazások megvalósítását, továbbá hasznos olyan szoftver tesztelésénél, amelyet később többprocesszoros gépen futtatnak. Sem a hagyományos eljáráshívó CALL, sem a visszatérő RETURN nem alkalmazható korutinoknál. Mivel az ugrás helyének a címe veremből jön, mint a visszatérés esetén, de a korutin maga is eltárolja a címet a későbbi visszatérés végett. Csapdák A csapda olyan automatikusan hívott eljárás, amelyet valamely, a program által előidézett feltétel vált ki, amely fontos, de ritkán fordul elő. Jó példa erre a túlcsordulás. Sok számítógépen, ha az aritmetikai művelet eredménye olyan nagy lenne, amit nem lehet a gépen ábrázolni, akkor csapda keletkezik, ami azt jelenti, hogy a vezérlés egy meghatározott memóriacímre adódik, nem folytatódik normálisan. Azt az eljárást, amelyre ilyenkor a vezérlés adódik, csapdakezelőnek hívják, amely valamely megfelelő tevékenységet végez, például hibaüzenetet ír ki. Ha az aritmetikai művelet eredménye az ábrázolási tartományban marad, akkor csapda nem keletkezik. Alapvető jellemzője a csapdának, hogy a program maga okoz valamilyen kivételes helyzetet, amit a hardver, vagy a mikroprogram fedez fel. A túlcsordulás lekezelésének egy alternatív módja az, amikor a túlcsordulás egy 1 bites regisztert állít 1-re. A programozó, ha kezelni akarja a túlcsordulást, minden aritmetikai utasítás után le kell kérdeznie ezt a bitet. Ez azonban lassú és tárpazarló megoldás. A csapda időt és memóriát takarít meg a programvezérelt megoldáshoz képest. A csapda megvalósítható a mikroprogram (hardver) által végzett tényleges ellenőrzéssel. Ha a csapda bekövetkezett, akkor a csapdakezelő rutin címe töltődik a programszámlálóba. Ami csapda egy adott szinten, az programvezérelt lehet alacsonyabb szinten. Ha mikorprogrammal végeztetjük az ellenőrzést, még mindig időt takarítunk meg a program által végzett teszthez képest, mert könnyen átlapolható más tevékenységgel. Memóriát is megtakarítunk, mert csak egy helyen, a mikroprogram fő ciklusában kell elhelyezni. Néhány kivételes helyzet, amely csapdával lekezelhető: lebegőpontos túlcsordulás, lebegőpontos alulcsordulás, egész túlcsordulás, védelem megsértése, definiálatlan műveleti kód, veremtúlcsordulás, nem létező B/K eszköz indítása, szóolvasási kísérlet páratlan memóriacímről, 0-val való osztási kísérlet.
82.
Megszakítások A megszakítás olyan eltérítése a vezérlési folyamatnak, amelyet nem a program okoz, hanem valami más, általában B/K: például, a program utasíthatja a lemezegységet, hogy kezdje el az adatátvitelt és annak befejeztekor megszakítást küldjön. Ugyanúgy, mint a csapda, a megszakítás bekövetkeztekor is megáll a program végrehajtása és a vezérlés a megszakításkezelőre adódik, amely elvégzi a kívánt tevékenységet. Ha ez befejeződött, a megszakításkezelő visszaadja a vezérlést a megszakított programnak. A megszakított processzusnak pontosan azt az állapotát kell helyreállítani, mint ami akkor volt, amikor a megszakítás történt. Alapvető különbség a csapdák és a megszakítások között a következő: a csapdák a programmal szinkronban vannak, a megszakítások pedig aszinkronban. Ha egy programot milliószor megismétlünk ugyanazzal a bemenettel, a csapda mindig pontosan ugyanott keletkezik, de a megszakítás nem, függhet például attól, hogy a gépkezelő mikor nyomja le a return gombot. A csapdák reprodukálhatóságának az az oka, hogy közvetlenül a program okozza, míg a megszakításokat nem, azokat csak közvetetten okozza a program. A megszakításokkal kapcsolatos kulcsfogalom az átlátszóság. Amikor megszakítás következik be, bizonyos műveletek végrehajtódnak, bizonyos kód végrehajtódik, de amikor ennek vége a számítógép ugyanabba az állapotba kerül, mint amelybe a megszakítás előtt volt. Az ilyen módon működő megszakítási rutint átlátszónak nevezzük. Az átlátszóság miatt sokkal egyszerűbb megérteni a megszakításokat. A 8088 óta az Intel CPU-nak két megszakítási szintje van (elsőbbségi értéke): maszkolható és nem maszkolható. A nem maszkolható megszakítások általában csak a katasztrófa közeli állapotokra használatosak, mint memóriaparitás-hiba. Minden B/K eszköz maszkolható szinten dolgozik.
83.
34. Operációs rendszer szintje. Virtuális memória. Lapméret, elaprózódás. Szegmentálás. A Pentium 4 és az UltraSPARC III virtuális memóriája. Virtuális memória Az első számítógépek idejében a memória kevés és drága volt. A probléma hagyományos megoldása másodlagos memória, például lemez igénybevétele. A programozó olyan átfedéseknek (overlays) nevezett kisebb részekre osztotta fel programját, amelyek külön-külön már elfértek a memóriában. A program futásakor először az első rész töltődött be és futott egy darabig. Amikor befejezte működését, beolvasta és elindította a következő részt és így tovább. A programozónak kellett gondoskodni a program átfedésekre darabolásáról, az egyes részek elhelyezéséről a másodlagos memóriában, a memória és a lemez közti mozgatásukról, és általában az átfedéses rendszer kezeléséről. A gép ehhez semmi segítséget nem adott. Az átfedések automatikus kezelésére, melynél a programozónak nem is kell tudnia az egész rendszerről (Fotheringham, 1961): ez a módszer, amely ma virtuális memória (virtual memory) néven ismeretes. Lapozás A címtartomány és a memóriarekeszek fogalmának szétválasztása. A címtartomány és a memóriacímek elkülönítésének az elve a következő. Bármely időpillanatban közvetlenül 4096 szó érhető el a memóriából, de ezek nem feltétlenül a 0 és 4095 közti memóriacímeknek felelnek meg. „Megmondjuk” a gépnek, hogy mostantól kezdve például a 4096 címre való hivatkozás esetén a memória 0 című szavát kell használni. Ha a 4097 címre hivatkozunk, ez jelentse az 1 memóriacímet, a 8191 a memória 4095 címén található szót, stb. Ha a címtartományt a tényleges memóriarekeszekbe az ábrán megadott séma szerint képezzük le mondhatjuk, hogy egy 4KB-os, virtuális memória nélküli gép esetén fix leképezésünk van a 0-s 4095 közti címek, valamint a memória 4096 szava között. Ezek után feltehetjük azt az érdekes kérdést, hogy mi történik akkor, ha a program végrehajtása során 8192 és 12287 közti címekre ágazik el. Virtuális memória nélküli gépen az futási hibát okozna, melynek hatására „Nem létező memóriacímre hivatkozás” vagy hasonló durva hibaüzenet után befejeződne a program végrehajtása. Virtuális memóriával rendelkező gépen a következő lépések hajtódnak végre: 1. a memória tartalmának lemezre mentése 2. a 8192 és 12287 közti szavak megkeresése a lemezen 3. a 8192 és 12287 közti szavak betöltése a memóriába 4. a végrehajtás folytatása, mintha mi sem történt volna. Az átfedések automatikus kezelésének ezen technikáját lapozásnak (paping), a lemezről beolvasott programrészeket lapoknak (pages) nevezzük. A címtartományhoz tatozó címeknek a valódi memóriacímekre való leképezését kifinomultabban is kezelhetjük. A nyomaték kedvéért azon címeket, amelyekre a program tud hivatkozni, virtuális címtartománynak (virtual addres space), míg a tényleges „hardveres” címeket fizikai címtartománynak (physical addres space) fogjuk nevezni. A memóriatérkép (memory map) vagy laptábla (page map) a virtuális címeket kapcsolja össze a fizikai
84.
címekkel. Feltesszük, hogy a lemezen van elég hely a teljes címtartomány (vagy legalábbis a használatban lévő része) számára. A programok úgy írhatók meg, mintha a teljes címtartomány számára elegendő memória lenne a gépben, még ha a valóságban nem is ez a helyzet. A program betölthet tetszőleges virtuális címről, írhat oda, a végrehajtás elágazhat a virtuális címtartomány tetszőleges helyén található utasításra, tekintet nélkül arra, hogy nincs is elegendő fizikai memória. Valójában a programozónak nem is kell tudnia a virtuális memória létezéséről. Egyszerűen úgy látja, mintha a gépen rengeteg memória lenne. A lapozási mechanizmust transzparensnek hívjuk, hiszem a programozó úgy írhat kódot, mintha nem is lenne lapozás. A lapozás megvalósítása A virtuális memória egyik alapkövetelménye az egész program és az összes adat tárolására szolgáló lemezegység. A virtuális címtartományt azonos méretű lapokra szokás felosztani. A ma szokásos lapméretek 512 bájt és 64 KB közé esnek, bár alkalmanként használnak akár 4 MB-os lapokat is. A lapméret mindig 2 valamelyik hatványa. A fizikai címtartományt hasonlóan osztják fel. A darabok mérete a lapmérettel megegyező, így mindegyikük pontosan egy lap tárolására alkalmas. Ezeket a memóriadarabokat, melyekbe lapokat töltünk be, lapkeretnek (page frames) fogjuk nevezni. Minden virtuális memóriával ellátott számítógép tartalmaz a virtuálisról fizikai címre való leképezést megvalósító eszközt. Ennek neve MMU (Memory Management Unit, memóriakezelő egység). Elhelyezkedhet magán a CPU lapkán vagy külön lapkán, amely szorosan együttműködik a CPU-val. Az általunk példaként felhozott MMU a 32 bites virtuális címeket 15 bites fizikai címekre képezi le; ehhez 32 bites bemeneti és 15 bites kimeneti regiszterre van szüksége. A kérésre lapozás és a munkahalmaz modell Az olyan hivatkozás, amely nem a memóriában lévő lapon található címre vonatkozik, laphibát (page fault) okoz. Laphiba felléptekor az operációs rendszernek be kell olvasnia lemezről a kért lapot, be kell írnia új fizikai helyét a laptáblába, és meg kell ismételnie a hibát okozó utasítást. A virtuális memória használatának ezt a módszerét kérésre lapozásnak (demand paging) nevezzük, annak a jól ismert gyereketetési algoritmusnak analógiájára, melynél ha sír a baba megetetjük, szemben a precíz napirend szerinti etetéssel. A kérésre lapozásnál a lapok nem töltődnek be előre, hanem csak akkor ha ténylegesen kérik őket. Ha a gépben időosztást használunk, tehát processzusok mondjuk 100 ms futás után cserélődnek, futása során minden program rengetegszer lesz újraindítva. Mivel minden programhoz egyedi memóriatérkép tartozik, s programváltáskor ez is változik, időosztásos rendszerekben kritikussá válhat a helyzet. Az alternatív megközelítés azon a megfigyelésen alapul, hogy a legtöbb program nem egyenletesen hivatkozik a címtartományra, hanem néhány lap körül „sűrűsödnek össze” a hivatkozások. Egy memóriahivatkozás utasítást tölthet be, adatokat olvashat, vagy tárolhat. Bármely t időpillanatban tekinthetjük a legutóbbi k memóriahivatkozásban szereplő lapok halmazát. Denning (1968) nyomán ezt munkahalmaz (woking set) néven fogjuk emlegetni. Mivel munkahalmaz időben lassan változik, a legutóbbi megállításkori halmaz alapján elfogadható becslések adhatók arra,
85.
hogy a program újraindításkor mely lapokra lesz szükség. Ezek a lapok már a program indítása előtt betölthetők (feltéve, hogy beférnek a memóriába). Lapkezelési eljárások Ha a program olyan lapra hivatkozik, amely nincs a memóriában, a szükséges lapot be kell tölteni lemezről. Legtöbbször azonban először „helyet kell csinálni”, bizonyos lapokat vissza kell írni a lemezre. Szükségünk van tehát ez eltávolítandó lapokat megadó algoritmusra. A legtöbb operációs rendszer megpróbálja megjósolni, hogy melyek a memóriában levő „leghaszontalanabb” lapok abban az értelemben, hogy eltávolításuk a legkisebb mértékben zavarná a futó programot. Ennek egyik módja az lehet, hogy minden lapra megjósolja a várható legközelebbi hivatkozás időpontját, s azt a lapot távolítja el, aminél ez a legtávolabbi jövőbeni időpont. Más szóval ahelyett, hogy egy nemsokára szükséges lapot mentenénk ki, próbáljunk olyat választani, ami még sokáig nem fog kelleni. Az egyik népszerű algoritmus a legrégebben nem használt lapot veszik mivel nagy a valószínűsége, hogy ez nincs benne a munkahalmazban. A módszer neve LRU (Least Recently Used, legrégebben használt) algoritmus. Általában jól használható, bár vannak olyan patologikus esetek, amikor csúnya kudarcot vall. Ha azonban a rendelkezésre álló memória nagyobb a munkahalmazénál, az LRU várhatóan minimalizálni fogja a laphibák számát. A másik lapkezelő elv a FIFO (First-In First-Out, először be először ki). A FIFO módszer a legrégebben betöltött lapot távolítja el, függetlenül attól, mikor hivatkoztak rá utoljára. Minden lapkerethez egy számláló tartozik, melyeket kezdetben 0-ra állítunk. Az éppen a memóriában tartózkodó lapokhoz tartozó számlálók értékét minden laphiba után eggyel növeljük, az újonnan betöltött lapét pedig nullával inicializáljuk. Ha lapot kell eltávolítani, azt választjuk, amelynek számlálója a legnagyobb értéken áll. Mivel az ő számlálója a legnagyobb, ez a lap „élte túl” a legtöbb laphibát. Ez azt jelenti, hogy korábban lett betöltve a memóriában levő összes lapnál, és így (remélhetőleg) komoly esélye van annak, hogy nem is lesz rá szükség a továbbiakban. Azt a jelenséget, amikor egy program gyakran, szinte folyamatosan laphibákat generál, vergődésnek (trashing) fogjuk nevezni. Talán fölösleges megemlítenünk, hogy nemkívánatos jelenségről van szó. Ha egy eltávolítandó lapon nem módosítottunk semmit a beolvasás óta (ami nagyon valószínű, ha nem adatot hanem programkódot tartalmaz), szükségtelen visszaírni a lemezre, hiszen ott már létezik egy pontos másolata. Ha a beolvasás óta módosítottuk, a lemezen lévő példány már nem pontos, ezért ki kell írni a mostanit. Amennyiben meg tudjuk mondani valahogyan, hogy a beolvasás óta a lap változatlan maradt (tiszta, clean) vagy pedig írtunk rá (szennyezett, dirty), elkerülhető a tiszta lapok újraírása. Ezzel egy csomó időt spórolunk meg. Sok gépen az MMU-ban minden laphoz tartozik egy bit, amelyet betöltéskor 0-ra állít, és a hardver vagy a mikroprogram 1-re módosít, ha a lap szennyezetté válik (ráírtunk valamit). Az operációs rendszer ennek a bitnek vizsgálatával el tudja dönteni, hogy a lap tiszta vagy szennyezett, tehát vissza kell-e másolni a lemezre lapcsere esetén.
86.
Lapméret és elaprózódás Ha véletlenül úgy adódik, hogy a felhasználó programja és adatai valahány lapon pontosan elférnek, a memóriába való betöltésükkor nem pocsékolunk el helyet. Ellenkező esetben az utolsó lapon valamennyi hely kihasználatlan marad. Ha egy 4096 bájtos lapméretű gépen például a program és az adatok összesen 26000 bájtot igényelnek, akkor megtellik az első 6 lap (6x4096= 24576 bájt), és az utolsó lapra marad még 26000-24576=1424 bájt. Mivel laponként 4096 bájt számára van hely, elpocsékolunk 2672 bájtot. Ahányszor csak betöltjük a hetedik lapot a memóriába, ezek a bájtok teljesen haszontalanul foglalnak le helyet. Az elvesztegetett bájtokkal kapcsolatos fönti problémára belső elaprózódás (interal fragmentation) néven fogunk hivatkozni (a kihasználatlan hely valamelyik lap belsejében található). Szegmentálás Sok esetben előnyösebb, ha egyetlen virtuális címtér helyett kettő vagy több címtartományunk van. Az egyik nyilvánvaló megoldás: sok, teljesen független címtartomány, ún. szegmensek (segments) bevezetése. A szegmenscímek 0-tól valamely maximális értékig terjedő lineáris sorozata. Az egyes szegmensek hossza 0-tól a megengedett maximumig bármekkora lehet. A különböző szegmensek lehetnek eltérő hosszúságúak, rendszerint ez is a helyzet. A szegmensek hossza még változhat is a végrehajtás során. Például valahányszor a verembe beleteszünk valamit, a veremszegmens mérete nőhet, ha kiveszünk belőle, csökkenhet. Mivel minden szegmens külön címtartományt alkot, a különböző szegmensek egymástól függetlenül nőhetnek vagy zsugorodhatnak. Amikor az egyik szegmensben elhelyezkedő veremnek a növekedéséhez nagyobb címtartományra van szüksége, nyugodtan megkaphatja, mert semmi más nincs a címtartományban, amivel összeütközésbe kerülhetne. A szegmensek természetesen betelhetnek, de általában olyan nagyok szoktak lenni, hogy ez csak ritkán fordulhat elő. Ilyen szegmentált vagy kétdimenziós memória esetén a programok két részből álló címmel adják meg a tényleges címet. Az első rész a szegmens száma, a második a szegmensen belüli cím. Hangsúlyozzuk, hogy a szegmens olyan logikai egység, ami a programozó számára is látható, s amelyet ő is egyetlen logikai egységként kezel. A változó méretű adatstruktúrák egyszerűbb kezelése mellett a szegmentált memóriának más előnyei is vannak. Ha az egyes eljárások 0 kezdőcímtől más-más szegmensekben helyezkednek el, a külön lefordított eljárások összelinkelése után az n. szegmensben lévő eljárás hívása a 0. szó (belépési pont) megcímzésére az (n, 0) kétrészes címet fogja használni. A szegmentálás megvalósítása A szegmentálás kétféle módon valósítható meg: cseréléssel (swapping) vagy lapozással. Az első módszernél minden időpillanatban szegmensek bizonyos halmaza van a memóriában. Ha olyan szegmensre történik hivatkozás, amely pillanatnyilag nincs bent, akkor betöltődik. Ha nincs elég hely számára, először egy vagy több szegmenst lemezre kell kiírni (kivéve, ha ezekből már van a lemezen tiszta példány; ekkor a memóriában található másolat eldobható). A szegmensek cserélése bizonyos értelemben hasonló a kérésre lapozáshoz: a szegmensek szükség szerint mozognak a lemez és a memória között. A szegmentálás megvalósítása azonban lényegesen eltér a lapozásétól: míg a lapméret rögzített, a szegmensek mértéke változó. Külső elaprózódás (external fragmentation), mivel az elpocsékolt hely a szegmenseken kívül, a köztük lévő lyukakban van. A külső elaprózódást néha lyukacsosodás (checker-boarding) néven is emlegetik.
87.
A külső elaprózódás elkerülésének egyik lehetséges módszere a következő. Valahányszor lyuk keletkezik, a lyuk mögötti szegmenseket toljuk el a 0 memóriacím felé, úgy, hogy ezt a lyukat megszüntessük. Ekkor persze a memória végén keletkezik egy nagyobb lyuk. Esetleg várhatunk is addig, míg a külső elaprózódás egy komolyabb szintet nem ér el (például a teljes memória adott százaléka fölé nem kerül a lyukak összege) és csak ekkor kezdjük el a memória „összepréselését”. Egy népszerű algoritmus, a legjobb illesztés (best fit), azt a legkisebb lyukat választja, amibe még belefér a kért szegmens. Emögött az az ötlet áll, hogy a lyukat és a szegmensek összepárosításánál lehetőleg ne „törjünk le” darabokat olyan nagy lyukakból, amelyeket fel lehetne használni a későbbi nagy szegmensekhez. A másik kedvelt eljárás, az első illesztés (fist fit) körbemegy a listán, és azt az első lyukat választja, amely elég nagy a szegmens tárolására. Ehhez nyilvánvalóan kevesebb idő kell, mint az egész lista átnézéséhez a legjobb illesztés megkeresésénél. Meglepő, hogy az általános hatékonyság szempontjából is jobb az első illesztés algoritmusa a legjobb illesztésnél. Az utóbbi hajlamos arra, hogy rengeteg kicsiny, teljesen haszontalan lyukat hozzon létre. Amikor olyan szegmenseket távolítunk el a memóriából, amelynek mindkét közvetlen szomszédja lyuk volt, az egymás utáni lyukak egy nagy lyukká olvadnak össze. A szegmentálás másik megvalósításánál a szegmenseket fix méretű lapokra osztjuk, és ezeket lapozzuk a kérések szerint. Lehetséges, hogy valamelyik szegmens lapjainak egy része a memóriában, a többi meg a lemezen van, ha ezt a megoldást választjuk. A lapozáskor minden szegmenshez külön laptábla kell. Mivel miden szegmens csupán egy lineáris címtartomány, az összes eddig megismert lapozási technika alkalmazható a szegmensekre. Az egyetlen új sajátosság az, hogy minden szegmens saját laptáblát kap. A Pentium 4 virtuális memóriája A Pentium 4-nek olyan kifinomult virtuálismemória-rendszere van, amely egyaránt támogatja a kérésre lapozást, a tiszta szegmentálást és a lapozással kombinált szegmentálást. A Pentium 4 virtuális memóriájának legfontosabb része két tábla, az LDT (Local Descriptor Table, lokális leírótábla) és a GDT (Global Descriptor Table, globális leírótábla). Minden programnak saját LDT-je van, de a gépen futó összes program egyetlen megosztott GDT-t használ. Míg a GDT rendszerszegmenseket ír le, ideértve magát az operációs rendszert is, addig az LDT a programra nézve lokális szegmenseket ad meg (kód, adat, verem stb). Mihelyt megtudja a hardver, hogy melyik szegmens-regisztert kell használni, belső regisztereiben rögtön megtalálja a szektorhoz tartozó teljes leírót. Ha nemlétező szegmensről van szó (a szelektor 0) vagy a szegmens pillanatnyilag nincs a memóriában (P értéke 0), csapda keletkezik. Ezután azt vizsgálja, hogy az offset a szegmens határain belül van-e; ha nem, ez ismét csapdát okoz. Ha a szegmens a memóriában van, és az offset is a megengedett határok közé esik, akkor a Pentium 4 a leíró 32 bites BASE mezőjét az offsethez hozzáadva a 6.14. ábrál látható lineáris címet (lineal address) alakítja ki. Ha a lapozás tiltott (a globális vezérlőregiszter egy bitjével), akkor a lineáris cím fizikai címként értelmeződik, és egyből továbbítódik a memória felé. Így lapozás nélküli tiszta szegmentálással állunk szemben. Ha viszont engedélyezett a lapozás, akkor a lineáris cím virtuális címként értelmeződik, és laptáblák használatával képeződik le a fizikai címre. Minden futó programhoz tartozik egy lapkönyvtár (page directory), amely 1024 darab 32 bites bejegyzést tartalmaz, erre a lapkönyvtárra egy globális regiszter mutat. A könyvtár minden bejegyzése szintén 1024 darab 32 bites bejegyzést tartalmazó laptáblákra mutat. A laptáblák bejegyzései lapkeretekre mutatnak.
88.
Az UltraSPARC III virtuális memóriája Az UltraSPARC III 64 bites virtuális címeken alapuló lapszervezési virtuális memóriát támogató 64 bites gép. Tervezési és költségszempontok miatt azonban a programok nem használják a teljes 64 bites virtuális címtartományt. Csak 44 bit érhető el, emiatt a programok nem lehetnek 1,8x1013 bájtnál hosszabbak. A megengedett virtuális memória két darab, egyenként 243 bájt fizikai hosszúságú zónára van felosztva. Az egyik a virtuális címtartomány legalján, a másik a legtetején helyezkedik el. A köztük levő résbe elő virtuális címek nem érhetők el, használatuk hibát okoz. A rendkívül nagy virtuális címtartomány miatt a Pentium 4-hez hasonló direkt laptábla nem volna praktikus. Az UtraSPARC MMU-ja ehelyett egészen más megközelítést használ. Tartalmaz egy TLB (Translation Lookaside Buffer) nevű hardvertáblát, ez képezi le a virtuális lapokat fizikai lapkeretekre. A TLB csak a legutóbb használt virtuális lapok sorszámát tárolja. A kód- és az adatlapokat külön kezeli, mindkét kategóriából a legutóbbi 64 lapszámot őrzi meg. Minden TLB-bejegyzés egy virtuális lapsorszámból és a neki megfelelő fizikai lapkeret sorszámából áll. Amikor az MMU egy processzusszámot vagy másképp környezetet (context) és egy ebbe a környezetbe tartozó virtuális címet kap, speciális áramkörök segítségével egyből összehasonlítja az adott környezethez tartozó összes TLB-bejegyzéssel. Ha valahol egyezést talál, a megfelelő TLB-bejegyzésben szereplő lapkeret sorszámot a virtuális címben szereplő offsettel összekombinálva képezi a 41 bites fizikai címet és néhány egyéb jelzőbitet (védelem stb). Ha nem talál egyezést, TLB-hiány (TLB miss) keletkezik, amit csapdáz az operációs rendszer. A hiány kezelése az operációs rendszeren múlik. TLB-hiány még akkor is előfordulhat, ha a hivatkozott lap a memóriában van. A kért virtuális lapra vonatkozó új TLB-bejegyzés beírasakor az operációs rendszer elméletileg bárhogyan eljárhatna. A hardver azonban némi segítséget is ad ennek a kritikus tevékenységek minél gyorsabban elvégzéséhez - már ha a szoftver hajlandó vele együttműködni. Elsősorban elvárjuk, hogy az operációs rendszer készítsen a gyakran használt TLB-bejegyzésekről egy szoftveres gyorsítótárat a TSB (Translation Storage Buffer) nevű táblázatban. Ez a táblázat virtuális lapok direktleképezett gyorsítótáraként épül fel. TLB-hiány esetén az operációs rendszer megvizsgálja, hogy megfelelő TSB-bejegyzés a szükséges lapot tartalmazza-e. Az MMU kellemes szolgáltatása a bejegyzés címének automatikus kiszámítása és az operációs rendszer által elérhető belső MMU-regiszterbe helyezése. TSB-találat esetén valamelyik TLB-bejegyzés törlődik, és helyére bemásolódik a kért TSB-bejegyzés. A kitörlendő TLB-bejegyzés kiválasztását a hardver 1 bites LRUalgoritmusa támogatja. Ha a TSB-keresés sikertelen volt, a virtuális lap nincs a gyorsítótáblán, az operációs rendszer egy másik táblázatban keresi a lapra vonatkozó információkat. A végső megoldásként használt tábla neve fordítótábla (translation table).
89.
35. Terminál. Modemek, jelzési, adatátviteli sebesség. Terminálok A számítógépes terminálok két részből állnak: billentyűzet és monitor. A nagygépes világban ez a két rész gyakran egybe van építve, és soros vonalon vagy telefonhálózaton keresztül van a központi géphez kapcsolva. A személyi számítógépek világában a billentyűzet és a monitor különálló egység. Háromfajta terminált használnak széles körben: a karaktertérképes terminálokat, bittérképes terminálokat és RS-232-C terminálokat. Ezek mindegyike használhat bármilyen billentyűzetet, de különbség van a számítógéppel való kommunikációban és a megjelenítés módjában. Egy személyi számítógépben a képernyőn való megjelenítés kétféle lehet: karaktertérképes és bittérképes. Karaktertérképes terminálok A karakterek úgy kerülnek megjelenítésre, hogy a CPU a videomemóriába másolja őket, minden második bájtba egyet. Minden karakterhez tartozik egy attribútumbájt, ami meghatározza, hogy az adott karaktert hogyan kell megjeleníteni. Attribútum lehet szín, fényesség, villogás stb. Így egy 25*80 karakterből álló képernyő 4000 bájtnyi videomemóriát igényel, 2000 bájtot a karaktereknek és 2000 bájtot az attribútumoknak. A legtöbb kártyán több képernyőre elegendő memória van. A videokártyának az a feladata, hogy folyamatosan olvassa a videomemóriát és a monitor meghajtásához szükséges jeleket generáljon. Az előállított jel egy nagy frekvenciájú analóg jel, amely karaktereket kirajzoló elektronsugár mozgását vezérli. Bittérképes terminálok A képernyőt nem 25*80-as karaktertömböknek tekintjük, hanem olyan tömbnek, amely képpontokból, úgynevezett pixelekből áll. Minden pixel ki- vagy bekapcsolt állapotban lehet. A karaktertérkép helyett bittérképet használó terminálokat bittérképes termináloknak nevezzük. Minden mai videokártya tud karaktertérképes és bittérképes módban is működni, a kettő között szoftveres úton válthatunk. A karaktereket úgy lehet megjeleníteni hogy mondjuk egy 9*14-es téglalapot tartunk fenn minden karakter számára, és ezeket a megfelelő bitmintákkal feltöltjük. Ezzel a módszerrel különböző típusba tartozó karakterek is megjeleníthetők egymással keverve. A hardver csak annyit csinál, hogy megjeleníti a bittömböt. A színes képernyők esetén minden pixelnek 8, 16 vagy 24 bit van fenntartva. A bittérképes terminálok gyakran ablakokat jelenítenek meg. A bittérképes terminálok nagyon rugalmasak, de két nagy hátrányuk is van. Először is nagyméretű videomemóriára van szükségük, a leggyakoribb felbontások manapság a 640*480 (VGA), 800*600 (SVGA), 1024*768 (XVGA) és az 1280*768-as képernyő. A szélesség és magasság aránya mindegyiknél 4:3. a legjobb színeket úgy kaphatjuk, ha mindhárom elsődleges színhez 8 bitet
90.
használunk, vagyis 3 bájtot pixelenként. Tehát egy 1024*768-as képernyő 2,3 MB videomemóriát igényel. A bittérképes terminálok másik hátránya a teljesítményük. A mozgás folyamatosságához legalább 25 képkockát kell vetíteni másodpercenként, tehát a szükséges adatátvitel 57,6 MB/s 1024*768-as felbontás esetén. Ez a terhelés sokkal nagyobb, mint amire az (E)ISA sín képes, ezért az IBM PC-k nagy teljesítményű videokártyái szükségképpen PCI kártyák. Egy kapcsolódó probléma a képernyő gördítése. Ez rendkívül terheli a CPU-t, ezért sok videokártya speciális hardvert tartalmaz, amelynek segítségével bázisregiszterek átállításával, másolás nélkül lehet képernyőrészeket mozgatni. RS-232-C terminálok Az RS-232-C szabványos számítógép-terminál interfész. A termináloknak egy szabványos 25 tűs csatlakozójuk van. Az RS-232-C szabvány meghatározza a csatlakozó méreteit és formáját, a feszültség szinteket és az egyes vonalak jeleinek jelentését. Ha a számítógép és a terminál messze van egymástól, akkor gyakran az egyetlen praktikus összeköttetési lehetőség a telefonkapcsolat. Sajnos a telefonrendszer nem képes az RS-232-C szabványnak megfelelő jelek továbbítására, ezért egy modemnek nevezett jelátalakító eszközt kell a számítógép és a telefon, illetve a telefon és a terminál közé beiktatni. Hogy kommunikálni tudjanak, a számítógép és a terminál is tartalmaz egy UART (univerzális aszinkron vevő és továbbító) lapkát, valamint a sín eléréséhez szükséges áramköröket. Egy karakter megjelenítéséhez a számítógép beolvassa azt a központi memóriából, átadja az UART-nak, ami aztán bitenként küldi őket az RS-232-C kábelre. Az UART tulajdonképpen egy párhuzamos-soros átalakító, mert egy egész karaktert kap, majd meghatározott ütemben egyenként adja ki a biteket. Egy start- és egy stopbitet is ad minden karakterhez, hogy a kezdetét és a végét fel lehessen használni. A terminálban egy másik UART fogadja a biteket és összeállítja a karaktert, amit aztán megjelenít a képernyőn. A terminál billentyűzetén bevitt adatok átesnek egy párhuzamos-soros átalakításon a terminálban, és a számítógép UART-jában kerülnek újra összeállításra. Az RS-232-C szabvány majdnem 25 jelet definiál. A 2. és a 3. vonal az adatok küldésére és fogadására szolgál. Minden vonal egy egyirányú bitfolyamot kezel, ellentétes irányokban. Amikor a terminál vagy a számítógép adatot akar küldeni, akkor a Request to send vonalon jelzi a szándékát. Ha a modem képes az adat fogadására, akkor a Clear to send vonalon jelez vissza. A többi vonal különféle állapotlekérdező, tesztelő és időzítési feladatokat lát el. Modemek A sima telefonvonal nem alkalmas a számítógép jeleinek továbbítására, mivel utóbbiak általában a 0-kat 0 volttal, az 1eseket 3-5,5 volt közötti feszültséggel reprezentálják. A kétszintű jelek jelentős torzulást szenvednek a hangátvitelre tervezett vonalon, ami átviteli hibákat eredményez. Egy 1000 és 2000 Hz közötti, vivőhullámnak nevezett tiszta szinuszos hullámjel azonban aránylag kis torzulással átvihető.
91.
Mivel a szinuszjel hullámzása tökéletesen kiszámítható, egy tiszta szinuszjel nem hordoz semmilyen információt. Az amplitúdó, a frekvencia vagy a fázis változtatásával azonban átvihetjük 1esek és 0-k sorozatát. Ezt a folyamatot modulációnak nevezik. Az amlplitúdómoduláció két feszültségszintet használ. A frekvenciamoduláció esetén a feszültségszint állandó, de a vivőhullám frekvenciája eltérő 1-esek és 0-k esetén. Gyakran frekvenciaeltolásos kódolásnak is evezik. Az egyszerű fázismodulációnál az amplitúdó és a frekvencia nem változik, de a vivőhullám fázisa 180 fokkal eltolódik minden 0-1 vagy 1-0 váltásnál. A vivőhullám fázisa minden oszthatatlan időintervallum kezdetén hirtelen eltolódhat 45, 135, 225 vagy 315 fokkal, ezzel az úgynevezett kétbites fáziskódolással 2 bitet lehet intervallumonként átvinni. Az időintervallumok száma a baud. Mivel a telefonvonal csak egy csatornát szolgáltat, a biteket sorosan, egymás után kell elküldeni. Az az eszköz, amelyik kétszintű jelek formájában, bitenként karaktereket fogad el a számítógéptől és a biteket egyesével vagy kettesével amplitúdó-, frekvencia- vagy fázismodulációt használva továbbítja: a modem. A küldö modem az egy karakterhez tartozó biteket egyenlő időközönként küldi el. Például a 9600 baud 104 milliomod másodpercenkénti jelváltást jelent. A fogadó oldalon egy másik modem konvertálja a modulált jelet bitsorozattá. Mivel a bitek szabályos időközönként érkeznek, ha a fogadó meghatározta a karakter elejét, akkor már csak az órajelét kell figyelnie, hogy mikor vegyen mintát a következő bitek meghatározásához. A mai modemek 28800 bit/másodperc és 57600 bit/másodperc sebességgel működnek, általában ennél jóval alacsonyabb baud értékek mellett. Majdnem mindegyik full-duplex (egyszerre mindkét irányba tud kommunikálni). A fél-duplex modem egyszerre csak egy irányba tud kommunikálni. A szimlpex csak az egy irányba működő vonalak neve.
92.
36. ADSL, kábeles internet. Azokat a szolgáltatásokat, amelyek a normál telefonvonalnál nagyobb sávszélességet biztosítanak, időnként szélessávúnak nevezik, bár ez a meghatározás inkább piaci, mint speciális technikai fogalom. ADSL Kezdetben több egymást átfedő ajánlat jelent meg, amelyek az xDSL általános terminológia alá tartoznak. A továbbiakban ismertetjük, hogy valószínűleg mivé válik majd ezek közül a legnépszerűbb, az ADSL. Mivel az ADSL jelenleg is fejlődik, ezért a szabvány nem minden eleme van teljesen a helyén, az alábbiakban ismertetett néhány részlet idővel megváltozhat, az alapelképzelés azonban érvényes marad. A modemek lassúságának az az oka, hogy a telefont az emberi hang továbbítására találták ki, és a teljes rendszert erre a feladatra optimalizálták. Az adattovábbítás mindig is mostohagyermek volt. Az előfizetőktől a telefontársaság központjába futó vezetéket, amelyet lokális huroknak neveznek, tradicionálisan egy 3000 Hz-es szűrővel korlátozzák a telefontársaságnál. Ez az a szűrő, amely behatárolja az adattovábbítás sebességét. Szűrő nélkül a lokális huroknak a gyakorlatban elérhető sávszélessége függ a vezeték hosszától, de általában néhány kilométer távolságon elérheti az 1,1 MHz-et. Az ADSL-kínálat legelterjedtebb megközelítését a 2.38 ábra mutatja be. Lényegében, azt teszik, hogy eltávolítják a szűrőt, és az elérhető 1,1 MHz spektrumot 256 független, egyenként 4312,5 Hz szélességű csatornára osztják fel. A 0-s csatornát az egyszerű régi telefonszolgáltatás céljaira használják. Az 1-5. csatornát nem használják, azért hogy megelőzzék a telefonhang és az adatjelek interferenciáját. A fennmaradó 250 csatornából egyet a felmenő, egyet a lejövő adatfolyam vezérlésére használnak. A többi csatorna pedig a felhasználók adatait továbbítja. Az ADSL olyan, mintha 250 modemünk lenne. Elvileg minden fennmaradó csatorna egy-egy full-duplex adatfolyam megvalósítására alkalmas, de a felharmónikusok, az áthallás és más effektusok a gyakorlati rendszereket jóval az elméleti korlát alatt tartják. A szolgáltató határozza meg, hogy hány csatornát lehet feltöltésre és hányat letöltésre használni. Az 50-50% is megvalósítható lenne a felmenő és a lejövő csatornák számára, de a legtöbb szolgáltató a sávszélesség 80-90%-át a letöltésre allokálja, hiszen a legtöbb felhasználó inkább letölt adatokat, mint fel. Emiatt került az „A” betű az ADSL rövidítésbe. Egy gyakori megosztás: 32 csatorna a feltöltésre, és az összes többi pedig a letöltésre. Az egyes csatornákon állandóan figyelik a vonalminőséget, és ha szükséges, megváltoztatják az adatsebességet, így a különböző csatornákon különböző lehet az átviteli sebesség. Az adatokat a valóságban az amplitúdó- és fázismoduláció kombinációjával továbbítják, így elérhetik a 15 bitet baudonként. Mondjuk, 224 lejövő csatornánál és 15 bit/baudnál, 4000 baud esetén a lejövő teljes sávszélesség 13,44 Mbps. A gyakorlatban a jel-zaj viszony sosem elég jó ahhoz, hogy ezt a sebességet el lehessen érni, de 4-8 Mbps elérhető, jó minőségű hurkokkal és rövid vezetékszakaszokkal.
93.
Egy tipikus ADSL-elrendezés látható a 2.39 ábrán. A diagram azt mutatja be, hogy a felhasználó vagy a telefontársaság szerelőjének egy hálózati interfészt kell felszerelnie az előfizető telephelyén. Ez a kis műanyag doboz jelöli a telefontársaság birtokának a végét és az előfizető birtokának a kezdetét. A hálózati interfészhez közel található a szétválasztó; ez egy analóg szűrő, amely leválasztja az adathálózatról a 0-4000 Hz-es sávot a POTS számára. A POTS jelet egy meglévő telefonra vagy telefaxra, az adatjeleket pedig egy ADSL-modemre irányítják. Az ADSL-modem tulajdonképpen egy digitális jelfeldolgozó eszköz, amely úgy van összekapcsolva, mintha 250 modem működne párhuzamosan különböző frekvenciákon. Mivel a legtöbb ADSL-modem külső, ezért a számítógépeket nagy sebességgel kell hozzákapcsolni. Általában ezt úgy oldják meg, hogy egy Ethernet-hálózati kártyát tesznek a számítógépbe, és egy két állomásból álló, nagyon kis hálózatot hoznak létre, amely csak a számítógépből és az ADSL-modemből áll. Néha USB portot használnak Ethernet-hálózat helyett. A jövőben belső ADSL-modemkártyák is lesznek, ehhez kétség sem férhet. A vezeték másik végén, a telefontársaság végpontján egy megfelelő szétválasztót kell felszerelni. A jel, hang részét itt is ki kell szűrni, és a normál telefonközpontba küldeni. A 26 KHz feletti jeleket egy újfajta készülékbe, a DSLAM-ba irányítják, ami ugyanolyan digitális jelfeldolgozó egység, mint az ADSL-modem. Amint a digitális jelekből a bitsorozatokat előállították, csomagokat alakítanak ki belőlük, és az itnernetszolgáltatóhoz küldik tovább. Kábeles internet Sok kábeltévé-társaság kínál manapság internet-hozzáférést kábelein keresztül. A kábelszolgáltatók minden városban fő telephellyel rendelkeznek, valamint rengeteg, elektronikával zsúfolt dobozzal szerte a működési területükön, amelyeket fejállomásoknak neveznek. A fejállomások nagy sávszélességű kábelekkel vagy üvegkábelekkel kapcsolódnak a fő telephelyhez. Minden fejállomásról egy vagy több kábel indul el, otthonok és irodák százain halad keresztül. Minden előfizető ehhez a kábelhez csatlakozik, ahol az átlépi az előfizető telephelyének határát. Így felhasználók százai osztoznak egy a fejállomáshoz vezető kábelen. Rendszerint a kábelek sávszélessége 750 MHz körül van. Bár a gyakorlatban egy saját 1,1 MHz sávszélességű csatorna nem nagyon különbözik a fejállomáshoz vezető kábel 200 MHz-es részének 400 felhasználó számára történő felosztásától, akiknek a fele nem használja a rendszert az adott pillanatban. Ez azonban azt jelenti, hogy hajnali 4 órakor jobb a kiszolgálás, mint délután 4-kor, míg az ADSL egész nap állandó. Azok, akik optimális kábeles internetszolgáltatásra vágynak, meggondolhatják, hogy gazdag vagy szegény környékre költözzenek. Amikor a kábeles internetet bevezették, a társaságoknak két problémát kellett megoldaniuk: 1. Hogyan bővítsék a rendszerüket az internetszolgáltatással úgy, hogy a tévéműsorok vételét ez ne befolyásolja? 2. Hogyan valósítsanak meg kétirányú forgalmat, amikor az erősítők alapvetően egyirányúak? A kiválasztott megoldás a következő. A modern kábelek jóval 550 MHz felett is működnek, gyakran 750 MHz-ig vagy még tovább. A feltöltésre szolgáló csatornák az 5-42 MHz sávban vannak, a letöltésre szolgáló csatornák forgalma a frekvenciatartomány felső részére esik, ahogyan az a 2.40 ábrán látszik.
94.
Vegyük észre, hogy a televíziójelek mind lejövő jelek, ezért lehetőség van arra, hogy a felmenő sáv erősítői pedig csak az 54 MHz-nél magasabb frekvenciákon, ahogyan ez az ábrán is látszik. A felmenő és a lejövő adatfolyam sávszélességében aszimmetria van, mivel a TV-sáv felett nagyobb frekvenciatartomány áll rendelkezésre, mint alatta. Másfelől viszont a forgalom nagyobb része valószínűleg letöltés, ezért a kábeltársaságok nem vették zokon ezt a körülményt. Ahogyan korábban láttuk, a telefontársaságok is aszimmetrikus DSL-szolgáltatást kínálnak, pedig ennek igazán nincs technikai indoka. Az internet-hozzáféréshez egy kábelmodemre van szükség, amelyben két interfész van, egyik a számítógéphez, a másik a kábeltévé-hálózathoz. A számítógép és a kábelmodem közötti interfész kézenfekvő. Ez általában egy Ethernet-kártya, mint az ADSL-nél. A jövőben lehetséges, hogy az egész modem a számítógépbe dugott kisméretű kártya lesz, éppúgy, mint a V9.x belső modemeknél. A kábelszabvány nagyobb része rádióelektronikával foglalkozik, ami jóval túlmutat e könyv keretein. Az egyetlen említésre méltó részlet, hogy a kábelmodemek ugyanúgy, mint az ADSLmodemek állandóan be vannak kapcsolva. Akkor veszik fel a kapcsolatot, amikor bekapcsolják, és folyamatosan kapcsolatban maradnak, amíg ki nem kapcsolják, mivel a kábeltársaságok nem a kapcsolat fennállásának ideje alapján számítják a díjat. A modem végigellenőrzi a lejövő csatornákat, és olyan speciális csomagokat keres, amelyeket a fejállomás periodikusan küld, és a rendszerparamétereket tartalmazzák az újonnan bekapcsolódó modemek számára. Amint a modem megtalálta ezt a csomagot, jelzi a jelenlétét az egyik felmenő csatornán. A fejállomás azzal válaszol, hogy kijelöli a modem felmenő és lejövő csatornáit. Ez a kijelölés később megváltozhat, ha a fejállomás a terhelés kiegyenlítése miatt szükségesnek ítéli. Ezután a modem meghatározza a fejállomástól mért távolságát egy speciális csomag küldésével, úgy, hogy leméri, mennyi ideig tart a válasz megérkdezése. Ezt a folyamatot távolsághatárolásnak hívják. A modem számára fontos, hogy tudja távolságát, hogy ehhez tudja igazítani a felmenő csatornák működtetését, és az időzítését helyesen állítsa be. Az adatforgalmat rövid idejű szeletekre, ún. minislotokra osztják. Minden lefelé haladó csomagnak egy vagy több minislotba kell beleférnie. A fejállomás ad jelet egy újabb minislot-periódusra, azonban a startpisztolyt nem egyszerre hallja meg minden modem a kábel mentén mért terjedési idő miatt. A modemek – ha tudják, milyen messze vannak a fejállomástól – ki tudják számítani, hogy valójában mennyi ideje indult el az előző minislot-periódus. A minislot hossza a hálózattól függ. A hasznos méret jellemzően 8 bájt. Az inicializálási fázisban a fejállomás minden egyes modem számára biztosít egy minislotot, amellyel felmenő sávszélességet kérhetnek. A szabály az, hogy több modemet is rendelhetnek ugyanahhoz a minislothoz, ami versenyhelyzetet teremt. Amikor a számítógép csomagot szeretne küldeni, a csomagot elküldi a modemhez, amely megkéri a szükséges számú minislotot a továbbításához. Ha a kérést a fejállomás elfogadta, nyugtázást küld a lejövő csatornán, és megadja, hogy mely minislotokat foglalta le a modem számára. Azután a modem elküldi a csomagot, kezdve az első lefoglalt minislottal. További csomagokat a fejlécben lévő mező használatával lehet kérni.
95.
A lejövő csatornákat a felmenő csatornáktól eltérően irányítják. Az első dolog, hogy csak egy küldő van, így nincs versenyhelyzet, és nincs szükség minislotokra, ami tulajdonképpen statisztikai alapú időosztásos multiplexelés. A másik, hogy a lejövő adatforgalom általában sokkal nagyobb, mint a felmenő, így rögzített, 204 bájt méretű csomagokat használnak. Ennek egy része egy ReedSolomon-féle hibajavító kód, és más járulékos dolgok, így a felhasználó számára 184 bájt hasznos adatmennyiség marad. Ezeket a számokat a MPEG-2 szabványú digitálistelevízió-szabvánnyal való kompatibilitás miatt választották, így a tévé és a lejövő csatornák formátuma azonos. A logikai kapcsolatokat a 2.41 ábra mutatja be. Visszatérve a modem inicializáláshoz, amint a modem behatárolta a távolságát, megkapta a felmenő és lejövő csatornáit, valamint a minislot-kiosztását, elkezdheti a csomagok küldését. Ezek a csomagok a fejállomáshoz futnak be, amely továbbítja egy dedikált csatornán a kábeltársaság fő telephelyére, majd az internetszolgáltatóhoz. Az internetszolgáltató felé menő első csomag a hálózaticím-kérés, amelyet dinamikusan osztanak ki. Le szokták kérdezni, és megküldik a napi pontos időt is. A következő lépés a biztonsághoz kötődik. Mivel a kábel osztott kommunikációs lehetőség, bárki bajba kerülhet azáltal, hogy valaki más elolvassa a rajta keresztülhaladó forgalmat. Annak megakadályozására, hogy mindenki a szomszédjai után szimatoljon, a forgalom mindkét irányban titkosított. Végül, a modemnek be kell jelentkeznie, és meg kell adnia saját egyedi azonosítóját a titkos csatornán. Ekkor az inicializálás véget ér. A felhasználó bejelentkezhet az ISP-hez, és elkezdhet dolgozni.
96.
37. Az Intel 8086/88 utasításai (adatmozgató, aritmetikai, logikai, string-kezelő, bitléptető/forgató, vezérlésátadó, processzorvezérlő, input/output utasítások, program megszakítás, szemafor). Adatmozgató utasítások Az adatmozgató ut. értékadásra valók. Nem változtatják a flagek értékét, kivéve a POPF. MOV XCHG XLAT LEA LES LDS PUSH PUSHF POP POPF
op1, op2 op1, op2 reg, mem reg, mem reg, mem reg reg
op1 = op2 értékadás op1 és op2 értéke kicserélődik ugyanaz, mint MOV AL, [BX + AL] ugyanaz, mint MOV reg, OFFSET mem MOV reg, *mem+ és MOV ES, *mem + 2+ MOV reg, [mem+ és MOV DS, *mem + 2+ SP = SP -2, MOV [SP], reg SP = SP -2, SR (FLAGS) bekerül a verembe a verem felső szavát teszi reg-be, SP = SP + 2 a verem felső szavát teszi SR-be, SP = SP + 2
Aritmetikai utasítások Az aritmetikai utasítások egyszerű számolási műveleteket hajtanak végre. Ahol lehetséges, célszerű az AX regiszterrel számolni, mivel az gyorsabb, mint a többi. Az ún. aritmetikai flageket (C, Z, S, A, O, P) beállítják ezek a műveletek. ADD ADC SUB SBB MUL
op1, op2 op1, op2 op1, op2 op1, op2 op1
IMUL DIV
op1 op1
IDIV INC DEC NEG CMP CBW CWD
op1 op1 op1 op1 op1, op2
op1 = op1 + op2 op1 = op1 + op2 + C(arry) op1 = op1 – op2 op1 = op1 – op2 – C(arry) AX = AL · op1 ha op1 8-bites előjel nélküli érték DX:AX = AX · op1, ha op1 16-bites előjel nélküli érték ua. mint MUL, csak előjeles értékekkel számol AL = AX / op1, ha op1 8-bites előjel nélküli egész AX = DX:AX / op1, ha op1 16-bites előjel nélküli egész ua. mint DIV, csak előjeles értékekkel számol op1 = op1 + 1 (nem változtatja a Carry flaget) op1 = op1 – 1 (nem változtatja a Carry flaget) op1 = – op1, kettes komplemens képzése flagek beállítása op1 – op2 értéke alapján AX = AL, kiterjesztés 16-bitre előjellel együtt DX:AX = AX, kiterjesztés 32-bitre előjellel együtt
97.
Vezérlésátadó utasítások A vezérlésátadó utasításokkal feltételes vagy feltétel nélküli ugrást, eljárás- és függvényhívást tudunk kezdeményezni. Az ugrás tulajdonképpen nem más, mint a CS:IP regiszter párnak a következő utasítás címére beállítása. Háromféle ugrást különböztetünk meg attól függően, hogy az operandus milyen hosszú. A SHORT ugrásnál IP új értéke az IP – 128 és IP + 127 között változhat, CS változatlan (8 bites, előjeles operandus). NEAR ugrásnál IP értéke tetszőlegesen változhat, CS változatlan (16 bites operandus). FAR ugrásnál mind CS, mind az IP értéken tetszőlegesen változhat (2x16 bites operandus, far pointer). JMP Jxx
op1 short ptr
feltétel nélküli ugrás a megadott címre (short, near, far) feltételes ugrás a megadott flag értéke szerint (short)
Lehetséges feltételek: C flag szerint: Z flag szerint: S flag szerint: O flag szerint: P flag szerint: CMP A, B utasítás után: A > B esetén: A ≤ B esetén: A > B esetén: A < B esetén: A ≥ B esetén: A ≤ B esetén:
Flag = 1 JC ≡ JB ≡ JNAE JZ ≡ JE JS JO JP ≡ JPE
Flag = 0 JNC ≡ JNB ≡ JAE JNZ ≡ JNE JNS JNO JNP ≡ JPO
JA ≡ JNBE JNA ≡ JBE JG ≡ JNLE JL ≡ JNGE JGE ≡ JNL JLE ≡ JNG
(C = 0 és Z = 0), előjel nélküli számoknál (C = 1 vagy Z = 1), előjel nélküli számoknál (Z = 0 és S = O), előjeles (S ≠ O flag), előjeles (S = O flag), előjeles (Z = 1 vagy S ≠ O), előjeles
JCXZ CALL
feltételes ugrás, ha CX = 0 eljáráshívás: PUSH IP majd JMP címke (near) ill. PUSH CS, PUSH IP, JMP címke (far) visszatérés közeli eljárásból: POP IP-vel egyenértékő visszatérés távoli eljárásból: POP IP, POP CS
címke címke
RET RETF Ciklus-szervező utasítások
A ciklus-szervező utasítások minden esetben CX értékét veszik figyelembe. Mindegyik utasítás csökkenti eggyel CX értékét, és ha az eredmény nulla, akkor vége a ciklusnak. Nagyjából egyenértékű a for(CX;CX>1;CX--) utasítással. Az operandusban megadott ugrás SHORT lehet csak (-128…+127). LOOP LOOPZ LOOPNZ LOOPE LOOPNE
címke címke címke címke címke
CX = CX – 1, ha CX ≠ 0 ugrás a címkére CX = CX – 1, ha CX ≠ 0 és Z flag = 1 ugrás a címkére CX = CX – 1, ha CX ≠ 0 és Z flag = 0 ugrás a címkére ua. mint LOOPZ ua. mint LOOPNE
98.
Logikai utasítások A logikai utasítások az operandusok között bitenkénti szabványos logikai műveletek megvalósításai. Az eredmény az első operandusba kerül a TEST utasítás kivételével, ahol értékük változatlan. Emellett természetesen mindegyiknél a megfelelő aritmetikai flagek is beállítódnak. AND TEST OR XOR NOT
op1, op2 op1, op2 o1p, op2 op1, op2 op1
op1 = op1 & op2, logikai ÉS művelet op1 & op2 értéke alapján beállítja a flageket op1 = op1 | op2, logikai VAGY művelet op1 = op1 + op2, logikai KIZÁRÓ VAGY művelet op1 = ≦op1, logikai negáció (egyes komplemens)
String-kezelő utasítások Ezek az utasítások a memóriában bájtsorozatokkal (stringekkel) kapcsolatos műveleteket valósítanak meg (másolás, kiolvasás, beírás, keresés). Mindig DS:SI által mutatott címről olvasnak, és az ES:DI címre írnak. Az utasítástól függően SI ill. DI regiszterek értéke 1 (Byte) ill. 2 (Word)-vel változik. Ha D (Direction = irány) flag 1, akkor növekszik, ha 0, csökken ennyivel. Létezik mindegyik utasításnak típus nélküli változata is (nincs a végén B vagy W), ekkor a megadott operandus mérete mondja meg, hogy melyik változatot kell használni. Ha ez nem dönthető el egyértelműen, akkor az assembler fordítási hibát ad, emiatt ill. az átláthatóság érdekében ezek használata kerülendő! Az ismétlő prefixumokat string-kezelő utasítások előtt használhatjuk, azokkal együttesen. Segítségükkel gyorsan végigmehetünk egy teljes stringen, minden elemre végrehajtva a kívánt műveletet. Az összes ismétlés CX-szer hajtódik legfeljebb végre, hasonlóan a LOOP utasításhoz, annyi különbséggel, hogy itt előbb megnézi a processzor, hogy CX = 0 teljesül-e, és csak az utasítás végrehajtása után csökkenti eggyel (azaz CX = 0 esetén egyszer sem hajtódik végre az utasítás). Ebből az is következik, hogy ha szabályosan végigfut egy ismétlési ciklus, akkor CX = 0 lesz. MOVS MOVSB MOVSW LODS LODSB LODSW STOS STOSB STOSW CMPS CMPSB CMPSW SCAS SCASB SCASW REP
op1
op1
op1
op1
op1
nem szerencsés, ua. mint MOVSB vagy MOVSW MOV ES:*DI+, DS:*SI+, és SI = SI ± 1, DI = DI ± 1 MOV ES:*DI+, DS:*SI+, és SI = SI ± 2, DI = DI ± 2 nem szerencsés, ua. mint LODSB vagy LODSW MOV AL, DS:[SI], és SI = SI ± 1 (D flagtől függően) MOV AX, DS:*SI+, és SI = SI ± 2 (D flagtől függően) nem szerencsés, ua. mint STOSB vagy STOSW MOV ES:[DI], AL és DI = DI ± 1 (D flagtől függően) MOV ES:[DI], AX és DI = DI ± 2 (D flagtől függően) nem szerencsés, ua. mint CMPSB vagy CMPSW CMP DS:*SI+, ES:*DI+ és SI = SI ± 1, DI = DI ± 1 CMP DS:*SI+, ES:*DI+ és SI = SI ± 2, DI = DI ± 2 nem szerencsés, ua. mint SCASB vagy SCASW CMP AL, ES:[DI] és SI = SI ± 1 (D flagtől függően) CMP AX, ES:*DI+ és SI = SI ± 2 (D flagtől függően) fenti 5 féle utasítás ismétlése legfeljebb CX-szer
99.
REPZ REPNZ REPE REPNE
ismétlés legfeljebb CX-szer, ha Z flag értéke 1 ismétlés legfeljebb CX-szer, ha Z flag értéke 0 ua. mint REPZ ua. mint REPNZ
Bitforgató utasítások Az érték vagy konstans 1, vagy a CL regiszter (286-os géptől felfelé megadhatunk 1-nél nagyobb konstanst is). RCL
reg, érték
RCR
reg, érték
ROL
reg, érték
ROR
reg, érték
SHR
reg, érték
SHL
reg, érték
SAR
reg, érték
SAL
reg, érték
forgatás balra, reg minden bitje eggyel balra tolódik, 0. bitbe C íródik, C felveszi a legmagasabb bit értékét forgatás jobbra, reg minden bitje eggyel jobbra tolódik, legmagasabb bitbe C íródik, C felveszi a 0. bit értékét forgatás balra, reg minden bitje eggyel balra tolódik, 0. bitbe és C flagbe a legmagasabb bit értéke kerül forgatás jobbra, reg minden bitje eggyel jobbra tolódik, legmagasabb bitbe és C flagbe a 0. bit értéke kerül eltolás jobbra, reg minden bitje eggyel jobbra tolódik, legmagasabb bitbe 0 érték kerül, 0. bit a C flagbe íródik eltolás balra, reg minden bitje eggyel balra tolódik, 0. bitbe 0 érték kerül, legmagasabb bit a C flagbe íródik eltolás jobbra, reg minden bitje eggyel jobbra tolódik, legmagasabb bit nem változik, 0. bit a C flagbe íródik ua. mint SHL
Processzor-vezérlő utasítások A processzor-vezérlő utasítások egy része a flageket állítja direktben, másik részük egyéb közvetlen utasítást ad a CPU részére. A flageket, a leírt hatáson kívül nem változtatják. CLC STC CMC CLD STD CLI STI NOP WAIT HLT
C flaget törli (C = 0) C flaget beállítja (C = 1) C flaget negálja (C = 1 – C) D flaget törli (D = 0), csökkenı irányú string-műveletek D flaget beállítja (D = 1), növekvő irányú string-műveletek I flaget törli (I = 0), megszakítások tiltása I flaget beállítja (I = 1), megszakítások engedélyezése CPU nem csinál semmit egy ideig ( ≡ XCHG AL, AL) CPU várakozik, amíg a koprocesszor kész nem lesz CPU leáll, amíg hardveres megszakítás jelet nem kap
100.
Input/Output utasítások Külső eszközökkel kommunikálhat a CPU, az ún. portokon keresztül. A port értéke egy 0-255 közé eső konkrét szám lehet. Ha ennél nagyobb sorszámú portot akarunk elérni, akkor a port helyére DX regisztert kell beírni (a port sorszáma természetesen ekkor DX-ben van). A művelethez kizárólag AX és AL regiszterek használhatóak, attól függően, hogy 2 vagy 1 bájtot mozgatunk. IN OUT
accum, port port, accum
beolvas 1 vagy 2 bájtot AL/AX-be a megadott portról kiírja az AL/AX-ben lévő értéket a megadott portra
Program-megszakítás A (program)-megszakítás azt jelenti, hogy az éppen futó program végrehajtása átmenetileg megszakad – a processzor állapota megőrződik, hogy a program egy késöbbi időpontban folytatódhassék – és a processzor egy másik program, az úgy nevezett megszakító rutin végrehajtását kezdi meg. A megszakító rutin, miután elvégezte munkáját, gondoskodik a processzor megszakításkori állapotának visszaállításáról, és visszaadja a vezérlést a megszakító programnak. Általánosítás: A központi egységnek több állapota van, és bizonyos utasítások csak a központi egységnek bizonyos kitüntetett (privilegizált) állapotában hajthatók végre, alap állapotban nem. Megoldás: Szoftver megszakítás. Az utasítások bizonyos csoportja, a memória meghatározott részei, a hardver egyes elemei csak a processzor kitüntetett állapotában érhetők el. A processzor (szoftver) megszakítást eredményező utasítással juttatható a kívánt állapotba. Ilyenkor az operációs rendszer egy meghatározott programja kapja meg a vezérlést. Ennek módjában áll a kívánság „jogosságának” ellenőrzése. Jogtalan kívánság, vagy nem kitüntetett állapotban történő kísérlet esetén – ami szintén megszakítást eredményezhet, tehát szintén az operációs rendszer kapja meg a vezérlést – az operációs rendszernek módjában áll a program további működését beszüntetni. Több ok okozhat megszakítást. Az Intel 8088 processzor esetén a megszakítási okokat 0 és 255 közé eső i számmal jellemezhetjük. Az i. megszakítási okhoz tartozó megszakító rutin FAR címe a memória 4*i címén található. A megszakítás esetén a hardver egység installáláskor adott száma, szoftver megszakítás esetén az operandus rész szolgáltatja. Interrupt utasítások: Az interrupt (megszakítás) kezelő utasításokkal saját, vagy beépített eljárásokat hívhatunk meg. Ezek egy része akkor fut le, ha egy hardver eszköz megszakítás-jelet küld a CPU-nak (pl. leütöttek egy billentyűt), más részüket a rendszer és mi használjuk programon belül (pl. BIOS rutinok). A megszakítások sorszáma 0 – 255 között lehet, és a 0000h:*4*sorszám+ helyen lévő távoli címen vannak megvalósítva.
101.
INT
sorszám
megszakítás hívása, interrupt táblában lévő cím szerint: PUSHF, CALL far ptr 0000h:[4*sorszám+ egymás után INT 4 hívása, ha az O flag értéke 1 visszatérés megszakításból (RETF, POPF egymás után)
INTO IRET Szemafor
Multiprogramozásos környezetben gyakran előfordul, hogy ugyanazt az erőforrást (pl. nyomtató) egyidejüleg több program is szeretné használni. Erre természetesen nincs lehetőség, ezért biztosítani kell, hogy egyidejüleg legfeljebb egy program használhassa az illető erőforrást. Szemafornak nevezzük azt a jelzést, amely megmutatja, hogy az erőforrást használja-e pillanatnyilag valamely program. Legyen az S szemafor egy olyan word típusú változó, amely mindegyik program számára elérhető. Jelentse S=0 azt, hogy az erőforrás szabad, és S≠0 azt, hogy az erőforrás foglalt. Próbáljuk meg a szemafor kezelését! A megoldás a következő: ujra:
szabad:
MOV XCHG JCXZ … jmp …
CX,S szabad
CX,0FFFH ;már foglaltat jelez a szemafor! ;ellenőrzés S korábbi tartalma szerint ;foglalt volt az erőforrás, várakozás
ujra ;szabad volt az erőforrás, ;de a szemafor már foglalt
Több processzoros rendszer esetén elképzelhető, hogy az egyik processzor éppen végrehajtotta az első mikroutasítást, amikor egy másik processzor is ugyanezt az utasítást kívánja végrehajtani. Ekkor ugyanúgy, mint az előző kísérletnél a LOCK prefixum segítségével tudjuk megadni. ujra:
szabad
MOV LOCK XCHG JCXZ szabad … jmp ujra …
CX,0FFFFH CX,S ;S már foglaltat jelez ;ellenőrzés S korábbi tartalma szerint ;foglalt az erőforrás, várakozás ;használható az erőforrás, ;de a szemafor már foglalt
Ha a programnak nincs szüksége tovább a korábban lefoglalt erőforrásra, akkor ezt a szemafor szabadra állításával jelezheti. A szemafor szabadra állítása a közönséges MOV
S,
0
utasítással történhet.
102.
38. Pszeudo operátorok. Egyszerű adatdefiníciós utasítások. Struktúra, rekord (definíció, hívás, mezőre hivatkozás) A pszeudo utasítások nem valódi utasítások, abban az esetben, hogy ezeket a lefordított program a futás során nem fogja végrehajtani (ilyenek pl. az adatdefiníciós utasítások), bizonyos esetekben nem is kerülnek bele a lefordított programba. A pszeudo utasításokat a fordítóprogram hajtja végre. Ez a végrehajtás fordítás közbeni tevékenységet vagy a fordításhoz szükséges információ gyűjtést jelenthet. Adatdefiníciós utasítások Az adatokat általában külön szegmensben szokás és javasolt definiálni. A kezdőértékkel ellátott változók a program betöltésekor a megadott értékkel rendelkeznek, de a program futása során változhatnak. Erre különösen akkor kell tekintettel lennünk, ha a programot egyszeri betöltés után többször is el akarjuk indítani. Az adatdefiníciós utasítások elé általában azonosítót (változó név) írunk, hogy hivatkozhassunk az illető adatra. Egy-egy adatdefiníciós utasítással több azonos típusú adatot is definiálhatunk. A kezdő érték tetszőleges konstans (szám, szöveg, cím...) kifejezés lehet. Ha nem akarunk kezdőértéket adni, akkor ?-et kell írnunk. A szöveg és a karakter konstansokat "-k vagy '-k között adhatjuk meg. Egyszerű adatdefiníciós utasítások Define Byte (db): Az operandus lehet numerikus, karakter vagy szöveg. Pl.: Adat1 Adat2 Adat3 Kar Szoveg Szoveg1
db db db db db db
25 1,2 5 dub (?) ’a’,’b’,’c’ ’Ez egy szöveg’,13,OAH ’Ez is ”szöveg”’,”és ez is ’szöveg’”
;1 byte, kezdőértéke decimális 25 ;2 byte (nem egy szó) ;5 inicializálatlan byte ;3 ASCII kódú karakter ;ASCII kódú szöveg, és 2 szám
Vegyesen is előfordulhatnak egy utasításban. Define Word (dw): Az operandus lehet numerikus, cím, karakter vagy 2 karakteres szöveg. Pl.: Szo dw Szo_cime dw
0742H, 452 szo
;szo OFFSET címe
Define Double (dd): Az oprandus lehet numerikus, távoli cím (segment és offset cím), karakter vagy maximum 4 karakteres szöveg. Tipikus alkalmazásai: Távoli címek tárolására a stringkezelő utasítások előkésítéséhez az LDS és az LES utasítás operandusként, vagy távoli eljárások indirekt hívásához. Pl.: Szo_f
dd
szo
;szo távoli (segment+offset) címe
Define Quadword (dq): Dupla pontosságú (4 szavas) lebegőpontos számok, változók számára történő helyfoglalásra használatos. Define Ten bytes (dt): 10 byte-on tárolt 10 jegyű pakolatlan vagy 20 jegyű pakolt decimális számok, változók számára történő helyfoglalásra használatos.
103.
Összetett adatdefiníciós utasítások Programozás során sokszor előnyös, ha több – esetleg eltérő típusú – adatot egységesen tudunk kezelni. Assembly-ben ezt a lehetőséget a struktúra és a rekord biztosítja. A struktúra ill rekord elemi részeit mezőknek (field) nevezzük. Struktúra Csak a struktúra típusát definiálja a későbbi struktúra-hívások számára, ezért a memóriában nem jár helyfoglalással. Str_típus Str_típus
STRUC ... ENDS
;struktúra (típus) definíció ;mező (field) definíciók, egyszerű adatdefiníciós utasítások ;struktúra definíció vége
A mező (field) definíció csak egyszerű adatdefiníciós utasítással történhet, ezért a struktúra mező nem lehet másik struktúra vagy rekord. A mezők definiálásakor megadott értékek kezdőértékül szolgálnak a későbiekben történő struktúra hívásokhoz. A definícióban megadott kezdőértékek közül azoknak a mezőknek a kezdőértéke híváskor felülbírálható, amelyek csak egyetlen adatot tartalmaznak (a szöveg konstans annak minősül). Pl.: S F1 F2 F3 F4 F5 S
STRUC db db db db db ENDS
1,2 10 dup(?) 5 ’a’,’b’,’c’ ’abc’
;struktúra (típus) definíció ;nem lehet felülírni ;nem lehet felülírni ;felülírható ;nem lehet felülírni ;felülírható
Struktúra hívás A struktúra definíciójánál a megadott str_típus névnek a műveleti kód részen történő szerepeltetésével hozhatunk létre struktúra változókat. A kezdőértékek fölülbírálása a kívánt érték <> közötti felsorolásával történik. A egyes mezők kezdőértékeit vesszővel választjuk el. Ha egy mezőnek a kezdőértékét nem kívánjuk megadni vagy nem adhatjuk meg akkor is ki kell írjuk a vesszőt, kivéve ha egyiknek sem kívánunk eltérő kezdőértéket adni. S1 S2 S3
S S<,,7,,’FG’> S<,,’A’>
;kezdőértékek a def-ből ;F3 kezdőértéke 7, F5-é ’FG’ ;F3 kezdőértéke ’A’, F5-é a definícióból
Struktúra mezőre hivatkozás A struktúra változó névhez tartozó OFFSET cím a struktúra OFFSET címét, míg a mező név a struktúrán belüli címet jelenti. A struktúra adott mezejére úgy hivatkozunk, hogy a struktúra és mező néve közé pontot írunk. Pl.: MOV AL,S1.F3 A mezőnevek szükségképpen egyedi nevek, tehát sem másik struktúra definícióban, sem közönséges változóként nem szerepelhet.
104.
Rekord Rekordon olyan 1 vagy 2 byte-os összetett adatot értünk, melynek meghatározott szomszédos bitsorozatai logikai egységet alkotnak. Ezeket a logikai egységeket mezőknek (field) nevezzük. Olyan esetben válhat hasznunkra a rekord, amikor egy vagy két byte-os adatokat bitcsoportonként kell kezelnünk, ami leggyakrabban driver-ek írásakor fordul elő. Rekord definíció Csak a rekord típusát definiálja a későbbi rekordhívások számára. Rec_típus RECORD mező specifikáció ahol az egyes mező specifikációkat vesszővel választjuk el. Maga a mező-specifikáció: mező_név: szélesség=kezdőérték a szélesség a mező bitjeinek száma. A kezdőérték el is maradhat, pl.: R RECORD x:3,y:4=15,z:5 Az R rekord szavas (12 bit), a következőképpen helyezkedik el egy szóban: x
x
x
y
y
y
y
z
z
z
z
z
Rekord hívás A rekord definíciójánál megadott Rec_típus névnek a műveleti kód részén történő szerepeltetésével hozhatunk létre rekord változókat. A kezdőértékek fölülbírálása a kívánt értékek <> közötti felsorolással történik. Az egyes mezők kezdőértékeit vesszővel választjuk el. Ha egy mezőnek a kezdőértékét nem kívánjuk megadni, akkor is ki kell írjuk a vesszőt, kivéve, ha egyiknek sem kívánunk eltérő kezdőértéket adni. R1 R2 R3
R R R
<> <,,7> <1,2>
;01E0H, kezdőértékek a def-ből ;01E7H,x,y kezdőértéke a def-ből, z-é 7 ;0240H,x kezdőértéke 1, y-é 2, z-é a def-ből
Rekordból vektort is előállíthatunk. Pl.: R_vektor
R
5 dup (<1,2,3>)
;0243H, 5 elemű rekord vektor
Rekordmezőre hivatkozás A mezőnév olyan konstansként használható, amely azt mondja meg, hány bittel kell jobbra léptetnünk a rekordot, hogy a kérdéses mező az 1-es helyértékre kerüljön. További segítség a MASK operátor, melyet a mező név elé írva olyan konstanst kapunk, amely az illető mezőhöz tartozó biteket 1, a többi biten 0. NOT MASK ennek a bitenkénti negáltja.
105.
39. Eljárás (deklaráció, hívás). Paraméter átadás/átvétel különböző módjai. Tegyük fel hogy például egy olyan programot szeretnénk csinálni, amely két vektor skaláris szorzatát számolja ki. Ez még nem is tűnik annyira bonyolultnak. De ha többször is el szeretnénk ezt végeztetni, akkor a többszöri utasítássorozat begépelése helyett eljárásokkal oldhatjuk meg. Eljárás deklaráció Az eljárásnak a program egy Elj_név
PROC
típus
pszeudo utasítással kezdődő (ez az eljárás belépési pontja), és Elj_név
ENDP
utasítással végződő szakaszt értjük. Az Elj_név az eljárás neve, típus az eljárás típusa, amely lehet NEAR vagy FAR. Eljárás hívására a CALL utasítás szolgál. Ilyenkor verembe helyezi az IP ill. ha FAR akkor IP és CS tartalmát, és átadja a vezérlést a meghívott eljárásnak. Az eljárásból a RET utasítással térhetünk vissza a CALL utasítás mögé. Ilyenkor a RET kiolvassa a veremből az IP ill. IP és CS tartalmát és visszatér a hívás utáni utasításhoz. A paraméterek regiszterekben történő átadása A skaláris adatokat szokásos érték szerint átadni, az összetett adatokat pedig cim szerint. mov xor mov mov
cl,n ch,ch si,OFFSET a di,OFFSET b
n a b
db db db
Ahol 3 1,2,3 3,2,1
Az érték szerinti paraméter átadásnál a hívott program nem tudja módosítani a paraméter értékét. Ez részben előny, mert nem tudja elrontani, de részben hátrány is, mert néha jó lenne, ha módosítani tudná. Ilyenkor cím szerint kell átadni a paramétert. A paraméterek veremben történő átadása A regiszeterekben történő paraméter átadásnál erősen kihasználtuk azt, hogy elegendő regiszter áll rendelkezésünkre. Ez általában nem tejesül. Ilyenkor a verembe tároljuk adatainkat. Ezt persze olyankor is megtehetjük, amikor elegendő regiszterünk lenne a paraméterek átadására. Ekkor ez igy nézne ki:
106.
mov xor push mov push mov push call
al,n ah,ah ax ax,OFFSET a ax ax,OFFSET b ax ...
Ilyenkor a verem így fog kinézni (SS:SP) visszatérési cím +2 +4 +6
b címe a címe n értéke
Az eljárás elején általában célszerű a regiszterek verembe tárolása, és a végén onnan veló kivétele (persze fordított sorrendben). Erre azért van szükség, hogy ne veszítsük el semmi adatot amivel dolgoztunk a programban. A paraméterek kiürítését a veremből például a ret
6
utasítással oldhatjuk meg, ahol az eljárásból való kilépéskor 6-tal megnöveli az SP-t és a veremben a visszatérési cim utánni 3 paramétert kivesz. Ez még úgy is megoldható, hogy a hívás után add
sp,6
utasítást írunk. Ez is szimplán megnöveli az SP-t 6-tal és kivesz 3 paramétert.
107.
40. Lokális adatterület, rekurzív és reentrant eljárások. Lokális adatterület Ha egy eljárás működéséhez lokális adatterületre, munkaterületre van szükség, és a működés befejezetével a munkaterület tartalma felesleges, akkor a munkaterületet célszerűen a veremben alakíthatjuk ki. A munkaterület lefoglalásának ajánlott módja: . . . proc . . . PUSH BP MOV BP,SP SUB SP,n ...
; BP értékének mentése ; BP SP, ; a stack relatív címzéshez ; n a munkaterület byte-jainak száma ; további regiszter mentések
A munkaterület negatív displacement érték mellet stack relatív címzéssel érhető el. (A verembe elhelyezett paraméterek ugyancsak stack relatív címzéssel, de pozitív displacement érték mellet érhetőek el.) A munkaterület felszabadítása visszatéréskor a ... ; visszamentések MOV SP,BP ; a munkaterület felszabadítása POP BP ; BP értékének visszamentése ret . . . ; visszatérés utasításokkal történhet. Rekurzív és reentrant eljárások Egy eljárás rekurzív, ha önmagát hívja közvetlenül, vagy más eljárásokon keresztül. Egy eljárás reentrant, ha többszöri belépést tesz lehetővé, ami azt jelenti, hogy az eljárás még nem fejeződött be, amikor újra meghívható. A rekurzív eljárással szemben a különbség az, hogy a rekurzív eljárásban „programozott”, hogy mikor történik az eljárás újrahívása, reentrant eljárás esetén az esetleges újrahívás ideje a véletlentől függ. Ez utóbbi esetben azt, hogy a munkaterületek ne keveredjenek össze, az biztosítja, hogy újabb belépés csak másik processzusból képzelhető el, és minden processzus saját vermet használ. Ha egy eljárásunk készítésekor betartjuk, hogy az eljárás a paramétereit a vermen keresztül kapja, kilépéskor visszaállítja a belépéskori regiszter-tartalmakat – az esetleg eredményt tartalmazó regiszterek kivételével –, továbbá a fenti módon kialakított munkaterületet használ, akkor az eljárásunk rekurzív is lehet, és a többszöri belépést is lehetővé teszi (reentrant).
108.
41. Feltételes fordítás Feltételes fordításra az assembler is képes. Ez tulajdonképpen ugyanaz, mint amit ProgAlapon tanultunk. El tudjuk érni, hogy a programkód egyes részeit a forditóprogram (jelen esetben az assembler) ne forditsa le. Ez különösen akkor lehet előnyös, ha pl. hibajakeresés céljából a programban több helyen elhelyeztünk egy parancsot, amely kiirja az eredményt a képernyőre vagy a nyomtatóra. Természetesen a végleges programban ezek a kiirások nem szerepelnek, vagyis valahogy el kell érnünk, hogy a forditóprogram ne forditsa le. Ez lehetséges úgy, hogy egyenként kitöröljük őket (akár mind a 432 darabot), ezzel azonban az a baj, hogy ha véletlenül továbbra is hibás a program, egyenként kell őket visszairni. Ugyanez a helyzet a kommentezéssel is. Ehelyett inkább olyan megoldást kell keresnünk, amely lehetővé teszi, hogy az általunk kiválasztott dolgokról a forditáskor megmondjuk, benne legyenek-e a forditott kódban, vagy sem. Ez a feltételes forditás. A feltételes forditás általános szerkezete: IFxx feltétel ... ELSE ... ENDIF
; lefordul, ha a feltétel igaz ; ez az ág nem kötelező ; lefordul, ha a feltétel hamis
A fenti példában xx-t helyettesitve a megfelelő kulcsszavakkal megkapjuk a következő táblázatot: IF kifejezés IFE kifejezés IF1 IF2 IFDEF Szimbólum IFNDEF Szimbólum IFB <arg> IFNB <arg> IFIDN <arg1>,<arg2> IFDIF <arg1>,<arg2>
; igaz, ha a kifejezés nem 0 ; igaz, ha kifejezés 0 ; igaz a forditás első menetében ; igaz a forditás második menetében ; igaz, ha Szimbólum definiált ; igaz, ha Szimbólumnem definiált ; igaz, ha arg üres (blank) ; igaz, ha arg nem üres ; igaz, ha arg1=arg2 ; igaz, ha arg1=arg2 nem teljesül
109.
42. Makró (definíció, hívás), blokk ismétlés Makró Az eljárások előnye, hogy csak egyszer kell megírnunk az illető részfeladatot megoldó eljárást, a továbbiak során elegendő a paraméterek megfelelő beállítása után felhívnunk ezt az eljárást. Maga az eljárás csak egyszer szerepel a programban. Kimutatkozik az eljárások hátránya, ha az eljárás maga egyszerű, de sok paramétert használ, mert ilyenkor a paraméterek átadása összemérhető magával az eljárás végrehajtásával. A paraméterek átadása minden hívásnál terheli a memóriát és a futási időt is. Többek között ilyen esetekben nyújt hatékony megoldást a makró. Makrók használatával kapcsolatban meg kell különböztessük a makró definíciót és a makró hívást. Makró definíció: M_név …
MACRO
*fpar1+,*fpar2+…
ENDM
;makró fej (kezdet) ;makró törzse ;makró vége
A makró fejben megadott *fpar1+,*fpar2+…-t formális paramétereknek, vagy egyszerűen paramétereknek szokás nevezni. A makró definíció nem lesz része a lefordított programnak, csupán azt határozza meg, hogy később mit kell a makró hívás helyére beírni (makró kifejtés, helyettesítés). A makró törzsén belül előfordulhat makró hívás és makró definíció is. Makró hívás: M_név
*apar1+,*apar2+…
A makró hívásában megadott *apar1+,*apar2+…-t aktuális paramétereknek vagy argumentumoknak szokás nevezni. A műveleti kód helyére írt M_név hatására a korábban megadott definíció szerint megtörténik a makró helyettesítés, más néven makró kifejtés. Ez a makró törzs bemásolását jelenti, miközben az összes paraméter összes előfordulása a megfelelő argumentummal helyettesítődik. A helyettesítés szövegesen történik, azaz minden paraméter – mint szöveg – helyére a megfelelő argumentum – mint szöveg – kerül. A helyettesítés nem rekurzív, és argumentuma sem lehet makró hívás, csak egyszerű szöveg, de az argumentumnak megfelelő formális paraméternek lehet olyan előfordulása, amely a későbbiekben makró hívást eredményez. Példaként legyen a programban gyakran előforduló részfeladat a dupla szavas összeadás. Makró definíció:
MDADD
Makró hívás:
MDADD
MACRO ADD AX,BX ADC DX,CX ENDM
110.
Fordítás közben MDADD definíciója szerint, megtörténik a makró helyettesítése, és a program-szöveg részévé válik: ADD AX,BX ADC DX,CX Futás közben csak ez a két utasítás kerül végrehajtásra. Paraméter nemcsak operandus részen fordulhat elő a makró törzsében, hanem másutt is, pl.: PL
MACRO MOV P2 ENDM
P1,P2 AX,P1 P1
makró definíció esetén a PL
Adat, INC
MOV INC
AX,Adat Adat
makró hívás a
utasításokra cserélődik. A &, %, ! karakterek továbbá a <> és ;; speciális szerepet töltenek be makró kifejtéskor. &: Előfordulhat, hogy azt szeretnénk, hogy makró kifejtéskor a paraméter – helyettesített – értéke része legyen egy szónak. Ezt a & karakterrel oldhatjuk meg. A makró generátor az & karakter mindkét oldalát megvizsgálja, hogy ott paraméter szerepel-e. Ha igen, elvégzi a paraméter helyettesítését, és mindenképpen elhagyja az & jelet. Pl.: UGRIK
MACRO J&Felt ENDM
Felt, Címke Felt&Címke
UGRIK
Z,Alfa
A hívás, pl.:
Ennek kifejtése: JZ
Zalfa
%: Az utána szereplő paraméter értékének számjegyek sorozatává alakítását írja elő. S ErrMsg S
= MACRO = MSG
0 text s+1 %s,text 111.
Msg Msg&sz
ENDM MACRO db ENDM
sz,str str
Az ErrMsg
’syntax error’
makró hívás hatására az msg1
db
’syntax error’
adatfoglaló utasítás !: Az utána következő karakter változatlanul kerül bemásolásra. Lehetőséget ad arra, hogy pl. az & jelet a kifejtett makró szövegében szerepelhessen. <>: Ha aktuális paraméterként olyan szöveget kívánunk megadni, amely pl. ,-t tartalmaz, akkor ezt <> jelek között tehetjük meg. Pl az adat
macro db endm
p p
makró definíció esetén az adat
<’abc’,13,10,0>
db
’abc’,13,10,0
hívás kifejtve:
míg ezzel szemben az adat
’abc’,13,10,0
db
’abc’
kifejtve
;;: A makró definíció megjegyzéseinek kezdetét jelzi. A ;; utáni megjegyzés nem jelenik meg a programlistában. Ha makró egyes részeihez címkét szeretnénk rendelni, és a makró többször is meghívjuk, akkor hibajelzést kapunk. Az ilyen hiba elkerülésére használjuk a LOCAL utasítást. LOCAL
c1*,c2…+
112.
c1*,c2…+ minden makró hívásnál más, ??xxxx alakú szimbólumra cserélődik, ahol xxxx a makró generátor által meghatározott hexadecimális szám. A LOCAL operátort közvetlenül a makró fej utáni sorba kell írni. Makró definíció belsejében meghívható az éppen definiálás alatt lévő makró is (a makró hívás ezáltal rekurzívvá válik). Pl. a PUSHALL IFNB
MACRO
Push reg1 PUSHALL
reg1,reg2,reg3,reg4,reg5,reg6 ;;ha a paraméter nem üres ;;az első regiszter mentése reg2,reg3,reg4,reg5,reg6 ;;rekurzió
ENDIF ENDM Makró lehetővé teszi, hogy egy felhívással akárhány (legfeljebb 6) regiszter tartalmát a verembe mentsük, pl.: a PUSHALL
ax,bx,cx
hatására a PUSH ax PUSH bx PUSH cx utasítás sorozat generálódik. Blokk ismétlés A makróhoz hasonló lehetőséget biztosít: a blokk egy definíciója alapján a blokk többszöri kifejtését. Lényeges különbség azonban, hogy ezek az operátorok nemcsak a blokk definíciójának kezdetét jelölik ki, hanem a kifejtést (hívást) is előírják. A program más részéről nem hívhatók ezek a definíciók. Blokk ismétlés kifejezés-szer: REPT … ENDM
kifejezés ;ez a rész ismétlődik
113.
A kifejezés nem lehet változó, a fordítási időben ismert kell legyen az értéke! Blokk ismétlés argumentum lista szerint:
Pl.:
hatása:
IRP … … … ENDM IRP Db ENDM db db db
par,<arg1,*,arg2…+> ; ez a rész kerültöbbször bemásolásra úgy, ; hogy par rendre felveszi az ; arg1*,arg2…+ értéket x,<1,2,3> x 1 2 3
Blokk ismétlés string alapján: IRPC … … ENDM
par,string ; ez a rész kerül bemásolásra úgy, ; hogy par rendre felveszi a string karaktereit
A stringet nem kell idéző jelek közé tenni, ez csak újabb ismétlést jelentene. A makró definíció is tartalmazhat blokk ismétlést és blokk ismétlés is tartalmazhat makró definíciót vagy makró hívást.
114.
43. Címkék, változók, konstansok, kifejezések Címkék Leggyakoribb definíciója, hogy valamelyik utasítás előtt a sor első pozíciójától :-tal lezárt azonosítót írunk. Az így definiált címke NEAR típusú. A LABEL és a PROC pszeudo utasítások további lehetőséget nyújtanak. ALFA: BETA
... LABEL FAR
;NEAR típusú ;FAR típusú
Az eljárás deklarációt a PROC utasítással nyitjuk meg. A címke rovatba írt azonosító az eljárás neve és egyben a belépési pontjának címkéje. Az eljárás végén az eljárás végét jelző ENDP pszeudo utasítás előtt meg kell ismételnünk ezt az azonosítót, de ez már nem minősül címkének. A
PROC NEAR ;NEAR típusú (a NEAR elhagyható) ... PROC FAR ;FAR típusú ...
B
Címkére vezérlés átadó utasítással hivatkozhatunk, NEAR típusra csak az adott szegmensből, FAR típusra más szegmensből Változók Definíciója ada definíciós utasításokkal történik. Néha (adat) címkének is nevezik. Adatdefiníciós utasítások Az adatokat általában külön szegmensben szokás és javasolt definiálni. A kezdőértékkel ellátott változók a program betöltésekor a megadott értékkel rendelkeznek, de a program futása során változhatnak. Erre különösen akkor kell tekintettel lennünk, ha a programot egyszeri betöltés után többször is el akarjuk indítani. Az adatdefiníciós utasítások elé általában azonosítót (változó név) írunk, hogy hivatkozhassunk az illető adatra. Egy-egy adatdefiníciós utasítással több azonos típusú adatot is definiálhatunk. A kezdő érték tetszőleges konstans (szám, szöveg, cím...) kifejezés lehet. Ha nem akarunk kezdőértéket adni, akkor ?-et kell írnunk. A szöveg és a karakter konstansokat "-k vagy '-k között adhatjuk meg. Egyszerű adatdefiníciós utasítások Define Byte (db): Az operandus lehet numerikus, karakter vagy szöveg. Pl.: Adat1 Adat2 Adat3 Kar Szoveg Szoveg1
db db db db db db
25 1,2 5 dub (?) ’a’,’b’,’c’ ’Ez egy szöveg’,13,OAH ’Ez is ”szöveg”’,”és ez is ’szöveg’”
Vegyesen is előfordulhatnak egy utasításban.
115.
;1 byte, kezdőértéke decimális 25 ;2 byte (nem egy szó) ;5 inicializálatlan byte ;3 ASCII kódú karakter ;ASCII kódú szöveg, és 2 szám
Define Word (dw): Az operandus lehet numerikus, cím, karakter vagy 2 karakteres szöveg. Pl.: Szo dw Szo_cime dw
0742H, 452 szo
;szo OFFSET címe
Define Double (dd): Az oprandus lehet numerikus, távoli cím (segment és offset cím), karakter vagy maximum 4 karakteres szöveg. Tipikus alkalmazásai: Távoli címek tárolására a stringkezelő utasítások előkésítéséhez az LDS és az LES utasítás operandusként, vagy távoli eljárások indirekt hívásához. Pl.: Szo_f
dd
szo
;szo távoli (segment+offset) címe
Define Quadword (dq): Dupla pontosságú (4 szavas) lebegőpontos számok, változók számára történő helyfoglalásra használatos. Define Ten bytes (dt): 10 byte-on tárolt 10 jegyű pakolatlan vagy 20 jegyű pakolt decimális számok, változók számára történő helyfoglalásra használatos. Összetett adatdefiníciós utasítások Programozás során sokszor előnyös, ha több – esetleg eltérő típusú – adatot egységesen tudunk kezelni. Assembly-ben ezt a lehetőséget a struktúra és a rekord biztosítja. A struktúra ill rekord elemi részeit mezőknek (field) nevezzük. Konstansok Egy művelet operandusa lehet konstans, szimbólum vagy kifejezés. A konstans lehet numerikus vagy szöveg konstans. A numerikusak lehetnek decimálisak, hexadecimálisak, oktálisak vagy binárisak. A számrendszert a szám végére írt D, H, O ill B betűvel választhatjuk ki. Ha nem írunk betűt a végére, akkor az alapértelmezett számrendszert kell érteni(általában decimális). Az alapértelmezett számredszert a .radix
n
pszeudo utasítással állíthatjuk be, és n a számrendszer alapszáma. A hexadecimális számok számjeggyel kell hogy kezdődjenek, különben a fordító azonosítónak fogja tekinteni. A szöveges konstansokat a DB utasításban " vagy ' jelek között adhatjuk meg. Kifejezések A kifejezés szimbólumokból és konstansokból épül fel az alábbi műveletek segíségével. Értékét a fordítóprogram határozza meg, és a kiszámított értéket használja operandusként. Szimbólumok értékén konstansok esetében természetesen a konstansok értékét, címkék, változók esetében a hozzájuk tartozó címet értjük. Az érték nemcsak számérték lehet, hanem minden, ami az utasításokban megengedett címzési módok valamelyikénak megfelel. Pl *BX+ is kifejezés és értéke a BX regiszterrel történő indirekt hivatkozás, és ehhez a fordítóprogramnak nem kell ismernie BX értékét. De előfordulhat, hogy egy kifejezés egyik szintaktikus helyzetben megengedett, másikban meg nem. mov mul
ax,[BX] ;[BX] megengedett [BX] ;*BX+ hibás, de WORD PTR *BX+ megengedett
116.
A műveletek csökkenő precedencia szerinti sorrendben: (nem feltétlen tartozik a tételhez) 1.
( ) zárójel pár a kifejezésben a műveletek sorrendjét befolyásolja, * + az indirekció előírásra szolgál. Ha * +-en belüli kifejezésre nem használható indirekció, akkor ( )-lel egyenértékű . (pont): struktúra mezőre hivatkozásnál használatos LENGTH változó: a változó-hoz tartozó adat terület elemeinek száma SIZE változó: a változó-hoz tartozó adat terület hossza byte-okban WIDTH R/F: az R rekord vagy az F (rekord) mező szélessége bitekben MASK F: az F (rekord) mező bitjein 1, másutt 0 Pl. v dw 20 dup (?) rec
record x:3, y:4
esetén: mov mov mov mov mov mov
ax,LENGTH v ax,SIZE v ax,WIDTH rec ax,WIDTH x ax,SIZE rec ax,MASK x
;ax 20 ;ax 40 ;ax 7 ;ax 3 ;ax 1 ;ax 70H
2. Explicit szegmens megadása (segment override prefix). Az automatikus szegmens regiszter helyett más szegmens regiszter használatát írja elő. Pl.
mov
ax,ES:[BX]
; ax(ES:BX) címen levő szó
Nem írható felül az automatikos szegmens regiszter az alábbi esetekben: CS program memória címzésnél SS stack referens utasításokban (PUSH,POP,...) ES string utasításban DI mellett, de az SI-hez tartozó DS átírható 3. Pl
típus PTR cím: (típus átdefiniálás) ahol a típus lehet BYTE, WORD, DWORD, QWORD, TBYTE, ill NEAR és FAR. Pl mul BYTE PTR [BX] ;a *BX+ címet byte-osan kell kezelni OFFSET szimbólum: a szimbólum OFFSET címe (a szegmens kezdetétől számított távolsága byte-okban) SEG szimbólum: a szimbólum szegmens címe (abban az értelemben, ahogy a szegmens regiszterben szokásos tárolni, tehát valós üzemmódban a szegmens tényleges kezdőcímének 16-oda) TYPE változó: a változó elemeinek hossza byte-okban ... THIS típus: a program szöveg adott pontján adott típusú szimbólum létrehozása
ADATB ADATW
EQU dw
THIS BYTE 1234H
;BYTE típusú változó, helyfoglalás nélkül ;ez az adat ADATB-vel byte-osan érhető el
117.
definíció esetén: mov mov mov
al,BYTE PTR ADATW al,ADATB ah,ADAT+1
;al 34H, helyes ;al ;ah
4.
LOW változó: egy szó alsó (alacsonyabb helyértékű) byte-ja HIGH változó: egy szó felső (magasabb helyértékű) byte-ja
5. Multiplikatív műveletek
* : szorzás / : osztás MOD: (modulo) a legkisebb nem negatív maradék, pl. mov al,20 MOD 16 ;al kifejezés SHL lépés: kifejezés bitenkénti léptetése balra lépés bittel kifejezés SHR lépés: kifejezés bitenkénti léptetése jobbra lépés bittel A kifejezésben előforduló műveleti jelek (SHL, SHR, és az alacsonyabb prioritású NOT, AND, OR, és XOR) nem tévesztendők össze a velük azonos alakú műveleti kódokkal: az előbbieket a fordító program, az utóbbiakat a futó program hajtja végre. 6. Additív műveletek
+ : összeadás - : kivonás vagy negatív előjel
7. Relációs operátorok: általában feltételes fordítással kapcsolatban fordúlnak elő
EQ: NE: LT: LE: GT: GE:
= < ≤ > ≥
8. NOT: bitenkénti negálás 9. AND: bitnkénti és művelet 10. Bitenkénti vagy és kizáró vagy művelet
OR: bitenkénti vagy művelet XOR: bitenkénti kizáró vagy művelet
11. SHORT: 8 bites IP relatív címzés kikényszerítése
118.
44. Szegmens definíció, szegmens csoport, aktív szegmensek kijelölése, globális szimbólumok A szegmens definícióban a szegmens egyes szeleteit írhatjuk meg a szegmens kezdő: sz_név
SEGMENT
align_type combine_type ’osztály’
és a szegmens vége: sz_név
ENDS
utasítások között. A sz_név a szegmens (szelet) neve. Ez lehet egyedi név is, de több SEGMENT utasítás előtt is szerepelhet ugyanaz a név. A fordító az azonos nevű szeleteket úgy tekinti, mintha egyetlen szegmens szeletbe írtuk volna. Az azonos nevű szeletek paraméterei egy modulon belül nem változhatnak. A szerkesztő egy memória szegmensbe szerekeszti az azonos nevű szegmenseket. A szegmens név és az osztály tetszés szerinti lehet. Az osztály legtöbbször CODE, DATA, CONSTANT, STACK, MEMORY. Az align_type (illesztés típusa) azt mondja meg, hogy – amennyiben a szegmens szelet egy már megkezdett szegmens folytatása, akkor – milyen ”határon” kezdődjön a szelet. Az align_type lehet BYTE, WORD, DWORD, PARA, PAGE, ami rendre 1-gyel, 2-vel, 4-gyel, 16-tal, és 256-tal osztható címet jelent. A combine_type (kombinációs típus) az azonos nevű szegmensek kezelésére vonatkozó üzenet a szerkesztőnek. Lehet: PUBLIC: (alapértelmezés) – az azonos nevű szegmes szeletek egymás folytatásaként szerkesztődnek össze. STACK: a szegmens szelet a stackt részekén szerkesztendő, egyébként megegyezik a PUBLIC-kal. COMMON: az azonos nevű szegmens szeletek azonos címre szerkesztendők, tehát ugyanarra a memória tartományra kerülnek. Az így keletkező terület hossza megegyezik a leghosszabb szegmens szelet hosszával. Így elérhető, hogy ugyanazt a memória területet eltérő beosztás szerint tudjuk címezni. MEMORY: a szerkesztő ezt a szegmenst az összes többi szegmens fölé (magasabb címre) fogja szerkeszteni, mindig a program legmagasabb címre kerülő része. AT kif: a kif sorszámú paragrafusra kerül a szegmens szelet. Az assemblert informálnunk kell arról, hogy melyik szegmens regiszter melyik szegmensnek a címét tartalmazza (melyik szegmensre mutat). Erre szolgál az ASSUME pszeudo utasítás: ASSUME
sz_reg1:sz_név1 * , sz_reg2:sz_név2 . . . +
119.
Az ASSUME utasításban felsorolt szegmenseket „aktív”-aknak nevezzük. Az utasítás hatása egy-egy szegmens regiszterre vonatkozóan mindaddig érvényes, amíg egy másik ASSUME utasítással mást nem mondunk az illető regiszterről. A GROUP utasítással csoportosíthatjuk a szegmenseket: G_név
GROUP S_név1 * , S_név2 . . . +
Az egy csoportba sorolt szegmensek a memória egy szegmensébe kerülnek. Ha ilyenkor az ASSUME utasításban a csoport nevét adjuk meg, és ennek megfelelően állítjuk be a bázis regisztert, akkor a csoport minden szegmensének minden elemére tudunk hivatkozni. Azonban vigyázni kell arra, hogy pl. egy változó OFFSET-je továbbra is annak a szegmensnek az elejétől számított távolsága, amelyben a változót definiáltuk, az effektív címe viszont a változónak a szegmens csoport elejétől (a memória szegmens elejétől) számított távolsága. Ha egy programot több modulban írunk meg, előfordul, hogy ugyanazt a szimbólumot, (pl. változót, címkét) több modulból is el akarunk érni. Az ilyen több modulból is elérhető szimbólumokat globális szimbólumoknak nevezzük. Ha egy szegmens valamelyik szimbólumát globálissá szeretnénk tenni, akkor PUBLIC-ká kell nyilvánítanunk annak a modulnak az elején, amelyben a szimbólumot definiáltuk. Ez a PUBLIC pszeudo utasítással lehetséges: PUBLIC
szimb1 [ , szimb2 . . . ]
Azokban a modulokban, amelyekben más modulban definiált szimbólunokat is használni szeretnénk, az ilyen szimbólumokat EXTERN-né kell nyilvánítanunk. Mivel az assemblernek a szimbólum típusát is ismernie kell, ezért az EXTERN pszeudo utasítás a következő alakú: EXTERN
szimb1:típus1 * , szimb2:típus2 . . . +
A globális szimbólumok lehetővé teszik, hogy a programokat modulokra bontva készítsük el. Az egyes blokkok közötti kapcsolatot a globális szimbólumok jelentik.
120.
45. Egyszerûsített lexikális elemzõ Fordítóprogramokban szokásos, hogy a lefordítandó programot olyan elemzésnek vetik alá, amely felismeri a programban elõforduló nyelvi elemeket (kulcsszavak, azonosítók, …), és ez alapján a fordítás további részéhez átalakítja a program szövegét. Ezt a feladatot a lexikális elemzõ végzi. Most egy rendkívüli mértékben leegyszerûsített lexikális elemzõ programját láthatjuk. Az elemzõnek legyen az a feladata, hogy felismerje a szövegben elõforduló azonosítókat, számokat, speciális jeleket és a program vége jelet, és ezek elõfordulását rendre A, 0, , és . karaktert írjon a képernyõre. Az esetleges hibákat ? jelezze. A programot az adatszegmenssel kezdjük. A lehetséges szintaktikus helyzetekhez ugró táblákat definiálunk. Az ugró táblához igazodva átkódoló táblát készítünk. DATA segment para public 'DATA' ;ugró táblák a szintaktikus helyzetnek megfelelõen: ;kezdetben, speciális és hibás karakter után t_S
dw dw dw dw dw
hiba
;hibás karakter: ;áttérés speciális jel szintre lev_a ;betû lev_n ;számjegy lev_s ;speciális jel vege ;szöveg vége: program vége
;azonosító szint t_a dw hiba dw OK dw OK dw lev_s dw vege
;hibás karakter: ;betû:nincs teendõ ;számjegy:nincs teendõ ;speciális jel, azonosító vége ;szöveg vége: program vége
;szám szint t_n dw
hiba
dw
hiba
dw dw
OK lev_s
;hibás karakter: ;áttérés spec. jel szintre ;betû:hiba, ;áttérés spec. jel szintre ;számjegy:nincs teendõ ;speciális jel: szám vége
level
dw
?
;ide kerül az aktuális ugrótábla címe
c_h c_b c_n c_s c_v
db db db db db
0 2 4 6 8
;hibás karakter kódja ;betû kódja ;számjegy kódja ;speciális jel kódja ;végjel kódja
121.
specjel db vegjel db
' ,.;+-()',13,10 ;a speciális jelek '$' ;vége jel, kihasználjuk, hogy itt van!
table
db
256 dup (?)
text
db
'a,tz,fe&a 21 a12; 12a $' ;elemzendõ szöveg
;átkódoló tábla (256 byte)
DATA ends ;============================================================== CODE segment para public 'CODE' assume CS:code, DS:DATA, ES:DATA, SS:STACK Lex proc far push ds xor ax,ax push ax mov ax,DATA mov ds,ax mov es,ax ;assume miatt call
prepare
;az átkódoló elkészítése
mov
si,offset text
;az elemzendõ szöveg kezdõcíme
call
parsing ;elemzés
ret ;vissza az Op. rendszerhez Lex endp ;-------------------------------------------------------------prepare proc ;az átkódoló tábla elkészítése ;az eljárás rontja AX, BX, CX, DI, SI tartalmát, ezért elmentjük a verembe push AX push BX push CX push DI push SI cld mov mov mov mov REP stos
;a string mûveletek iránya pozitív bx, offset table di,bx al,c_h ;hibás karakter kódja cx,256 ;a tábla hossza table ;table <= minden karakter hibás
mov al,c_b ;betû kódja mov di,'A' ;az elsõ nagybetû ASCII kódja add di,bx ;az A betû helyének offset címe mov cx,'Z'-'A'+1 ;a nagybetûk száma ;kihasználjuk, hogy a betûk ASCII kódja folyamatos REP stosb
122.
mov add mov REP stosb
di,'a' ;az elsõ kisbetû ASCII kódja di,bx ;az a betû helyének offset címe cx,'z'-'a'+1 ;a kisbetûk száma
mov al,c_n mov di,'0' ;az elsõ nagybetû ASCII kódja add di,bx ;az 0 helyének offset címe mov cx,'9'-'0'+1 ;a számjegyek száma ;kihasználjuk, hogy a számjegyek ASCII kódja folyamatos REP stosb mov xor
si,offset specjel ;speciális jelek feldolgozása ah,ah ;ki fogjuk használni, hogy AX=AL
pr1:
lods specjel ;speciális jelek olvasása mov di,ax cmp al,vegjel ;vegjel közvetlenül a speciális jelek után! je pr2 ;az már végjel mov al,c_s ;speciális karakter kódja mov [BX+DI],al ;elhelyezés a táblában loop pr1 ;ciklus vége
pr2:
mov mov
al,c_v ;a végjel kódja [BX+DI],al ;elhelyezés a táblában
;a regiszterek visszamentése pop SI pop DI pop CX pop BX pop AX ret prepare endp ;------------------------------------------------------------------parsing proc ;elemzés push AX push BX push CX push DI push SI
lv1: OK:
cld mov mov mov xor lods XLAT mov add jmp
;a string mûveletek irány pozitív bx,offset table di,offset t_s ;kezdetben is spec. jel szint level,di ;szint beállítás ah,ah ;kihasználjuk hogy AX=AL text ;a következõ karakter ;AL <= 0, 2, 4, 6 vagy 8 di,level ;DI <=az akt. ugrótábla címe di,ax ;di <= a megfelelõ elem címe [DI] ;kapcsolódó utasítás 123.
hiba:
mov mov
di,offset t_s al,'?'
;hibás karakter, spec. jel szint
lv2:
mov int jmp
ah,14 ;BIOS hívás elõkészítése 10h ;BIOS hívás: karakter írás a képernyõre lv1
lev_a: mov mov jmp
di,offset t_a al,'A' lv2
;azonosító kezdõdik
lev_na: mov mov jmp
di,offset t_n al,'0' lv2
;szám kezdõdik
lev_s: mov mov jmp
di,offset t_s al,',' lv2
;speciális jel
vege:
al,'.' ah,14 ;BIOS hívás elõkészítése 10h ;BIOS hívás, karakter kiírása képernyõre ;elemzés vége, vissza a hívóhoz SI DI CX BX AX
mov mov int ret pop pop pop pop pop
parsing endp ;-----------------------------------------------------------------CODE ends ;================================================================== STACK segment para stack 'STACK' dw 100 dup (?) ;100 word legyen a verem STACK ends end Lex ;modul vége, start cím: Lex
124.
46. Két menetes assembler fordító Az assembly nyelvű programok egysoros utasításokból állnak, így természetesnek tűnik az elgondolás, hogy az assembler az utasításonként lefordított gépi nyelvű kódot egy fájlba helyezze el, a megfelelő listarészeket pedig (ha van ilyen) egy másik fájlba. Azonban ez különböző nehézségekbe ütközik, és így nem megvalósítható. Egy ilyen lehetséges probléma az előre hivatkozási probléma. Ez akkor lép fel, amikor egy olyan L szimbólumra hivatkozunk, amelyet eddig még nem definiáltunk (pl egy címke, amely a program végére ugrik, így a definíció a program végéhez van közel). Így az assembler nem ismeri a szimbólum címét. Ezt a problémát két módon lehet lekezelni:
Az assembler a forrásprogramot kétszer olvassa. Egy olvasási folyamatot menetnek nevezünk. A fordítók, amelyek kétszer olvassák a forrásprogramot, a kétmenetes fordítók. Az assembler a programot csak egyszer olvassa, és egy közbülső formába transzformálja, ezt pedig memória egy táblázatába helyezi. Csinál egy második menetet is, de ez már a táblázaton megy végig. Így B/K idő takarítható meg. Ha van listaigény, az egész forráskódot tárolni kell a megjegyzésekkel együtt.
A kétmenetes fordítók működése: Első menet: Ennek fő feladata az ún. Szimbólumtábla felépítése, amely tartalmazza az összes szimbólum értékét. Egy szimbolikus névnek értékül adható címke vagy konstans. A fordítás alatt létezik egy utasításszámláló nevű változó, amely nyomon követi annak az utasításnak a futtatáskori címét, amelyet éppen fordít. Az első menet kezdetekor ez 0, utána pedig minden utasítás feldolgozásakor az utasítás hosszával növekszik. Az első menetben legalább 3 táblázat jön létre: Szimbólumtábla, pszeudoutasítások táblázata és a műveleti kódtábla. Esetleg még egy konstans táblázat. A szimbólumtábla tartalmazza a szimbólumot(vagy egy mutatót rá), a numerikus értéket, valamint egyéb információkat(a szimbólumhoz tartozó adatmező hossza; áthelyezési bitek=>változike a szim. étéke, ha a progi más cimre töltődik be, mint az assembler feltételezi;vajon elérhető-e a szimbólum más eljárásból?) A szimbólumtábla az asszociatív memória működését szimulálja: A szimbólum ismeretében megadja a hozzá tartozó értéket. A szimbólumtábla lehet tömbös felépítésű, a párok első komponense a szimbólum, a második pedig az érték(vagy az ezekre mutató mutató). A szimbólumtáblában kereshetünk lineárisan(egyszerű, de lassú módszer, az elemeket át kell vizsgálni sorban egyenként, amig meg nem lesz a keresett szimbólum), és bináris keresőalgoritmus segítségével, ha a tömb rendezett. Ilyenkor megnézzük a középső elemét, ha az a keresett elem, vége a keresésnek, ha ennél nagyobb, akkor a felső fél
125.
táblázatban csináljuk ugyanezt, ha kisebb, az alsóban (mindig a középső értéket nézzük meg először). Így a legrosszabb esetben log2n lépésre van szükség n elem esetén. Az asszociatív memória szimulálásának teljesen más módja a tördelő kódolási módszer. A művelettábla nyit egy bejegyzést minden mnemonic (szimbolikus műveletkód) részére. A bejegyzésnek (vegyük úgy, mint egy táblázat egy sora) a következő mezői vannak (a tábláza oszlopai): szimbolikus kód, a két operandus, az utasítás hossza, és egy típusszám(operandusaik szerint csoportosítja az utasításokat). Pl.: Müv.Kód
Első op Második op
ADD
EAX
Müv.Kód Hexában
immed32
Hossz Típusszám
05
5
4
Egyes assemblerek lehetővé teszik a közvetlen címzés használatát. Ilyenkor az assembler automatikusan memóriát foglal a konstansnak. Ezeket a konstansokat literáloknak nevezzük. Az első menetben az összes literálból táblázat készül. A fordító minden literált felvesz ide, de a menet végén az ismétlődőeket kitörli. Második menet: Ennek feldata a tárgyprogram előállítása és lehetőleg a fordítási lista kinyomtatása. Itt jön létre a .obj fájl. A második menet kiad még néhány információt, amelyekre a szerkesztőnek lesz szüksége a későbbiekben. Ez is egyesével olvassa a sorokat és dolgozza fel azokat. Egy sor egy-egy utasítás, amely a típusára, a műveleti kódra és a hosszra vonatkozó információval kezdődik (az ideiglenes fájlban), így a második menet ezt egyszerûen beolvassa, nem kell elemezgetnie. Az utasításhoz generált bináris kódot a code váltózóban adja vissza, amely aztán kiírásra kerül, és az utasítások bináris kódjaiból létrejön az object file. Ez hexadecimális alakú. A forrasprogramban azonban hibák is előfordulhatnak. Az egyszerûbbeket, mint például az elgépelésből eredő definálatlan szimbólumok, az assembler megpróbálja kijavítani a hozzá legjobban hasonlító szimbólum használatával. Azonban általában a fordítóprogram tehetetlen a legtöbb hibával szemben. Pl.
Még nem definiált szimbólum alkalmazása Többszörösen definiált szimbólum alkalmazása A műveleti kódmezőben lévő kód nem megendegett műveleti kód A műveleti kódnak túl kevés vagy túl sok operandus van megadva Egy oktális számban előfordul pl. a 9-es számjegy Jogtalan regiszterhasználat Hiányzó END utasítás
126.
47. Az include utasítás. Az include utasítás feldolgozása a fordítás során. Az assembler képes kezelni a több fájlra darabolt programokat is, a nyomkövetővel történő használathoz az egész programnak egyetlen, egy „$” kiterjesztéssel rendelkező fájlban kell elhelyezkedni. Ezen belül fájlok beillesztését a #include fájlnév paranccsal lehet kérni. Ebben az esetben a kívánt fájl szintén a kombinált „$” fájlba íródik a kérés helyétől kezdődően. Az assembler ellenőrzi, hogy a beillesztendő fájlt már feldolgozta-e, és csak egy példányt tölt be. Ez különösen hasznos, ha több fájl ugyanazokat a fejlécfájlokat használja. Ilyenkor a kombinált forrásfájlba csak egy példány kerül beillesztésre. A fájl beillesztéséhez szükséges, hogy a #include a sor első tokenje legyen vezető szóközök nélkül, a fájl útvonalát pedig idézőjelek között kell megadnunk. Ha csak egyetlen forrásfájlunk van, mondjuk a pr.s, akkor feltételezzük, hogy a projekt neve pr, a kombinált fájl pedig a pr.$ lesz. Ha egynél több forrásfájlunk van, akkor az assembler az első fájl nevének tövét tekinti a projekt nevének, és használja a .$ fájl definiálásához, amelyet utána a forrásfájlok összemásolásával állít elő. Ez a viselkedés felülbírálható a parancssoron az első forrásfájl megadását megelőzően megadott „-o projname” kapcsolóval, amikor is a kombinált fájl a projname.$ lesz. Megjegyezzük azonban, hogy a beillesztett fájlok, és egynél több forrásfájl használatának vannak hátrányai is. A címkéknek, változóknak és konstansoknak az összes forrásban különbözőnek kell lenni. Ezen kívül, a ténylegesen fordításra kerülő fájl a projname.$, tehát arra vonatkoznak az assembler által a hibák és figyelmeztetések jelzésekor kiírt sorszámok. Nagyon kis projektek esetén néha az a legegyszerűbb, ha az egész programot egyetlen fájlban helyezzük, és elkerüljük a #include használatát.
127.
48. Makró generátor A makró generátor feladata a makró definíciók megjegyzése (pl. makró táblába helyezése) és a makró hívások kifejtése. A makró generátor általában az assembler első menetében működik. Az assembler sorról sorra megy végig a forrásprogramon. Ha eközben makródefiníciót talál (a műveleti kód részen lévő MACRO szóról ismerhető fel), akkor a makró teljes szövegét (a makró végét az ENDM szó jelzi) elhelyezi a makró táblában. Amikor a makró a makrótáblába kerül, az assembler egy különleges jellel megjelöli a formális paramétereket, ez az & jel. Igy majd a makróhívások során használhatunk paramétereket, amelyekkel a meghívott makró dolgozni fog. A makróhívások kifejtése során az assembler felismeri, hogy makrót talált a forrásprogramban, megkeresi a makrót a makrótáblában, betölti egy pufferbe, majd a puffer tartalmát beleilleszti a program szövegébe a megfelelő helyre. A makrókifejtést a következő programrészlet ciklikus ismétlésével lehet illusztrálni:
EgySzoOlvasasaAMakroTorzsbol; if FormalisParameter then AmegfeleloSorszamuAktualisParameterAtmasolasa; else AszoAtmasolasa; ElvalasztojelFeldolgozasa;
A makróhívásokkor jelentős probléma, hogy a makrón belüli címkék minden makróhíváskor megjelennek a programban, és ezáltal címkeduplázódás (triplázódas stb, szóval ismétlés) jön létre, ami fordítási hibát eredményez. Ezért a makrók fejléce után, a címke neve elé oda kell irni a LOCAL pszeudoutasítást (a pszeudoutasítások egy másik tétel témaját képezik), ezzel azt érjük el, hogy a makrógenerátor a címkét egy '??xxxx' alakú azonosítóval helyettesíti (xxxx változó, egy hexadecimális szám), és minden szimbólum feldolgozása után a változót (vagyis xxxx-et) 1-gyel növeli. Így nem lép majd fel címkeismétlés.
128.
49. Szerkesztő Különböző operációs rendszerekben a szerkesztő elnevezései: Link, Linker, Linkage Editor, Linkage Loader, stb. Alapvető feladata, hogy a programhoz tartozó object file-okat (modulokat) egyetlen futtatható file-ba, a load modulba szerkessze. Eközben 4 feladatot kell megoldania:
az azonos nevű és osztályú szegmens-szeletek egymáshoz illesztése a szegmens-szeletek definíciójában megadott módon, a GROUP pszeudo utasítással egy csoportba sorolt szegmensek egymás után helyezése, a relokációk elvégzése, a külső hivatkozások (extern) feloldása.
A szerkesztő két menetben dolgozik: az első menetben táblázatokat készít, a második menetben a táblázatokba elhelyezett információk alapján elvégzi a szerkesztést. Az egyik táblázat a szegmens-szeletekre vonatkozó térkép (map), a másik a globális szimbólumok táblázata. Az első menetben a szerkesztő beolvassa az összeszerkesztendő modulokat és közben kitölti a map-et a kezdőcím és a relokációs konstans kivételével. Az összes modul beolvasása után a kívánt szempontok (szegmens név, osztály, kombinációs típus, és a szerkesztő opcióiban előírt szempontok) szerint rendezi a táblázat sorait, majd a kezdőcím és a relokációs konstans rovatot is ki tudja tölteni. A legelső kezdőcím az operációs rendszertől függ (betöltési cím). Az egyes szegmens-szeleteknek és a szegmens első szeletének a kezdőcíme közötti különbség lesz a relokációs konstans. Ezt az illető szegmens-szeletben definiált szimbólumokra történő hivatkozások esetén hozzá kell adni a fodító által előállított relokálandó címhez. A globális szimbólumok kezeléséhez a fordítóprogram minden object modulban információt ad át a modulban PUBLIC-ká és EXTERN-né nyilvánított változókról. A szerkesztő az első menetben a PUBLIC változókból egy közös globális szimbólum táblát készít. A PUBLIC utasítás nem tartalmazza a típust és a szegmens nevét, de az assembler ismeri, és el tudja helyezni az object modulban. A modul nevét a szerkesztő is ismeri. A cím a táblázat összeállításakor még relokálatlan címet jelent. Az első menetben ebben a táblázatban elvégezhető a relokáció. Az assembler az EXTERN utasítás alapján újabb táblázatot készít. Az első menetben kigyűjti a szimbólumokat a hozzájuk tartozó típussal együtt, és ez alapján az első menet végén ellenőrzi, hogy minden szimbólum előfordul-e közös globális szimbólum táblában. Ha nem, akkor definiálatlan külső hivatkozások maradtak, ilyenkor az első menet további programkönyvtárbeli modulok hozzávételével folytatódhat. A szerkesztő a második menetben a rendezett térkép sorainak megfelelő sorrendben beolvassa és elhelyezi a szegmens szeleteket, elvégzi a szükséges relokációt és feloldja a külső hivatkozásokat. Utóbbi feladathoz egy-egy modul betöltésének végén a szerkesztő az EXTERN szimbólumokat sorra megkeresi a közös public táblában. Ha megtalálta, akkor sorra veszi a hivatkozásokat, és mindegyik hivatkozáshoz elhelyezi a PUBLIC táblában található címet. Ha az illető szimbólum nem található meg a közös PUBLIC táblában, akkor „feloldatlan címkonstans” hibajelzést ad. 129.
A szerkesztő lehetővé teszi, hogy egy nagyobb programot több modulban, esetleg különböző programozási nyelveken írjunk meg. Segítségével lehetővé válik, hogy részfeladatok megoldásához már korábban elkészített object modulokat használjunk fel.
130.
50. Time sharing (időosztás). dinamikus szerkesztés
binding
(cím
hozzárendelés),
Egy időosztásos (time sharing) rendszerben (nagyobb léptékben nézve) egyidejűleg több program fut. A program-kiválasztó (scheduler) feladata, hogy gondoskodjon arról, hogy mindegyik program elég sűrűn kapjon egy rövid CPU-időt. Egy program elindításakor többek között a következő feladatokat kell végrehajtani: betöltés, indítás, felfüggesztés, kimentés; a program folytatásakor: visszamentés, futtatás, felfüggesztés, kimentés. A kimentés – viszamentésre azért van szükség, mert általában nem biztosítható hogy a visszamentett program a memóriának ugyanarra a területére kerüljön vissza, ahol korábban futott. Ha pl. a programunk egy JMP L ugró utasítást tartalmaz, akkor L-hez valamikor hozzá kell rendelnünk a konkrét címet, ez címhozzárendelés (binding). A címhozzárendelés különböző időpontokban történhet. Ez alapján történhet:
Program írásakor Fordításkor Szerkesztéskor Betöltéskor A címhez használt bázisregiszter kitöltésekor Utasítás végrehajtásakor
Program írásakor: A számítástechnika kialakulásakor ez volt a helyzet, a programot bináris számokkal kellett megadni. Manapság ez a módszer már ritka, de a lehetősége fellelhető a szegmens definicióban alkalmazható AT kifejezés kombinációs típusban. Fordításkor: Ma már ezt a módszert is igen ritkán alkalmazzák, pl. szintén az AT kifejezés kombinációs tipussal kapcsolatban, ha a szegmensben szimbolikus címzést használnak. A címhozzárendelés ilyen módjának a legnagyob hátránya hogy alkalmazása nehézzé, időnként lehetelenné teszi az így elkészített program részek különböző programokban való felhasználását. Szerkesztéskor: Ma ez a címhozzárendelás egyik legelterjedtebb módja. Betöltéskor: Az assembly nem ezt a címhozzárendelési mószert használja. Ha ezt használná, a programban nem szerepelhetne egyetlen FAR típusú címkonstans se, hiszen ennek az értéke a betöltés helyétől függ. A címhez használt bázisregiszter kitöltésekor: Ez a módszer már biztosítja az időosztásos rendszerben futtatható programok elkészítését. Alkalmazása még komolyabb megszorításokat jelent. A betöltések esetén is gondoskodni kell a FAR címeket tartalmazó változók helyes értékéről, sőt, távoli eljárás hívás esetén FAR cím kerül a verembe, és természetesen ezzel is foglalkozni kell. Megfelelően kialakított hardver sokat segíthet a probléma megoldásában. Az utasítás végrehajtásakor: Ehhez a címhozzárendelést két lépésben valósítják meg, Először a szimbolikus címzést virtuálissá alakítják, majd ezt fizikai címzéssé. A virtuális címhozzárendelés történhet pl. szerkesztési időben, a fizikai cím hozzárendelés a lap (page) tábla kitöltésekor, ami valóban gyakran az utasítás végrehajtásának megkezdése után történik.
131.
Dinamikus szerkesztés Előfordulnak olyan nagyméretű programok, amelyekben bizonyos eljárások csak nagyon ritkán szükségesek. Ha ezeket az eljárásokat is hozzászerkesztjük a programhoz, akkor a program memóriaigénye nagyon nagy lehet. Ennek elkerülésére szolgál a dinamikus szerkesztés. A dinamikus szerkesztés egy lehetséges megoldás, hogy a programban létrehozzunk egy táblázatot (Linkage segment), amely minden esetleg szükséges eljáráshoz egy csatoló blokkot tartalmaz. Minden blokk elején egy virtuális cím, a további részén az eljárás neve található karaktersorozat formában. A virtuális cím lehet egy csatolóprogram címe vagy egy lehetetlen cím (invalid adress). Az utóbbi esetben gondoskodnunk kell arról, hogy a létrejövő megszakítás hatására a csatoló program kapja meg a vezérlést. Multics dinamikus szerkesztése: minden programhoz egy úgynevezett kapcsolószegmenst társít, amiben a hívható eljárások mindegyikének van egy információs blokkja. Az információs blokk elején egy szó van fenntartva az eljárás virtuális címe számára, ezt az eljárás neve követi, ami karakterláncként tárolt. A Windows dinamikus szerkesztése: a dinamikus szerkesztéshez egy speciális fájlformátumot használ, amit DLL-nek (Dynamic Link Library) hívnak. A DLL-ek tartalmazhatnak eljárásokat, adatokat, vagy mindkettőt. Rendszerint arra használják, hogy lehetőséget biztosítsanak két vagy több folyamat számára a könyvtár ejárásainak és adatainak megosztott alkalmazására. A UNIX dinamikus szerkesztése: lényegében hasonló a Windows DLL-es koncepciójához. Az általa használt speciális fájlt megosztott könyvtárnak hívják. Egy megosztott könyvtár, a DLL fájlhoz hasonlóan egy archivált fájl, ami megosztott eljárásokat vagy adatmodulokat tartalmaz, amelyek futási időben vannk jelen a memóriában és a folyamatok számára egyidejűleg elérhetők.
132.
51. Programok hangolása Programhangoláson azt a folyamatot értjük, amikor megállapítjuk a kritikus programrészeket, és ezek gyorsításával az egész program futását felgyorsítjuk. Bizonyított tény, hogy a nagyobb programokban a program 1%-a felelős a program futási idejének kb. 50%-áért, 10%-a pedig a 90%áért. A legritkább esetben célszerű egy feladatot teljes egészében assemblyben programozni, de ha a program gyakran fut, akkor célszerű lehet a hangolás során bizonyos részeket assemblybe átírni. A kritikus részek felderítésére használható a következő módszer. Miközben a hangolandó programot nagy méretű feladaton vagy feladatokon futtatjuk, rövid, véletlen időnként, időzítés szerinti megszakításokat kérünk. A megszakítások címét egy file-ban rögzítjük. Később a megszakítások címét és a szerkesztő által összeállított memóriatérképet összevetve, megállapíthatjuk, hogy mely eljárásokban történt a legtöbb megszakítás, ezekben az eljárásokban tartózkodott legtöbbet a program. Ezeket az eljárásokat, eljárás részeket kell felgyorsítani pl. Assembly betétekkel, vagy az egész eljárás assemblybe való átírásával. A programhangolás hatásának szemléltetésére tételezzük fel, hogy ugyanannak a feladatnak a megoldásához assemblyben 5-ször annyi utasításra (és időre) van szükség, mint probléma orientált nyelv esetén, és az elkészült program 3-szor olyan gyors. A probléma orientált nyelven készült változatának kritikus 10%-át assemblyben újraprogramozzuk. Egy kis számolás után beláthatjuk, hogy a program problémaorientált nyelven történő elkészítésének és hangolásának ideje (és költsége) kb. harmada annak, mintha az egészet assemblyben készítenénk, ugyanakkor a sebessége csak 20%-al lassabb.
133.