ebooksgratis.com

See also ebooksgratis.com: no banners, no cookies, totally FREE.

CLASSICISTRANIERI HOME PAGE - YOUTUBE CHANNEL
Privacy Policy Cookie Policy Terms and Conditions
Assembly - Wikipédia

Assembly

A Wikipédiából, a szabad enciklopédiából.

Az assembly (angol: a.m. összerakás, összegyűjtés) a gépi kódhoz (a számítógép „anyanyelvéhez”) legközelebb álló, és így helykihasználás és futási idő szempontjából a leghatékonyabb programozási nyelv.

Az assembly nyelv nem keverendő össze a gépi kóddal: egy assembly nyelvű program végrehajtható utasításai általában egy gépi kódú utasításnak felelnek meg, tehát az assembly egy programozási nyelv, a gépi kód az a tárgykód, amit csaknem minden programozási nyelv előállít végeredményként.

Tartalomjegyzék

[szerkesztés] Keletkezés

Az első számítógépek programozása úgy történt, hogy a számításokat végző elemek huzalozását változtatták meg.

A számítógépeket a kezdetekben a processzoruk utasításaihoz rendelt számok bevitelével (gépi kóddal) lehetett programozni, melyek ábrázolása eleinte bináris majd később oktális (nyolcas) vagy hexadecimális (tizenhatos) számrendszerben (vagy röviden csak „hexában”) történt.

Állítólag az atombomba-számításokat végző dr. Glennie 1954-ben saját szakállára elkészítette a MARK I első assembler fordítóját.

Az assembly kódhoz tartozó fordítóprogramot assemblernek nevezik. Ez készít a szöveges forrásprogramból egy olyan állományt, amely csaknem teljes egészében megfelel annak a memória képnek, amelyet a processzor végrehajtható programként értelmezni fog.

Az assembler "párja" a disassembler ami a lefordított bináris kódot értelmezi és assembly forráskódú listává alakítja. Alacsonyszintű programozás további kellékei:

  • memóriatartalom vizsgáló, "dump" program
  • debugger – hibakereső program
  • hexa editor – állományok hexadecimális (16-os számrendszerű), ha szükséges utasításszintű módosítását teszi lehetővé
  • processzor szimulátor – adott processzorra írt programot "szoftveresen" futtat egy másik számítógépen, esetleg a célgép további hardver elemeit is emulálja

[szerkesztés] Formai jegyek

Az assembly nyelvet utasítások (tényleges kódot hoznak létre) és direktívák, vagy pszeudó utasítások (a fordítás vagy kódgenerálás vezérlése) alkotják.

A különböző processzorcsaládok utasításkészlete bár sokszor jelentősen eltér, de a gyártók által megadott assembly nyelvű szintaxis általában hasonló irányelvekre épül. Az utasítások általában néhány betűs rövidítések, azoknak a gépi utasításoknak a mnemonikjai, amelyek a processzor utasításkészletét alkotják.

A direktívákkal vezérelhető a változók és a program elhelyezése, igazítása, a program belépési pontjának meghatározása. A direktívák hatására léterjövő információk egy részét a fordító szintaktikai ellenőrzéshez használja, más részük a szerkesztő és/vagy a betöltő program számára ad információt. Ez a két program teszi lehetővé, hogy az assembler által készített kódból futtatható program jöjjön létre.

Az assembly forráskód soronként logikailag egy műveletet tartalmaz, egészében nézve a forrás felépítése a következő:

  • Deklarációs rész: változók, konstansok, makrók definiálása.
  • Végrehajtható, ill kód-rész: utasítások egymásutánja. Egy utasítássorhoz klasszikus esetben egy gépi kódú utasítás (és annak esetleges paraméterei) tartozik, az újabb, úgynevezett makró assemblerekkel definiálhatunk nevesített kódrészleteket is, mintegy „magasabb szintre emelve” ezáltal a nyelvet.
    1. Címke: „megcímkézhetünk” egy utasítást, melyet ugró utasítások célpontjaként, esetleg változók illetve konstansok azonosítására használhatunk.
    2. Az elvégzendő művelet (operátor) megnevezése (mnemonikja)
    3. Egy szóköz után az esetlegesen szükséges operandus(ok) (paraméterek), több operandust hagyományosan vesszővel választunk el. Az operandus(ok) előtt vagy után speciális jelölések mutatják a címzési módot.
    4. Megjegyzések, ezeket szintaxistól függő elválasztó karakter után írva rögzíthetjük.
    • Utasítástípusok

Egy processzornak vagy műveletvégzőnek általában 50-80 mnemonikkal megkülönböztetett végrehajtható utasítása van, de ez nagyon eszközfüggő.

