Szerelő

Szerelő
Az Assembler cikk szemléltető képe
Az első változat kelte 1949
Fájlkiterjesztés asm és s

Az összeállítási nyelv vagy az összeállítási nyelv a számítógépes programozásban az a legalacsonyabb szintű nyelv , amely emberi gépi nyelvet képvisel, olvasható formában. A gépi nyelvi bitek kombinációit úgynevezett „ memo ”  szimbólumok képviselik  , vagyis könnyen megjegyezhetők. Az összeszerelő program ezeket az emlékeztetőket gépi nyelvvé, valamint az értékeket (tizedesjegyekkel írva) binárisra, a helyek címkéit pedig címekké alakítja, például objektumfájl vagy futtatható fájl létrehozása céljából .

A jelenlegi gyakorlatban ugyanazt az assembler kifejezést használják mind az összeállítási nyelv, mind az azt lefordító összeállítási program megjelölésére. Így tehát „programozás az assemblerben” beszélünk.

A d műveletre jellemző a 'műveletre jellemző sok fordító által egyszerre és mindenkorra lefordított minden (változó) utasításban előforduló változónév a hozzá tartozó memóriahelyzettel és minden egyes (a felhasználó által tizedesjegyekkel írt) konstansra binárisra történő fordítás. name assembler ebben a konkrét esetben általában nem használatos.

Történelem

Az első rögzített programokkal rendelkező számítógép, az EDSAC (1949) programjait ábécé mnemonikával írták, egy-egy betűhöz minden utasításhoz. A fordítást ezután a programozók kézzel, hosszú, fárasztó és hibára hajlamos művelettel végezték el.

Az első összeszerelési programot Nathaniel Rochester írta az IBM 701-hez (az első IBM által kiadott számítógéphez ) 1954-ben.

Az összeszerelési nyelvek kiküszöbölik a számítógépek első generációjának programozói által elkövetett hibákat, mivel elengedik az utasítások numerikus kódjának memorizálását és a címszámításokat. Az összeállítás programozásával ezután mindenféle programot írtak.

Az 1970-1980-as években az assembler alkalmazási alkalmazások használatát nagymértékben kiszorította a magas szintű programozási nyelvek használata: Fortran , COBOL , PL / I stb. : a gépek ereje megengedte, és néhány perc számítógépes idő fordítása fordításra néhány órányi programozói idő megtakarítása érdekében nyereséges művelet volt, még akkor is, ha az akkori fordítók kevésbé hatékony (nagyobb és gyakran lassabb) kódot szolgáltattak. Ezenkívül ezek a magas szintű nyelvek lehetővé tették az egyetlen hardver architektúrától való függőség leküzdését.

Az operációs rendszerek írták assembly nyelven, amíg a bevezetése MCP hogy Burroughs 1961-ben, amit írt ESPOL, nyelvjárás Algol .

Az összeszerelő némileg visszatért az első mikrokomputerek mellett, ahol a technikai jellemzők (csökkent memória méret, alacsony számítási teljesítmény, sajátos memória architektúra stb.) Erős korlátokat szabtak meg, amihez hozzáteszik a pszichológiai szempontból fontos tényezőt, a "hobbi" hozzáállást a mikrokomputerek első felhasználói közül, akik nem voltak megelégedve a számítógéphez általában mellékelt értelmezett BASIC- szel írt programok lassúságával .