[szerkesztés] Jellemző utasítások típusok

[szerkesztés] Memóriakezelő utasítások

Ezek az utasítások az operatív memóriával közvetlenül kapcsolatos olvasó és/vagy író utasításokat valósítják meg. Minden esetben legalább egy operandusuk van (egy címes gépek esetén), ami az adott memóriacímre hivatkozás (bár ez a cím lehet implicit oprandus is, vagyis már adott regiszterben előkészített; nem pedig a műveleti kód adott mezőjében megadott). Az olvasási utasítások a kijelölt memóriacím tartalmat egy kijelölt regiszterbe töltik, míg az írási utasítások a kijelölt regiszeter tartalmát tárolják el a kijelölt memóriacímen; továbbá léteznek memória-memória utasítások is, melyekkel egy memóriarekeszt vagy tartományt mozgatnak át (egyes helyeken string-kezelő utasításokként említik őket). Külön utasítások létezhetnek a byte, szó (2 byte) duplaszó (2 szó) stb. tartományok elérésére, de lehetséges, hogy ezt előtéttagok – más néven prefixum – segítségével kell elérni. Ezek – formailag – az utasítás előtt helyezkednek el, és egy utasítás előtt egyszerre több is lehet belőlük (a maximális szám processzorfüggő). Tehát a memóriareferens utasítások kimenetelét illetve lezajlását különböző előtéttagok befolyásolhatják:

  • ismétlő prefix – ismétlés adott feltétel fennállásáig
  • operandusméret prefix – az elérni kívánt memóriarekesz nagyságát befolyásolja
  • címmódosító prefix – az elérni kívánt memóriarekesz címének értelmezését befolyásolja
  • szinkronizációs prefix – a CPU és az FPU közötti szinkronizáció céljára (a 386-os PC-nél már hardveresen működik eme mechanizmus)
  • buszlezárás prefix – az adatmódosítás biztonságát (konzisztencia) növeli, például többprocesszoros rendszerekben

[szerkesztés] Regiszterkezelő utasítások

A regiszterek között végezhető műveleteket (regiszterek közötti csere, regiszter jobb-bal oldalának cseréje, speciális regiszterekhez való hozzáférés stb.) valósítják meg.

[szerkesztés] Aritmetikai és logikai utasítások

Ezek az utasítások aritmetikai műveletek (összeadás, kivonás, szorzás, osztás, esetleg ugyanezek lebegőpontos változatai, kiegészítve az un. normalizáló utasítással), illetve elemi logikai műveletek (és, vagy, nem, kizáró-vagy) végrehajtására szolgálnak.

Általában ide sorolják az un. léptetési utasításokat is, mivel ezek – a bináris számrendszer speciális esete miatt – épp 2 egész számú hatványaival való szorzás, osztás műveletet valósítanak meg.

[szerkesztés] Ugró utasítások

Az ugró utasításokkal a program végrehajtásának folyamata vezérelhető. Általában feltétel nélküli és feltételes ugrási utasításokról beszélünk. A feltételek egy regiszter, vagy az úgynevezett program- vagy processzorjelző (flag) adott bitjének/bitjeinek állapotához köthetőek (nulla, nem nulla, pozítív, negatív, kisebb, nagyobb, van túlcsordulás, van átvitel stb). Az egyes utasítások leírásánál pontosan meg van adva, hogy a processzorjelzőket hogyan módosítják a végrehajtás során. (A módosító hatásúak legtöbbször aritmetikai-logikai műveletek vagy kifejezetten erre a célra szánt utasítások.)

Az utasítások operandusa az a hely (vagyis egy cím), ahol a programot folytatni kell, a feltételtől függően. Ha a feltétel nem teljesül, akkor a program a következő utasítást hajtja végre, tehát a végrehajtás folyamata nem módosul. Maga a címoperandus lehet literális – vagyis cimke vagy cimke kifejezéssel megadott cím – vagy regiszterben kijelölt, esetleg valamilyen indirekció. Továbbá a feltételes ugrásoknál előfordul implicit operandusú megoldás, vagyis amikor az ugrási címet nem adjuk meg konkrétan. Ilyen elágazó utasítás esetén a végrehajtás mindig a (program)sorban következő vagy a következő utáni utasításra helyeződik át – az elágazástól függően.

[szerkesztés] Speciális utasítások

Speciális utasítások a megállító (halt, sleep), az üres (nop) utasítás és egyes processzor állapot kezelő utasítások.

[szerkesztés] Megállító utasítás