Nagy programokat írtak teljes egészében mikrokomputerek számára, például az IBM PC DOS operációs rendszerét (kb. 4000 sornyi kód) és a Lotus 1-2-3 táblázatot (rivális Multiplan-ját, amely már CP / M alatt létezett , C-ben írva . Az 1990-es években ez a legtöbb videó konzolos játék esetében is így volt (például a Mega Drive vagy a Super Nintendo esetében ).

Az összeszerelő sajátosságai

Egy adott nyelv minden processzorhoz

A gép nyelve az egyetlen nyelv, amelyet a processzor végrehajthat. Azonban a processzorok minden családja más és más utasításokat használ .

Például az x86 család processzora felismeri a következő típusú utasítást:

10110000 01100001

Az összeállítási nyelvben ezt az utasítást a programozó számára könnyebben érthető egyenérték képviseli:

movb $0x61,%al

(10110000 = movb% al
01100001 = 0x61 USD)

Ez azt jelenti: "írja be az AL regiszterbe a 97-es számot (az érték hexadecimálisan van megadva  : 61 16 = 97 10 ) ".

Így az összeszerelési nyelv, a gépi nyelv pontos ábrázolása az egyes processzor-architektúrákra jellemző . Ezenkívül több mnemonika vagy összeállítási nyelv szintaxiscsoport létezhet egyetlen utasításkészlethez, ezáltal makro-utasításokat hozva létre .

Szétszerelés

Az összeállítási kód átalakítását gépi nyelvvé egy összeállítási programnak nevezett program hajtja végre . A fordított műveletnek , nevezetesen az összeszerelőnek a gépkóddal egyenértékű megtalálásának neve van: szétszerelés .

Ellentétben azzal, amit gondolni lehet, nem mindig van egy-egy megfelelés ( bijection ) az összeszerelési kód és a gépi nyelv között. Egyes processzorokon a szétszerelés tehát olyan kódot eredményezhet, amelyet az ember nagyon nehezen érthet meg, miközben a számítógép tökéletesen lefordítható marad. A szétszerelés lehetetlenségének számos oka lehet: önmódosító kód használata, változó méretű utasítások, képtelenség megkülönböztetni a kódot és az adatokat stb. ( áthatolhatatlan kód )

Ráadásul sok, az összeállítási kódban található elem elvész a gépi nyelvre történő fordítás során. Amikor az assemblerben kódot hoz létre, a programozó neveket rendelhet a memóriában lévő helyekhez, megjegyzést fűzhet a kódjához , makro-utasításokat használhat, vagy használhatja az összeszereléskor feltételekkel generált kódot. Mindezek az elemek összeszereléskor redukálódnak arra, ami feltétlenül szükséges a gép számára, ezért szétszereléskor nem jelennek meg egyértelműen: például a memóriában egy helyet csak a numerikus címe vagy egy eltolása jelöli .

Gépi utasítások

Néhány alapvető művelet elérhető a legtöbb utasításkészletben.

  • Elmozdulás a memóriában:
    • érték betöltése egy regiszterbe;
    • értéket áthelyezünk egy memóriahelyről egy regiszterbe, és fordítva;
  • Számítás:
    • Emellett , vagy kivonás az értékek két nyilvántartások és terhelése az eredmény egy nyilvántartásban;
    • logikai műveletet (vagy bitenkénti műveletet) követő két regiszter értékeinek kombinációja ;
  • A program sorrendjének módosítása:
    • ugrás egy másik helyre a programban (általában az utasításokat egymás után hajtják végre, egymás után);
    • ugrás egy másik helyre, de miután elmentette a következő utasítás helyét, hogy visszatérhessen (visszatérési pont);
    • visszatérés az utolsó visszatérési ponthoz;
  • Összehasonlítás:
    • hasonlítsa össze két regiszter értékét.

És vannak konkrét utasítások egy vagy néhány utasítással a műveletekhez, amelyeknek sokat kellett volna vennie. Példák:

Közgyűlési nyelvű irányelvek

Amellett, hogy a kódoló gépi utasítások, szerelés nyelv van további irányelveket összeállító adatblokkot, és bízzák címeket utasításai meghatározásával címkéket.

Képesek meghatározni az egyes szerelvényeken kiértékelt szimbolikus kifejezéseket, így a kód még könnyebben olvasható és érthetőbb.

Rendszerint beépített makrónyelven rendelkeznek, hogy megkönnyítsék az összetett kódok vagy adatblokkok előállítását.

Egyszerű példák

Íme néhány egyszerű példa:

  • AT&T szintaxisban ( Linux számára a GNU assembler ( GAS ) számára írva );
  • az i386 utasításkészlet használatával  ;
  • az alábbiak szerint kell használni:
$ gcc foo.S -c -o foo.o $ ld foo.o -o foo $ ./foo

Helló megjelenítése

(A megjegyzések pontosvesszők után vannak)

str: .ascii "Bonjour\n" .global _start _start: movl $4, %eax movl $1, %ebx movl $str, %ecx movl $8, %edx int $0x80 movl $1, %eax movl $0, %ebx int $0x80 ;Compilation: ;as code.s -o code.o ;ld code.o -o code ;Execution: ;./code

Olvassa el a billentyűzetet (legfeljebb 16 karakter), majd jelenítse meg

# define N 16 .global _start .comm BUFF , N _start: mov $3 , %eax mov $0 , %ebx mov $BUFF , %ecx mov $N , %edx int $0x80 mov %eax , %edx mov $4 , %eax mov $1 , %ebx mov $BUFF , %ecx int $0x80 mov $1 , %eax mov $0 , %ebx int $0x80

Egyszerű példák, Intel x86 szintaxis

Itt vannak ugyanazok a példák, néhány különbséggel:

  • Intel x86 szintaxisban , a NASM összeállító számára írva  ;
  • az i386 utasításkészlet használatával  ;
  • az alábbiak szerint kell használni:
$ nasm -f elf foo.asm $ ld -o foo foo.o -melf_i386 $ ./foo

Mutass jó estét

(A megjegyzések pontosvesszők után vannak)

section .data ; Variables initialisées Buffer: db 'Bonsoir', 10 ; En ascii, 10 = '\n'. La virgule sert à concaténer les chaines BufferSize: equ $-Buffer ; Taille de la chaine section .text ; Le code source est écrit dans cette section global _start ; Définition de l'entrée du programme _start: ; Entrée du programme mov eax, 4 ; Appel de sys_write mov ebx, 1 ; Sortie standard STDOUT mov ecx, Buffer ; Chaine à afficher mov edx, BufferSize ; Taille de la chaine int 80h ; Interruption du kernel mov eax, 1 ; Appel de sys_exit mov ebx, 0 ; Code de retour int 80h ; Interruption du kernel


Olvassa el a billentyűzetet (legfeljebb 64 karakter), majd jelenítse meg

section .bss ; Section des variables non-initialisees Buffer: resb 64 ; Reservation de 64 blocs (octets ?) memoire pour la variable où sera stockee l'entree de l'utilisateur BufferSize: equ $-Buffer ; taille de cette variable section .text ; Section du code source global _start _start: ; Entree du programme mov eax, 3 ; Appel de sys_read mov ebx, 0 ; Entree standard STDIN mov ecx, Buffer ; Stockage de l'entree de l'utilisateur mov edx, BufferSize ; Taille maximale int 80h ; Interruption du kernel mov eax, 4 ; Appel de sys_write mov ebx, 1 ; Sortie standard STDOUT mov ecx, Buffer ; Chaine à afficher mov edx, BufferSize ; Taille de la chaine int 80h ; Interruption du kernel mov eax, 1 ; Appel de sys_exit mov ebx, 0 ; Code de retour int 80h ; Interruption du kernel

Az összeállítási nyelv használata

Viták folynak az összeállítási nyelv hasznosságáról. Sok esetben a fordítók - az optimalizálók átalakíthatják a magas szintű nyelvet olyan kódokká, amely ugyanolyan hatékonyan fut, mint egy nagyon jó programozó által kézzel írt szerelési kód, ugyanakkor még mindig sokkal könnyebb, gyorsabb (és ezért kevésbé hatékony). Drága) írni, olvasni és olvasni. fenntartani.

A hatékonyság már az ötvenes években aggodalomra ad okot, annak nyomát találjuk az Fortran nyelvkönyvében (1956-ban jelent meg) az IBM 704 számítógép számára  : A Fortran által gyártott objektumprogramok majdnem ugyanolyan hatékonyak lesznek, mint a jó programozók által írtak .

Az időközben az összeállítók óriási előrehaladást értek el, ezért nyilvánvaló, hogy a programok túlnyomó többsége gazdasági okokból ma már magas szintű nyelveken íródott, a további programozási költségek meghaladják a teljesítmény várható javulásából származó nyereséget.

Vannak azonban még mindig nagyon konkrét esetek, amikor az assembler használata még mindig indokolt:

  1. Néhány összetett, közvetlenül a assemblerben írt számítás, különösen a masszívan párhuzamos gépeken , gyorsabb lesz, a fordítók nem elég kifinomultak ahhoz, hogy kihasználják ezen architektúrák sajátosságait;
  2. Bizonyos rutinokat ( illesztőprogramokat ) néha könnyebb írni alacsony szintű nyelveken;
  3. Az operációs rendszer memóriaterületén végrehajtott, nagyon rendszerfüggő feladatokat időnként nehéz vagy akár lehetetlen magas szintű nyelven írni. Például azokat a szerelési utasításokat, amelyek lehetővé teszik a Windows számára az i386 és az azt követő mikroprocesszor feladatváltozásának kezelését (LGDT és LLDT), nem emulálhatják és nem generálhatják magas szintű nyelvek. Ezeket szükségszerűen egy rövid szerelési szubrutinban kell kódolni, amelyet egy magas szintű nyelven írt programból hívnak meg.

Egyes fordítók, ha a legmagasabb optimalizálási opciójuk nincs engedélyezve , a magas szintű nyelven írt programokat átalakító kódokká alakítják, mindegyik magas szintű utasítás szigorúan ekvivalens szerelési utasítások sorozatát eredményezi és ugyanazokat a szimbólumokat használja; ez lehetővé teszi a hibakeresés és profilalkotás céljából a kód megtekintését , ami időnként sokkal több időt takarít meg egy algoritmus átalakításával . Semmilyen körülmények között nem tarthatók meg ezek a technikák a végső optimalizáláshoz.

A beágyazott rendszerek programozása , gyakran mikrovezérlőkön alapul , hagyományos „rés” az összeszerelés programozásához. Valójában ezek a rendszerek gyakran nagyon korlátozott erőforrásokkal rendelkeznek (például egy PIC 16F84 mikrovezérlő 1024 14 bites utasításra korlátozódik, RAM-ja pedig 136 bájtot tartalmaz), ezért lehetőségeinek kiaknázásához nagyon optimalizált alacsony szintű programozást igényelnek. A hardver fejlődése miatt ezeknek a rendszereknek az alkatrészei állandó költség mellett és állandó energiafogyasztással egyre erőteljesebbé válnak, így a "bármelyik összeállítóba" történő beruházás sokkal drágább munkaidőben - ostobaság az erőfeszítés szempontjából. Általában az összeszerelés programozása sokkal hosszabb, kényesebb (mivel a programozónak figyelembe kell vennie a fejlesztés minden olyan mikrorészletét, amelytől a magas szintű nyelven tartózkodik), ezért lényegesen drágább, mint a magas szintű nyelvi programozás. Ezért csak azokra a helyzetekre kell fenntartani, amelyekhez másképp nem tehetünk.

Makrószerelő

Sok szerelő támogatja a makrók nyelvét . Kérdés, hogy több utasítást csoportosítsanak annak érdekében, hogy logikusabb és kevésbé fárasztó sorrend legyen.
Például (a Microsoft MASM assemblerben ):

putchar Macro car ; Prototype de la macro ifdef car ; si car est défini mov dl,car ; le mettre dans dl endif mov ah,2 ; ah=2 : fonction "putchar" en DOS int 21h ; appel au DOS endm ; fin macro

egy makró, amely egy karaktert jelenít meg az MS-DOS alatt . Például a következőképpen fogják használni:

putchar "X"

És ez generálja:

mov dl,"X" mov ah,2 int 21h

Ál-utasítások

Az álutasítás a makró utasítások speciális típusa. Ezt az összeszerelő szoftver szerkesztője előre definiálja, és feladata hiányzó processzor utasítások utánzása vagy egy meglévő utasítás használatának megkönnyítése. Mivel az ál-utasításnak nagyon hasonló neve van, mint egy valós processzor-utasításnak, első pillantásra lehetséges összekeverni az utóbbiak egyikével. Például előfordulhat, hogy egy RISC processzor nem rendelkezik JMP utasítással, amely lehetővé teszi, hogy a program egy adott pontjára ugorjon, és folytassa a sorrendben történő végrehajtását. Ebben az esetben a szoftverszerkesztő létrehozza a programozó számára a „JMP <parameter>” álutasítást, amelyet az összeszerelés során egy „mov pc , <parameter>” utasítás vált fel , a pc pedig a mutató utasítás lesz. végrehajtott. Egy másik példa, a „PUSH <paraméter>” pszeudo-utasítás helyébe a tárolása <paraméter> címen által mutatott sp előre csillapodás az utóbbi, sp hogy a stack pointer a processzor.

A RISC mikroprocesszorokon vagy mikrovezérlőkön, például az ARM családban , nincs olyan szerelési utasítás, amely lehetővé tenné azonnali konstans betöltését egy nyilvántartásba, függetlenül annak értékétől. A legtöbb összeszerelő ál-utasítással rendelkezik, amely a végrehajtási idő szempontjából a lehető leghatékonyabb módon teszi lehetővé az ilyen betöltést, megkímélve ezt a feladatot a programozó számára.

Strukturált programozás az assemblerben

Támogatás a strukturált programozáshoz  : a strukturált programozás egyes elemeit integráltuk a végrehajtás folyamatának kódolására Dr. HD Mills ( 1970 március), és Marvin Kessler hajtotta végre, aki kiterjesztette az S / 360 makró összeállítót if / else / endif és még áramlásszabályozó blokkokkal is. Ezzel csökkenthető vagy megszüntethető az átugrási műveletek használata az összeszerelő kódban.

Megjegyzések és hivatkozások

  1. Laurent Bloch , Bevezetés a programozásba a programmal , Éditions TECHNIP,2011( online olvasás ).

Lásd is