Megállítja a program futását, és csak "külső beavatkozás" (pontosabban interrupt vagy reset) hatására lép tovább. Egyes processzorok ekkor automatikusan energiatakarékos üzemmódba lépnek.

[szerkesztés] Üres utasítás

Az üres utasítás "nem tesz semmit". Ezt általában időzítésre használják (valamilyen hardver időzítés miatt, elágazott programszálak futási idejének kiegyenlítésére esetleg hardver diagnosztikai célra → címsín vizsgálatához).

[szerkesztés] Processzor állapot kezelő utasítások

A megszakítások kezelésére szolgáló, valamint a ki- és beviteli műveletek, illetve egyéb, a számítógép és/vagy a processzor működését vezérlő utasítások tartoznak ebbe a csoporba.

[szerkesztés] Direktívák

A direktívák az assemblernek szóló utasítások, amelyekből nem keletkezik gépi kód. Néhány fontosabb csoportjuk

  • listakészítés engedélyezése/tiltása, pl
PRINT ON           ; /360
  • Program tulajdonságainak megadása, pl
ORG cím            ; Z80: program (végső) címe
SEGMENT AT cím     ; x86: memóriaterület címe
END cimke          ; Program vége, egyben belépési pont megadása
  • Program szakaszokra bontása, szakaszok tulajdonságainak megadása, pl
snév SEGMENT CODE  ; x86:  kódszegmens
snév DESCT         ; /360: 'dummy' adatszegmens
snév CSECT READ    ; /360: kódszegmens, írásvédett
snév AMODE ANY     ; /360: csak 31-bites módban futtatható
  • Címzéshez használandó regiszterek definiálása, pl
ASSUME CS:code,DS:data,ES:video ; 8086: definíció
ASSUME ES:nothing               ; 8086: visszavonás
USING code,R12                  ; /360: definíció
DROP R12                        ; /360? visszavonás
  • Szimbólumok exporja/importja, pl
ENTRY rutin   ; /360
EXTRN valtozo ; /360
  • Változók definíciója
var EQU érték ; általános
var = érték   ; /8086
  • Makrók definíciója és meghívása, illetve a makrókban használható speciális utasítások (pl elágazás)

[szerkesztés] Assembly nyelvjárások

A különféle architektúráknak, platformoknak, processzoroknak eltérő, egymással általában semmilyen kompatibilitást nem biztosító assembly nyelvei vannak, bár ezen nyelvek alapszerkezete nagyon hasonló.

[szerkesztés] Intel x86 (8086 – 80486 – Pentium)

  • Intel szintaxis
    • Microsoft Macro Assembler (MASM, Microsoft) – Ingyenesen hozzáférhető a MASM32 projekt részeként [1]
    • Turbo Assembler (TASM, Borland) [2]
    • Netwide Assembler (NASM, GNU) [3]
    • High Level Assembler (HLA, Public Domain) – Randall Hyde-nak, a The Art of Assembly Language című könyv szerzőjének saját assemblere [4]
    • Flat Assembler (FASM, GNU GPL) [5]

Példa (C eredeti: *p = n):

MOV  EDX,[EBP-16]
MOV  EAX,[EBP-20]
MOV  [EDX],EAX
  • AT&T szintaxis
    • GNU Assembler (GAS, GNU)

Példa (ugyanaz, mint az előbbi):

mov    -16(%ebp),%edx
mov    -20(%ebp),%eax
mov    %eax,(%edx)

[szerkesztés] MOS-6510

A 6510 (pontosabban, a 65xx, 75xx, 85xx processzorcsalád) a Commodore 64 és társai (mint amilyen a C16, VIC-20 vagy a Commodore 128) processzora. Három általános célú nyolcbites regiszterrel rendelkezik: az A akkumulátorral, valamint az X és Y indexregiszterekkel. Címtartománya 64 kilobyte, de külön címzési módok támogatják az első 256-byte (00xxH címek, az ugynevezett zero page) elérését, a második 256-byte (01xxH címek) pedig rögzítetten a stack helye (ezért az S stack-pointer regiszter is csak nyolc bites).

[szerkesztés] Motorola 68xxx

Ezen processzorok főként a Commodore Amiga gépekben váltak ismertté.

[szerkesztés] Z80

Az Intel 8080 adaptációjaként a Zilog cég által gyártott, és korának legelterjedtebb processzorának nyelve. Számos összetettebb utasítással is rendelkezik. A Z80 assembly nyelve az Intel 8080-asénak egy kibővített és egyben egyszerűsített változata, például az összes adatmozgató utasítás mnemonikja egységesen LD, szemben a 8080 különféle változataival, például:

8080       Z80

MOV  A,B   LD   A,B
MOV  A,M   LD   A,(HL)
MOV  M,A   LD   (HL),A
LDAX B     LD   A,(BC)
STAX B     LD   (BC),A 
MVI  A,n   LD   A,n
LXI  H,nn  LD   HL,nn
LHLD cím   LD   HL,(cím)

[szerkesztés] IBM System/360

Az IBM mainframe-ei processzorainak nyelve. Tizenhat általános célú 32 bites regisztere van (R0-R15), a használható címtartomány eredetileg 24 bites volt (16 MB címtartomány), a /370-es sorozattól ez 31 bitesre bővült (2 GB címtartomány). A gépi utasítások 2, 4 vagy 6 byte hosszúak, a használható adattípusok: byte, félszó (16 bit), szó (32 bit), pakolt szám (1-16 byte), általános memóriaterület (1-256 byte). Kétcímű gép, azaz egy utasításban két memóriaterület is szerepelhet.

Példaprogram (egy eljárás tipikus kezdete/vége/hívása):

RUTIN STM   R14,R12,12(R13) ; regiszterek mentése a hívó
                            ; regisztermentési területére
      BASR  R12,R0          ; bázisregisztrer beállítása
      USING *,R12           ; assembly direktíva:
                            ; használd a bázisregiszert
      LA    R14,SAVEA       ; saját mentési területünk
      ST    R13,4(R14)      ; elmentjük a hívóét
      LR    R13,R14         ; használjuk a sajátunkat

      ...

KILÉP L     R15,visszatérési_érték
      L     R13,4(R13)      ; vissza a hívó mentési területére
      L     R14,12(R13)     ; visszatérési cím
      LM    R0,R12,20(R13)  ; hívó regisztereinek visszatöltése
                            ; kivéve az R15-öt
      BR    R14             ; visszatérés
SAVEA DS    18F             ; regisztermentési terület: 72 byte

      ...

HÍVÁS L     R15,=A(RUTIN)   ; rutin címe R15-be
      LA    R1,paraméterek_címe
      BASR  R14,R15         ; ugrás R15-re,
                            ; visszatérési cím R14-be
UTÁNA LTR   R15,R15         ; visszaadott érték vizsgálata
      BZ    SIKER           ; tipikusan 0=siker

[szerkesztés] A nyelv előnyei és hátrányai

Az összehasonlítást a magas(abb) szintű programozási nyelvekkel szemben kell érteni.

[szerkesztés] Előnyei:

  • Kisebb méretű kód, mert a programozó maga dönti el mely utasítások szükségesek az adott probléma megoldásához.
  • Az esetek többségében gyorsabb futás jellemzi.
  • Könnyebben lehet optimalizálni mind memória használatra, mind futási sebességre.
  • Vannak olyan eszközök (pl. mikrokontrollerek), amelyek nagyon kis méretű operatív tárral és memóriával rendelkeznek, és feldolgozási sebességük is igen lassú. A magas szintű nyelvek pedig az assemblyvel szemben többnyire lényegesen nagyobb programkódot állítanak elő, és sem a memória, sem pedig a futási sebességre nem igazán lehet velük optimalizálni.
  • Bitműveletek használata egyszerűbb.
  • Az általunk megírt eljárások pontos működését ismerjük, könnyebben lehet további speciális célokra úgy módosítani, hogy az ne vonjon maga után aránytalanul nagyobb kódot, memória használatot, vagy hosszabb futási időt, sőt az esetek többségében még javíthatunk is rajta!
  • A nyelv határai a rendelkezésre álló hardver(ek) tényeges határáig terjednek, másszóval: a programozó a rendelkezésre álló hardver(ek) összes elérhető funkcióját 100%-ig ki bírja használni.

[szerkesztés] Hátrányai:

  • Magát a programozást lényegesen nehezebb elsajátítani.
  • A komoly számítást igénylő feladatok elvégzése sok plusz munkát és hozzáértést igényel.
  • Vannak olyan eszközök, amelyek olyan alap matematikai műveleteket sem tartalmaznak mint a szorzás vagy osztás. Ezeket többnyire lekezeli a magas szintű programnyelv, ellenben az assemblyvel, ahol ezeket nekünk kell megírnunk mint eljárás.
  • Maga a forrás nehezebben átlátható (a sok ide-oda ugrálás miatt).
  • Platform-függő, azaz szorosan kötődik az adott processzorhoz és/vagy futtató szoftverhez. Emiatt sokszor csak a program teljes újraírásával lehet átvinni más futtató környezetre. (A környezet jelen esetben mind a processzor típusára, mind a futtató szoftveres környezetre értendő!)
  • Az optimalizálási előny hatályát veszti olyan rendszerekben, ahol kimagaslóan sok regiszter áll rendelkezésre a futtató processzorban, vagy sok processzor áll rendelkezésre a feladatok megosztására.

[szerkesztés] Használata napjainkban

Manapság legelterjedtebben mikrokontroller alapú rendszerekben alkamazzák, mivel ott sokszor maga a futtató eszköz és/vagy annak környezete nem teszi lehetővé magas szintű nyelvek alkalmazását vagy akár fordítóprogramok létrehozását (túl kevés támogatott utasítás, kis méretű memória illetve stack, stb.). Megjegyzendő azonban, hogy a mikrokontroller architektúrák robbanásszerű fejlődése eredményeképp erősen terjed a C, C++ nyelv használta is e téren.

"Nagyszámítógépes" környezetben (PC-k, munkaállomások stb.) a hardverillesztő szoftvert és az operációs rendszert programozók írnak assembly nyelven, más esetekben használata ritka, csak a nagyon méret – vagy időkritikus feladatoknál alkalmazzák.

[szerkesztés] Egy példa

Ez a példa (rutin) a Z80-as (Zilog Z80) mikroprocesszor assembly-jében íródott. Bájtok blokkját másolja át a memória (RAM) egyik helyéről (címéről) a másikra. Értelme a Sinclair ZX Spectrum számítógépen az, hogy a másolás a videomemória célterületére történik (a gyakorlatban arra használták, hogy a pl. egy sok számítást igénylő kép előállítása ezen a számítógépen sokáig tartott, s ha annak folyamatát a felhasználó elől el akarták rejteni, akkor először a memória egy használatlan területén állították elő a képet, majd ez – nagyon rövidke idő alatt – be lett másolva a videomemória területére. A megjegyzések pontosvesszővel vannak elválasztva a programkódtól.

       ld    hl, 16384      ; a hl regiszterpárba a videomemória első bajtjának címe kerül
       ld    bc, 6912       ; a bc regiszterpárba kerül az átmozgatott blokk hossza (a videomemória hossza) bájtban 
       ld    de, 40000      ; a de regiszterpárba a forráscím
loop   ld    a, (de)        ; az a regiszterbe a forrás értéke kerül
       ld    (hl), a        ; a hl regiszterpár értékének a címére a kiolvasott érték kerül
       inc   hl             ; célcím növelése eggyel
       inc   de             ; forráscím növelése eggyel
       dec   bc             ; a hátralévő hossz csökkentése
       ld    a, b           ; ez és a következő sor a vizsgálja, hogy a bc regiszterpár
       or    c              ; értéke 0
       jr    nz, loop       ; ha nem, ugrás vissza (a loop fejlécű sorra)
       ret                  ; visszatérés

Érdekes megfigyelni a tizenhat bites bc regiszterpár nullás értékének vizsgálátát egy nyolcbites regiszterrel, ami két lépésben történik. Először az ld a, b utasítással a b regiszter értéke (mely a bc regiszterpár egyik regisztere) az a regiszterbe töltődik, majd az or c utasítással az a és a c regiszter értékei közt or logikai utasítás hajtódik végre, melynek értéke az a regiszterbe kerül. Ha az eredmény éppen 0, az azt jelenti, hogy a bc regiszterpár értéke is éppen 0 és a jr nz, loop feltételes ugrás nem hajtódik végre (de egyébként igen).

A 8 bites processzorhoz képest fejlett utasításkészletnek köszönhetően az előző példát egyszerűbben is megírhatjuk (és gyorsabb lesz a végrehajtási sebesség is: előző esetben 52 órajel/bájt, következő esetben 21 órajel/bájt):

       ld    bc,6912     ;bc-ben a hossz bájtokban
       ld    de,40000    ;de-ben a forrásterület címe
       ld    hl,16384    ;hl-ben a célterület címe
       ldir              ;blokkmozgató utasítás automata ismétléssel (21 órajel átvitt bájtonkánt)
       ret

A játékokhoz korábban a végsőkig igénybevették a processzorok számítási teljesítményét. Pl a következő trükkel újabb 25%-nyi időt nyerhetünk (16,5 órajel/bájt):

       ld    b,0         ;számláló (0=256)
       ld    de,40000  
       ld    hl,16384
loop   ldi               ;blokkmozgató utasítás, nem ismétel (16 órajel)
       ldi
       .
       .
       .
       ldi               ;összesen 27 db ldi utasítás egymás után (27*256=6912)
       djnz  loop        ;b-t csökkenti és visszaugrik, ha b<>0 (13 órajel)
       ret


aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -