Gjuha assembler

Në fushën e informatikës, gjuha assembler (e njohur edhe si: kod simbolik i makinës) është një gjuhë programimi e nivelit të ulët që lidhet ngushtë me udhëzimet e kodit të makinës të arkitekturës përkatëse. Shpesh quhet thjesht assembly dhe shkurtohet si ASM ose asm. Në gjuhën e asamblerit, zakonisht çdo deklaratë përfaqëson një udhëzim të vetëm të kodit të makinës (raporti 1:1). Megjithatë, përveç udhëzimeve, zakonisht mbështeten edhe elementë shtesë si konstante, komente, direktiva të assembler-it, etiketa simbolike për regjistra ose adresa të kujtesës, si dhe makro-udhezime.

Kodi i parë i asamblesë në të cilin një gjuhë përdoret për të përfaqësuar udhëzimet e kodit të makinës gjendet në veprën e Kathleen dhe Andrew Donald Booth të vitit 1947, Coding for ARC.  Kodi i asamblesë shndërrohet në kod makine të ekzekutueshëm nga një program i dobishëm i referuar si asambler. Termi "asambler" i atribuohet përgjithësisht Wilkes, Wheeler dhe Gill në librin e tyre të vitit 1951 Përgatitja e Programeve për një Kompjuter Elektronik Dixhital,  të cilët, megjithatë, e përdorën termin për të nënkuptuar "një program që asamble një program tjetër që përbëhet nga disa seksione në një program të vetëm". Procesi i konvertimit quhet asamble, si në asamblenë e kodit burimor. Hapi llogaritës kur një asambler po përpunon një program quhet koha e assemblerit.

Meqenëse gjuha e asamblerit bazohet drejtpërdrejt në udhëzimet e kodit të makinës, çdo gjuhë e tillë është e lidhur ngushtë me arkitekturën specifike të kompjuterit ku përdoret. Për shembull, ekzistojnë variante të veçanta për arkitektura si x86 apo ARM.

Në disa raste, për të njëjtën arkitekturë ekzistojnë më shumë se një assembler, ndërsa në raste të tjera një assembler mund të jetë i përshtatur posaçërisht për një sistem operativ të caktuar. Shumica e gjuhëve të asamblimit nuk ofrojnë sintaksë të veçantë për thirrjet e sistemit operativ, por mund të përdoren në mënyrë universale me çdo sistem operativ, pasi ato japin qasje të drejtpërdrejtë në funksionet reale të procesorit, mbi të cilat mbështeten mekanizmat e thirrjeve të sistemit. Në kontrast me gjuhët e asamblimit, gjuhët e programimit të nivelit të lartë janë zakonisht të bartshme në arkitektura të ndryshme, por kërkojnë interpretim ose kompilim – procese më të ndërlikuara sesa përpilimi i kodit të asamblimit.

Në dekadat e para të zhvillimit të kompjuterëve, ishte praktikë e zakonshme që si programimi i sistemeve ashtu edhe ai i aplikacioneve të realizoheshin plotësisht në gjuhën e asamblimit. Edhe pse kjo gjuhë mbetet e pazëvendësueshme për disa funksione specifike, sot pjesa më e madhe e programimit kryhet në gjuhë të nivelit më të lartë, të cilat interpretohen ose kompilohen. Në veprën e tij No Silver Bullet, Fred Brooks përshkroi ndikimin e kalimit nga programimi në asamblim drejt gjuhëve të nivelit të lartë: sipas tij, përdorimi progresiv i këtyre gjuhëve ka qenë faktori më i fuqishëm për rritjen e produktivitetit, besueshmërisë dhe thjeshtësisë së softuerit. Shumica e studiuesve e vlerësojnë këtë zhvillim si një rritje të produktivitetit të paktën pesëfish, e shoqëruar me përmirësime të dukshme në besueshmëri, thjeshtësi dhe kuptueshmëri.

Në ditët e sotme, përdorimi i gjuhës së asamblimit kufizohet zakonisht në segmente të vogla brenda sistemeve më të mëdha të shkruara në gjuhë të nivelit të lartë. Kjo bëhet kryesisht për arsye performance ose për të komunikuar drejtpërdrejt me pajisjen në mënyra që gjuhët e nivelit të lartë nuk i mbështesin. Si shembull, në versionin 4.9 të kernelit të Linux-it, më pak se 2% e kodit burimor është i shkruar në asamblim, ndërsa mbi 97% është i shkruar në gjuhën C.

 Sintaksa e gjuhës së asamblesë 
Gjuha e asamblimit përdor mnemonikë për të përfaqësuar udhëzimet e nivelit të ulët të makinës, direktivat, si dhe elementë të tjerë të arkitekturës si regjistrat dhe flamujt. Disa mnemonikë janë të paracaktuar nga sistemi, ndërsa të tjerë mund të përcaktohen nga vetë programuesi. Shumë operacione kërkojnë një ose më shumë operanda për të formuar një udhëzim të plotë.                                                                Assemblerët zakonisht lejojnë përdorimin e konstanteve të emërtuara, regjistrave dhe etiketave për programin dhe vendndodhjet e kujtesës, si dhe mund të kryejnë llogaritje për operandët. Kjo i shpëton programuesit nga llogaritjet e përsëritura dhe e bën kodin e asamblimit shumë më të lexueshëm sesa kodi i makinës. Në varësi të arkitekturës, këto elemente mund të kombinohen për udhëzime specifike ose mënyra adresimi, duke përdorur zhvendosje, të dhëna shtesë ose adresa fikse. Shumë assemblerë ofrojnë gjithashtu mekanizma shtesë për të lehtësuar zhvillimin e programeve, për të kontrolluar procesin e përpilimit dhe për të ndihmuar në debugim.

Disa gjuhë asamblimi janë të orientuara sipas kolonave, ku fushat vendosen në kolona të caktuara; kjo ishte shumë e zakonshme në makinat që përdornin kartat e shpuara gjatë viteve 1950 dhe fillimit të viteve 1960.                                                                                              Të tjera assemblerë përdorin sintaksë të lirë, ku fushat ndahen me ndarës si shenjat e pikësimit ose hapësirat. Ekzistojnë edhe forma hibride, ku p.sh. . etiketat vendosen në një kolonë të caktuar, ndërsa fushat e tjera ndahen me ndarës. Ky stil u bë më i zakonshëm se sintaksa e orientuar sipas kolonave gjatë viteve 1960.

 Terminologjia 

 Një makro asembler është një asembler që përfshin një strukturë makroinstruksionesh në mënyrë që teksti (i parametrizuar) i gjuhës assembler të mund të përfaqësohet nga një emër, dhe ky emër mund të përdoret për të futur tekstin e zgjeruar në kod tjetër.
 Kodi i hapur i referohet çdo inputi të assemblerit jashtë një përkufizimi makro.
 Një cross-assembler (shih gjithashtu cross compiler ) është një asembler që ekzekutohet në një kompjuter ose sistem operativ (sistemi pritës ) të një lloji të ndryshëm nga sistemi në të cilin do të ekzekutohet kodi që rezulton ( sistemi i synuar ). Cross-assembler lehtëson zhvillimin e programeve për sisteme që nuk kanë burimet për të mbështetur zhvillimin e softuerit, siç është një sistem i ngulitur ose një mikrokontrollues. Në një rast të tillë, kodi objekt që rezulton duhet të transferohet në sistemin e synuar, nëpërmjet memories vetëm për lexim (ROM, EPROM, etj.), një programuesi (kur memoria vetëm për lexim është e integruar në pajisje, si në mikrokontrollues), ose një lidhjeje të dhënash duke përdorur ose një kopje të saktë bit-për-bit të kodit objekt ose një përfaqësim të bazuar në tekst të atij kodi ( siç është Intel hex ose Motorola S-record ).
 Një asembler i nivelit të lartë është një program që ofron abstraksione gjuhësore që më shpesh shoqërohen me gjuhë të nivelit të lartë, siç janë strukturat e kontrollit të avancuara ( IF/THEN/ELSE, DO CASE, etj.) dhe llojet e të dhënave abstrakte të nivelit të lartë, duke përfshirë strukturat/regjistrimet, bashkimet, klasat dhe bashkësitë.
 Një mikroasembler është një program që ndihmon në përgatitjen e një mikroprogrami për të kontrolluar funksionimin e nivelit të ulët të një kompjuteri.
 Një meta-assembler është "një program që pranon përshkrimin sintaksor dhe semantik të një gjuhe assembler dhe gjeneron një assembler për atë gjuhë", ose që pranon një skedar burimor assembler së bashku me një përshkrim të tillë dhe assembler skedarin burimor në përputhje me atë përshkrim. Assemblerët "Meta-Symbol" për serinë e kompjuterëve SDS 9 dhe SDS Sigma janë meta-assemblerë. Sperry Univac gjithashtu ofroi një Meta-Assembler për serinë UNIVAC 1100/2200 .
 Asambleri inline (ose asambleri i integruar ) është kodi i asamblerit që përmbahet brenda një programi gjuhësor të nivelit të lartë.  Ky përdoret më shpesh në programet e sistemeve që kanë nevojë për qasje të drejtpërdrejtë në harduer.

 Konceptet kryesore 

 Asambler 
Një program assembler krijon kod objekt duke përkthyer kombinimet e mnemonikëve dhe sintaksës për operacionet dhe mënyrat e adresimit në ekuivalentët e tyre numerikë. Ky përfaqësim zakonisht përfshin një kod operacioni (opcode) si dhe bitë kontrolli dhe të dhëna të tjera. Assembleri gjithashtu llogarit shprehjet konstante dhe zgjidh emrat simbolikë për vendndodhjet e kujtesës dhe entitete të tjera. Përdorimi i referencave simbolike është një veçori kryesore e assemblerëve, pasi shmang llogaritjet e lodhshme dhe përditësimet manuale të adresave pas ndryshimeve në program.                                                        Shumica e assemblerëve përfshijnë edhe mekanizma të makrove, të cilat lejojnë zëvendësimin tekstual – për shembull, për të gjeneruar sekuenca të shkurtra udhëzimesh si kod inline, në vend që të thirren si nënprograme të veçanta.

Disa asemblerë mund të jenë gjithashtu në gjendje të kryejnë disa lloje të thjeshta optimizimesh specifike për setin e udhëzimeve. Një shembull konkret i kësaj mund të jenë asemblerët x86 të kudondodhur nga shitës të ndryshëm. Të quajtur "jump-sizing", shumica e tyre janë në gjendje të kryejnë zëvendësime të instruksioneve "jump-in" (kërcime të gjata të zëvendësuara nga kërcime të shkurtra ose relative) në çdo numër kalimesh, sipas kërkesës. Të tjerë madje mund të bëjnë rirregullim ose futje të thjeshtë të instruksioneve, siç janë disa asemblerë për arkitekturat RISC që mund të ndihmojnë në optimizimin e një planifikimi të arsyeshëm të instruksioneve për të shfrytëzuar tubacionin e CPU-së sa më efikas të jetë e mundur. 

Asamblerët kanë qenë të disponueshëm që nga vitet 1950, si hapi i parë mbi gjuhën e makinës dhe përpara gjuhëve të programimit të nivelit të lartë si Fortran, Algol, COBOL dhe Lisp. Ka pasur gjithashtu disa klasa përkthyesish dhe gjeneratorësh kodi gjysmë-automatikë me veti të ngjashme si me gjuhët e asamblesë ashtu edhe me ato të nivelit të lartë, me Speedcode si ndoshta një nga shembujt më të njohur.

Mund të ketë disa asemblerë me sintaksë të ndryshme për një arkitekturë të caktuar CPU-je ose grupi udhëzimesh. Për shembull, një udhëzim për të shtuar të dhëna memorieje në një regjistër në një procesor të familjes x86 mund të jetë add eax,[ebx], në sintaksën origjinale të Intel, ndërsa kjo do të shkruhej addl (%ebx),%eax në sintaksën AT&amp;T të përdorur nga GNU Assembler. Pavarësisht pamjeve të ndryshme, format e ndryshme sintaksore në përgjithësi gjenerojnë të njëjtin kod numerik makine. Një asembler i vetëm mund të ketë gjithashtu mënyra të ndryshme në mënyrë që të mbështesë variacionet në format sintaksore, si dhe interpretimet e tyre të sakta semantike (si sintaksa FASM, sintaksa TASM, mënyra ideale, etj., në rastin e veçantë të programimit të asamblesë x86 ).

 Numri i kalimeve 
Ekzistojnë dy lloje asemblerësh bazuar në numrin e kalimeve nëpër burim ( sa herë asembleri e lexon burimin ) për të prodhuar skedarin e objektit.

 Asamblerët me një kalim të vetëm e përpunojnë kodin burimor një herë. Për simbolet e përdorura para se të përcaktohen, asambleri do të lëshojë "gabime" pas përkufizimit përfundimtar, duke i thënë lidhësit ose ngarkuesit të shënojë vendet ku janë përdorur simbolet ende të pacaktuara.
 Asamblerët me shumë kalime krijojnë një tabelë me të gjitha simbolet dhe vlerat e tyre në kalimet e para, pastaj e përdorin tabelën në kalimet e mëvonshme për të gjeneruar kod.

Në të dyja rastet, asembleri duhet të jetë në gjendje të përcaktojë madhësinë e secilit udhëzim në kalimet fillestare në mënyrë që të llogarisë adresat e simboleve pasuese. Kjo do të thotë që nëse madhësia e një operacioni që i referohet një operandi të përcaktuar më vonë varet nga lloji ose distanca e operandit, asembleri do të bëjë një vlerësim pesimist kur të hasë për herë të parë operacionin dhe, nëse është e nevojshme, do ta mbushë atë me një ose më shumë udhëzime " pa operacion " në një kalim të mëvonshëm ose me gabime. Në një asembler me optimizim të vrimave të shikimit, adresat mund të rillogariten midis kalimeve për të lejuar zëvendësimin e kodit pesimist me kod të përshtatur për distancën e saktë nga objektivi.

Arsyeja origjinale për përdorimin e asamblerëve me një kalim ishte madhësia e memories dhe shpejtësia e asamblesë - shpesh një kalim i dytë do të kërkonte ruajtjen e tabelës së simboleve në memorie ( për të trajtuar referencat përpara ), rikthimin dhe rileximin e burimit të programit në shirit, ose rileximin e një pakete letrash ose shiriti letre të shpuar. Kompjuterët e mëvonshëm me memorie shumë më të mëdha ( sidomos ruajtja e diskut ), kishin hapësirën për të kryer të gjithë përpunimin e nevojshëm pa një rilexim të tillë. Avantazhi i asamblerit me shumë kalime është se mungesa e gabimeve e bën procesin e lidhjes ( ose ngarkimin e programit nëse asambleri prodhon drejtpërdrejt kodin e ekzekutueshëm ) më të shpejtë. 

Shembull: në fragmentin e mëposhtëm të kodit, një asambler me një kalim do të ishte në gjendje të përcaktonte adresën e referencës së prapme BKWD kur asamble deklaratën S2, por nuk do të ishte në gjendje të përcaktonte adresën e referencës së përparme FWD kur asamble deklaratën e degës S1; në të vërtetë, FWD mund të jetë i padefinuar. Një asambler me dy kalime do të përcaktonte të dy adresat në kalimin 1, kështu që ato do të njiheshin kur gjeneronte kod në kalimin 2.
 S1   B    FWD
   ...
 FWD   EQU *
   ...
 BKWD  EQU *
   ...
 S2    B   BKWD

 Montues të nivelit të lartë 
Asamblerët më të sofistikuar të nivelit të lartë ofrojnë abstraksione gjuhësore të tilla si:

 Deklaratat dhe thirrjet e procedurave/funksioneve të nivelit të lartë
 Struktura të avancuara kontrolli ( NËSE/ATËHERË/PËRNDRYSHE, NDËRRO. )
 Llojet e të dhënave abstrakte të nivelit të lartë, duke përfshirë strukturat/regjistrimet, bashkimet, klasat dhe bashkësitë.
 Përpunim i sofistikuar makro ( megjithëse i disponueshëm në montuesit e zakonshëm që nga fundi i viteve 1950 për, p.sh., serinë IBM 700 dhe serinë IBM 7000, dhe që nga vitet 1960 për IBM System/360 ( S/360 ), ndër makina të tjera. )
 Karakteristikat e programimit të orientuar nga objektet, të tilla si klasat, objektet, abstraksioni, polimorfizmi dhe trashëgimia. 

Shihni Dizajnin e Gjuhës më poshtë për më shumë detaje.

 Gjuha e assemblerit 
Një program i shkruar në gjuhën assembly përbëhet nga një seri udhëzimesh mnemonike të procesorit dhe meta-deklaratash ( të njohura ndryshe si operacione deklarative, direktiva, pseudo-udhëzime, pseudo-operacione dhe pseudo-operacione ), komente dhe të dhëna. Udhëzimet në gjuhën assembly zakonisht përbëhen nga një mnemonik i kodit op të ndjekur nga një operand, i cili mund të jetë një listë e të dhënave, argumenteve ose parametrave. Disa udhëzime mund të jenë "të nënkuptuara", që do të thotë se të dhënat mbi të cilat vepron udhëzimi përcaktohen në mënyrë implicite nga vetë udhëzimi - një udhëzim i tillë nuk merr një operand. Deklarata që rezulton përkthehet nga një assembler në udhëzime në gjuhën e makinës që mund të ngarkohen në memorie dhe të ekzekutohen.

Për shembull, udhëzimi më poshtë i tregon një procesori x86 / IA-32 që të zhvendosë menjëherë një vlerë 8-bitëshe në një regjistër. Kodi binar për këtë udhëzim është 10110 i ndjekur nga një identifikues 3-bitësh për të cilin regjistër duhet të përdoret. Identifikuesi për regjistrin AL është 000, kështu që kodi i mëposhtëm i makinës ngarkon regjistrin AL me të dhënat 01100001. 
 10110000 01100001
Ky kod binar kompjuterik mund të bëhet më i lexueshëm nga njeriu duke e shprehur atë në heksadecimal si më poshtë.
 B0 61
Këtu, B0 do të thotë "Zhvendos një kopje të vlerës së mëposhtme në AL ", dhe 61 është një përfaqësim heksadecimal i vlerës 01100001, e cila është 97 në sistemin dhjetor. Gjuha e asamblesë për familjen 8086 ofron mnemonikën MOV ( një shkurtim i move ) për udhëzime të tilla si kjo, kështu që kodi i makinës më sipër mund të shkruhet si më poshtë në gjuhën e asamblesë, i plotësuar me një koment shpjegues nëse kërkohet, pas pikëpresjes. Kjo është shumë më e lehtë për t'u lexuar dhe për t'u mbajtur mend.MOV AL, 61h    ; Load AL with 97 decimal (61 hex)Në disa gjuhë asambleri ( përfshirë këtë ), e njëjta mnemonikë, siç është MOV, mund të përdoret për një familje udhëzimesh të lidhura për ngarkimin, kopjimin dhe zhvendosjen e të dhënave, qofshin këto vlera të menjëhershme, vlera në regjistra ose vendndodhje memorieje të treguara nga vlerat në regjistra ose nga adresa të menjëhershme ( të njohura edhe si adresa të drejtpërdrejta ). Asamblerë të tjerë mund të përdorin mnemonikë të veçantë të opkodit, siç është L për "zhvendos memorien në regjistër", ST për "zhvendos regjistrin në memorie", LR për "zhvendos regjistrin në regjistër", MVI për "zhvendos operandin e menjëhershëm në memorie", etj.

Nëse e njëjta mnemonikë përdoret për udhëzime të ndryshme, kjo do të thotë që mnemonika korrespondon me disa kode të ndryshme binare udhëzimesh, duke përjashtuar të dhënat ( p.sh. 61h në këtë shembull ), varësisht nga operandët që ndjekin mnemonikën. Për shembull, për CPU-të x86/IA-32, sintaksa e gjuhës së asamblesë Intel MOV AL, AH përfaqëson një udhëzim që zhvendos përmbajtjen e regjistrit AH në regjistrin AL. Forma heksadecimale  e këtij udhëzimi është:
 88 E0
Bajti i parë, 88h, identifikon një lëvizje midis një regjistri me madhësinë e një bajti dhe një regjistri ose memorieje tjetër, dhe bajti i dytë, E0h, është i koduar ( me tre fusha biti ) për të specifikuar që të dy operandët janë regjistra, burimi është AH dhe destinacioni është AL.

Në një rast si ky, ku e njëjta mnemonikë mund të përfaqësojë më shumë se një udhëzim binar, asembleri përcakton se cilin udhëzim të gjenerojë duke shqyrtuar operandët. Në shembullin e parë, operandi 61h është një konstante numerike heksadecimale e vlefshme dhe nuk është një emër i vlefshëm regjistri, kështu që vetëm udhëzimi B0 mund të jetë i zbatueshëm. Në shembullin e dytë, operandi AH është një emër i vlefshëm regjistri dhe jo një konstante numerike e vlefshme (heksadecimal, dhjetor, oktal ose binare), kështu që vetëm udhëzimi 88 mund të jetë i zbatueshëm.

Gjuhët e assemblerit janë gjithmonë të dizajnuara në mënyrë që ky lloj mungese paqartësie të zbatohet universalisht nga sintaksa e tyre. Për shembull, në gjuhën e asamblesë Intel x86, një konstante heksadecimale duhet të fillojë me një shifër numerike, në mënyrë që numri heksadecimal 'A' ( i barabartë me dhjetë dhjetore) të shkruhet si 0Ah ose 0AH, jo AH, konkretisht në mënyrë që të mos duket se është emri i regjistrit AH. ( I njëjti rregull parandalon gjithashtu paqartësinë me emrat e regjistrave BH, CH dhe DH, si dhe me çdo simbol të përcaktuar nga përdoruesi që mbaron me shkronjën H dhe përndryshe përmban vetëm karaktere që janë shifra heksadecimale, siç është fjala "BEACH". )

Duke u kthyer te shembulli origjinal, ndërsa opcode x86 10110000 ( B0 ) kopjon një vlerë 8-bitëshe në regjistrin AL, 10110001 ( B1 ) e zhvendos atë në CL dhe 10110010 ( B2 ) e bën këtë në DL. Shembuj të gjuhës assembly për këto vijojnë. MOV AL, 1h    ; Load AL with immediate value 1
MOV CL, 2h    ; Load CL with immediate value 2
MOV DL, 3h    ; Load DL with immediate value 3Sintaksa e MOV mund të jetë gjithashtu më komplekse siç tregojnë shembujt e mëposhtëm. MOV EAX, [EBX]	 ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX
MOV DS, DX    ; Move the contents of DX into segment register DSNë secilin rast, mnemonika MOV përkthehet direkt në një nga opkodet 88-8C, 8E, A0-A3, B0-BF, C6 ose C7 nga një asambler, dhe programuesi normalisht nuk ka nevojë ta dijë ose ta mbajë mend se cilin. 

Transformimi i gjuhës së asamblerit në kod makine është puna e një asambleri, dhe e kundërta mund të arrihet të paktën pjesërisht nga një çmontues. Ndryshe nga gjuhët e nivelit të lartë, ekziston një korrespondencë një-me-një midis shumë deklaratave të thjeshta të asamblerit dhe udhëzimeve të gjuhës së makinës. Megjithatë, në disa raste, një asambler mund të ofrojë pseudo-udhëzime ( në thelb makro ) të cilat zgjerohen në disa udhëzime të gjuhës së makinës për të ofruar funksionalitete të nevojshme zakonisht. Për shembull, për një makinë që i mungon një udhëzim "degëzim nëse është më i madh ose i barabartë", një asambler mund të ofrojë një pseudo-udhëzim që zgjerohet në "vendoset nëse është më i vogël se" dhe "degëzim nëse është zero ( në rezultatin e udhëzimit të vendosur )" të makinës. Shumica e asamblerëve me funksione të plota ofrojnë gjithashtu një gjuhë të pasur makro ( të diskutuar më poshtë ) e cila përdoret nga shitësit dhe programuesit për të gjeneruar kod dhe sekuenca të dhënash më komplekse. Meqenëse informacioni në lidhje me pseudoinstruksionet dhe makrot e përcaktuara në mjedisin e asamblerit nuk është i pranishëm në programin e objektit, një çmontues nuk mund të rindërtojë thirrjet e makros dhe pseudoinstruksionit, por mund të çmontojë vetëm udhëzimet aktuale të makinës që asambleri gjeneroi nga ato entitete abstrakte të gjuhës së asamblerit. Po kështu, meqenëse komentet në skedarin burimor të gjuhës së asamblerit injorohen nga asambleri dhe nuk kanë efekt në kodin objektor që gjeneron, një çmontues është gjithmonë plotësisht i paaftë të rikuperojë komentet burimore.

Çdo arkitekturë kompjuteri ka gjuhën e vet të makinës. Kompjuterët ndryshojnë në numrin dhe llojin e operacioneve që mbështesin, në madhësitë dhe numrat e ndryshëm të regjistrave, si dhe në përfaqësimet e të dhënave në memorie. Ndërsa shumica e kompjuterëve me qëllim të përgjithshëm janë në gjendje të kryejnë në thelb të njëjtën funksionalitet, mënyrat se si e bëjnë këtë ndryshojnë; gjuhët përkatëse të asamblesë pasqyrojnë këto ndryshime.

Për një grup të vetëm udhëzimesh mund të ekzistojnë grupe të shumëfishta mnemonikësh ose sintakse në gjuhën assembly, të cilat zakonisht instancohen në programe të ndryshme assembler. Në këto raste, më i popullarizuari është zakonisht ai që ofrohet nga prodhuesi i CPU-së dhe përdoret në dokumentacionin e tij.

Dy shembuj të CPU-ve që kanë dy grupe të ndryshme mnemonikësh janë familja Intel 8080 dhe Intel 8086/8088. Meqenëse Intel pretendoi të drejtat e autorit mbi mnemonikën e gjuhës së saj të asamblesë ( të paktën në secilën faqe të dokumentacionit të tyre të botuar në vitet 1970 dhe në fillim të viteve 1980 ), disa kompani që prodhuan në mënyrë të pavarur CPU të pajtueshme me grupet e udhëzimeve të Intel shpikën mnemonikën e tyre. CPU Zilog Z80, një përmirësim i Intel 8080A, mbështet të gjitha udhëzimet 8080A plus shumë të tjera; Zilog shpiku një gjuhë krejtësisht të re asambleje, jo vetëm për udhëzimet e reja, por edhe për të gjitha udhëzimet 8080A. Për shembull, aty ku Intel përdor mnemonikët MOV, MVI, LDA, STA, LXI, LDAX, STAX, LHLD dhe SHLD për udhëzime të ndryshme të transferimit të të dhënave, gjuha e asamblesë Z80 përdor mnemonikën LD për të gjitha ato. Një rast i ngjashëm janë CPU-të NEC V20 dhe V30, kopje të përmirësuara të Intel 8086 dhe 8088, përkatësisht. Ashtu si Zilog me Z80, NEC shpiku mnemonikë të rinj për të gjitha udhëzimet 8086 dhe 8088, për të shmangur akuzat për shkelje të të drejtave të autorit të Intel. ( Është e dyshimtë nëse të drejta të tilla të autorit mund të jenë të vlefshme, dhe më vonë kompanitë e CPU-ve si AMD  dhe Cyrix ribotuan mnemonikën e udhëzimeve x86/IA-32 të Intel pikërisht pa leje dhe as pa dënim ligjor. ) Është e dyshimtë nëse në praktikë shumë njerëz që programuan V20 dhe V30 shkruan në të vërtetë në gjuhën e asamblesë të NEC dhe jo në atë të Intel; meqenëse çdo dy gjuhë asambleje për të njëjtën arkitekturë të grupit të udhëzimeve janë izomorfike (disi si anglishtja dhe latinishtja Pig ), nuk ka kërkesë për të përdorur gjuhën e asamblesë të publikuar nga prodhuesi me produktet e atij prodhuesi.

 "Përshëndetje, botë!" në x86 Linux 
Në gjuhën e asamblesë 32-bit për Linux në një procesor x86, "Përshëndetje, botë!" mund të printohet kështu.section	.text    ; start of the code segment
  global _start  ; declare _start to be visible in the generated object file

_start:	    
  mov	edx,len   ; length of string, third argument to write()
  mov	ecx,msg   ; address of string, second argument to write()
  mov	ebx,1    ; file descriptor (standard output), first argument to write()
  mov	eax,4    ; system call number for write()
  int	0x80    ; system call trap

  mov	ebx,0    ; exit code, first argument to exit()
  mov	eax,1    ; system call number for exit()
  int	0x80    ; system call trap

section	.data    ; start of data segment
msg db 'Hello, world!', 0xa ; 14 bytes of data
len equ $ - msg   ; the value 14 as a constant calculated at compile time

 Dizajni i gjuhës 

 Elementet bazë 
Ekziston një shkallë e madhe diversiteti në mënyrën se si autorët e asamblerëve i kategorizojnë deklaratat dhe në nomenklaturën që përdorin. Në veçanti, disa përshkruajnë çdo gjë tjetër përveç një mnemonike makine ose mnemonike të zgjeruar si një pseudo-operacion ( pseudo-operacion ). Një gjuhë tipike asambleje përbëhet nga 3 lloje deklaratash udhëzimi që përdoren për të përcaktuar operacionet e programit:

 Mnemonikë të kodit të opsionit
 Përkufizimet e të dhënave
 Direktivat e Asamblesë

 Mnemonikë Opcode dhe mnemonikë e zgjeruar 
Udhëzimet ( deklaratat ) në gjuhën e asamblerit janë përgjithësisht shumë të thjeshta, ndryshe nga ato në gjuhët e nivelit të lartë. Në përgjithësi, një mnemonik është një emër simbolik për një udhëzim të vetëm të ekzekutueshëm në gjuhën e makinës ( një opcode ), dhe ekziston të paktën një mnemonik opcode i përcaktuar për secilin udhëzim në gjuhën e makinës. Çdo udhëzim zakonisht përbëhet nga një operacion ose opcode plus zero ose më shumë operandë. Shumica e udhëzimeve i referohen një vlere të vetme ose një çifti vlerash. Operandet mund të jenë të menjëhershme ( vlera e koduar në vetë udhëzimin ), regjistra të specifikuar në udhëzim ose të nënkuptuar, ose adresat e të dhënave të vendosura diku tjetër në ruajtje. Kjo përcaktohet nga arkitektura themelore e procesorit: asambleri thjesht pasqyron se si funksionon kjo arkitekturë. Mnemonikët e zgjeruara përdoren shpesh për të specifikuar një kombinim të një opcode me një operand specifik, p.sh., asamblerët System/360 përdorin  si një mnemonik të zgjeruar për  me një maskë prej 15 dhe  ( "NO OPeration" - mos bëj asgjë për një hap ) për  me një maskë prej 0.

Mnemonikët e zgjeruara përdoren shpesh për të mbështetur përdorime të specializuara të instruksioneve, shpesh për qëllime që nuk janë të qarta nga emri i instruksionit. Për shembull, shumë CPU nuk kanë një instruksion të qartë NOP, por kanë instruksione që mund të përdoren për këtë qëllim. Në CPU-të 8086, instruksioni  përdoret për , ku  është një pseudo-opcode për të koduar instruksionin  . Disa çmontues e njohin këtë dhe do ta deshifrojnë  si . Në mënyrë të ngjashme, asamblerët e IBM për System/360 dhe System/370 përdorin mnemonikën e zgjeruar  dhe  për  dhe  me maska zero. Për arkitekturën SPARC, këto njihen si instruksione sintetike. 

Disa asemblerë mbështesin gjithashtu makro-instruksione të thjeshta të integruara që gjenerojnë dy ose më shumë udhëzime makine. Për shembull, me disa asemblerë Z80, instruksioni  njihet për të gjeneruar  të ndjekur nga .  Këto nganjëherë njihen si pseudo-opkode .

Mnemonikët janë simbole arbitrare; në vitin 1985, IEEE publikoi Standardin 694 për një grup uniform mnemonikësh që do të përdoren nga të gjithë asamblerët.  Standardi është tërhequr që atëherë.

 Direktivat e të dhënave 
Ekzistojnë udhëzime të përdorura për të përcaktuar elementët e të dhënave për të mbajtur të dhëna dhe variabla. Ato përcaktojnë llojin e të dhënave, gjatësinë dhe rreshtimin e të dhënave. Këto udhëzime gjithashtu mund të përcaktojnë nëse të dhënat janë të disponueshme për programe të jashtme ( të mbledhura veçmas ) apo vetëm për programin në të cilin është përcaktuar seksioni i të dhënave. Disa asemblerë i klasifikojnë këto si pseudo-operacione.

 Direktivat e Assemblerit 
Direktivat e asamblerit, të quajtura edhe pseudo-opcode, pseudo-operacione ose pseudo-ops, janë komanda të dhëna një asambleri "që e drejtojnë atë të kryejë operacione të tjera përveç udhëzimeve të asamblerit". Direktivat ndikojnë në mënyrën se si funksionon asambleri dhe "mund të ndikojnë në kodin e objektit, tabelën e simboleve, skedarin e listës dhe vlerat e parametrave të brendshëm të asamblerit". Ndonjëherë termi pseudo-opcode është i rezervuar për direktivat që gjenerojnë kod objekti, të tilla si ato që gjenerojnë të dhëna. 

Emrat e pseudo-operacioneve shpesh fillojnë me një pikë për t'i dalluar ato nga udhëzimet e makinës. Pseudo-operacionet mund ta bëjnë montimin e programit të varur nga parametrat e futur nga një programues, në mënyrë që një program të mund të montohet në mënyra të ndryshme, ndoshta për aplikacione të ndryshme. Ose, një pseudo-operacion mund të përdoret për të manipuluar prezantimin e një programi për ta bërë më të lehtë leximin dhe mirëmbajtjen. Një përdorim tjetër i zakonshëm i pseudo-operacioneve është rezervimi i zonave të ruajtjes për të dhënat e kohës së ekzekutimit dhe opsionalisht inicializimi i përmbajtjes së tyre në vlera të njohura.

Asamblerët simbolikë i lejojnë programuesit të shoqërojnë emra arbitrarë ( etiketa ose simbole ) me vendndodhje të memories dhe konstante të ndryshme. Zakonisht, çdo konstante dhe variabël i jepet një emër në mënyrë që udhëzimet të mund t'i referohen këtyre vendndodhjeve me emër, duke promovuar kështu kodin vetë-dokumentues. Në kodin ekzekutues, emri i secilës nënprogram shoqërohet me pikën e saj të hyrjes, kështu që çdo thirrje në një nënprogram mund të përdorë emrin e saj. Brenda nënprogrameve, destinacioneve GOTO u jepen etiketa. Disa asamblerë mbështesin simbole lokale të cilat shpesh janë leksikisht të dallueshme nga simbolet normale ( p.sh., përdorimi i "10$" si një destinacion GOTO ).

Disa asemblerë, siç është NASM, ofrojnë menaxhim fleksibël të simboleve, duke i lejuar programuesit të menaxhojnë hapësira të ndryshme emrash, të llogarisin automatikisht zhvendosjet brenda strukturave të të dhënave dhe të caktojnë etiketa që i referohen vlerave literale ose rezultatit të llogaritjeve të thjeshta të kryera nga asembleri. Etiketat mund të përdoren gjithashtu për të inicializuar konstantet dhe variablat me adresa të zhvendosshme.

Gjuhët asamblere, si shumica e gjuhëve të tjera të kompjuterit, lejojnë që në kodin burimor të programit të shtohen komente që do të injorohen gjatë asamblesë. Komentimi i mençur është thelbësor në programet në gjuhën asamblere, pasi kuptimi dhe qëllimi i një sekuence udhëzimesh binare të makinës mund të jetë i vështirë për t'u përcaktuar. Gjuha asamblere "e papërpunuar" ( e pakomente ) e gjeneruar nga kompiluesit ose çmontuesit është mjaft e vështirë për t'u lexuar kur duhet të bëhen ndryshime.

 Makrot 
Shumë asemblerë mbështesin makro të paracaktuara, dhe të tjerë mbështesin makro të përcaktuara nga programuesi ( dhe të ripërcaktueshme në mënyrë të përsëritur ) që përfshijnë sekuenca rreshtash teksti në të cilat janë të ngulitura variabla dhe konstante. Përkufizimi i makrosë është më së shpeshti  një përzierje e deklaratave të asemblerit, p.sh., direktiva, udhëzime simbolike të makinës dhe shabllone për deklaratat e asemblerit. Kjo sekuencë rreshtash teksti mund të përfshijë opkode ose direktiva. Pasi të jetë përcaktuar një makro, emri i saj mund të përdoret në vend të një mnemonike. Kur asembleri përpunon një deklaratë të tillë, ai e zëvendëson deklaratën me rreshtat e tekstit të shoqëruara me atë makro, pastaj i përpunon ato sikur të ekzistonin në skedarin e kodit burimor ( duke përfshirë, në disa asemblerë, zgjerimin e çdo makroje ekzistuese në tekstin zëvendësues ). Makrot në këtë kuptim datojnë që nga autokoduesit e IBM të viteve 1950. 

Makro-assemblerët zakonisht kanë direktiva për të, p.sh., përcaktuar makrot, përcaktuar variablat, vendosur variablat në rezultatin e një shprehjeje aritmetike, logjike ose vargu, përsëritur, gjeneruar kod me kusht. Disa nga këto direktiva mund të kufizohen për përdorim brenda një përkufizimi makro, p.sh., MEXIT në HLASM, ndërsa të tjerat mund të lejohen brenda kodit të hapur ( jashtë përkufizimeve të makrove ), p.sh., AIF dhe COPY në HLASM.

Në gjuhën e asamblerit, termi "makro" përfaqëson një koncept më gjithëpërfshirës sesa në disa kontekste të tjera, siç është para-procesori në gjuhën e programimit C, ku direktiva e tij #define përdoret zakonisht për të krijuar makro të shkurtra me një rresht. Udhëzimet makro të asamblerit, si makrot në PL/I dhe disa gjuhë të tjera, mund të jenë "programe" të gjata më vete, të ekzekutuara me interpretim nga asambleri gjatë asamblesë.

Meqenëse makrot mund të kenë emra 'të shkurtër', por të zgjerohen në disa ose në fakt shumë rreshta kodi, ato mund të përdoren për t'i bërë programet në gjuhën assembly të duken shumë më të shkurtra, duke kërkuar më pak rreshta kodi burimor, si me gjuhët e nivelit më të lartë. Ato gjithashtu mund të përdoren për të shtuar nivele më të larta strukture në programet assembly, duke futur opsionalisht kodin e integruar të debugging-ut nëpërmjet parametrave dhe veçorive të tjera të ngjashme.

Makro-assemblerët shpesh lejojnë që makrot të marrin parametra . Disa asemblerë përfshijnë gjuhë makro mjaft të sofistikuara, duke përfshirë elementë të gjuhës së nivelit të lartë si parametra opsionalë, variabla simbolikë, kushte, manipulim vargjesh dhe operacione aritmetike, të gjitha të përdorshme gjatë ekzekutimit të një makroje të caktuar, dhe duke lejuar makrot të ruajnë kontekstin ose të shkëmbejnë informacion. Kështu, një makro mund të gjenerojë udhëzime të shumta në gjuhën e asamblesë ose përkufizime të të dhënave, bazuar në argumentet e makrove. Kjo mund të përdoret për të gjeneruar struktura të dhënash në stilin e regjistrimit ose sythe " të shpalosura ", për shembull, ose mund të gjenerojë algoritme të tëra bazuar në parametra kompleksë. Për shembull, një makro "sort" mund të pranojë specifikimin e një çelësi kompleks renditjeje dhe të gjenerojë kod të hartuar për atë çelës specifik, pa pasur nevojë për testet në kohë ekzekutimi që do të kërkoheshin për një procedurë të përgjithshme që interpreton specifikimin. Një organizatë që përdor gjuhën e asamblesë që është zgjeruar shumë duke përdorur një suitë të tillë makrosh mund të konsiderohet se po punon në një gjuhë të nivelit më të lartë, pasi programues të tillë nuk po punojnë me elementët konceptualë të nivelit më të ulët të një kompjuteri. Duke nënvizuar këtë pikë, makrot u përdorën për të zbatuar një makinë virtuale të hershme në SNOBOL4 (1967), e cila u shkrua në SNOBOL Implementation Language (SIL), një gjuhë asambleje për një makinë virtuale. Makina e synuar do ta përkthente këtë në kodin e saj vendas duke përdorur një makro asambler. Kjo lejoi një shkallë të lartë transportueshmërie për kohën.

Makrot u përdorën për të përshtatur sisteme softuerike në shkallë të gjerë për klientë specifikë gjatë epokës së mainframe‑ve. Ato u përdorën gjithashtu nga personeli i klientëve për të plotësuar nevojat e punëdhënësve të tyre, duke krijuar versione të veçanta të sistemeve operative të prodhuesve.

Kjo u realizua, për shembull, nga programuesit e sistemeve që punonin me IBM Conversational Monitor System / Virtual Machine (VM/CMS) dhe me shtesat e IBM për “përpunim transaksionesh në kohë reale”, si Customer Information Control System (CICS) dhe ACP/TPF, sistemi i linjave ajrore/financiar që filloi në vitet 1970 dhe që ende përdoret për shumë sisteme të mëdha rezervimi kompjuterik (CRS) dhe sisteme kartash krediti sot.

Është gjithashtu e mundur të përdoren vetëm aftësitë e përpunimit të makrove të një assembleri për të gjeneruar kod të shkruar në gjuhë krejtësisht të ndryshme. Për shembull, mund të gjenerohet një version i një programi në COBOL duke përdorur një program të pastër makro‑assembler, i cili përmban rreshta kodi COBOL brenda operatorëve të kohës së montimit që udhëzojnë assemblerin të gjenerojë kod arbitrar.

IBM OS/360 përdor makro për të kryer gjenerimin e sistemit. Përdoruesi specifikon opsionet duke koduar një seri makrosh assembleri. Montimi i këtyre makrove gjeneron një rrjedhë pune (job stream) për ndërtimin e sistemit, duke përfshirë gjuhën e kontrollit të punës (Job Control Language – JCL) dhe deklaratat e kontrollit të utiliteteve.

Kjo ndodh sepse, siç u kuptua në vitet 1960, koncepti i “përpunimit me makro” është i pavarur nga koncepti i “asamblimit”; i pari, në terma modernë, i ngjan më shumë përpunimit të tekstit sesa gjenerimit të kodit objekt.

Koncepti i përpunimit me makro u shfaq, dhe vazhdon të shfaqet, edhe në gjuhën programuese C, e cila mbështet udhëzime para‑procesori për të caktuar variabla dhe për të kryer teste kushtesh mbi vlerat e tyre. Ndryshe nga disa përpunues makro të mëparshëm brenda assemblerëve, para‑procesori i C nuk është Turing‑i plotë, pasi i mungon aftësia për të kryer loop ose për të përdorur “go to”, elementë që do të lejonin programet të përsëriteshin.

Pavarësisht fuqisë së përpunimit me makro, ai ra në mospërdorim në shumë gjuhë të nivelit të lartë (përjashtime kryesore janë C, C++ dhe PL/I), ndërkohë që mbeti një praktikë e përhershme në assemblerë.

Zëvendësimi i parametrave në makro bëhet rreptësisht sipas emrit: në kohën e përpunimit të makros, vlera e një parametri zëvendësohet tekstualisht në vend të emrit të tij. Klasa më e njohur e gabimeve që rezultuan nga kjo ishte përdorimi i një parametri që vetë ishte një shprehje dhe jo një emër i thjeshtë, në rastet kur autori i makros priste një emër. Në makron:

foo: makro a     

ngarkoni a*b

Qëllimi ishte që thirrësi të jepte emrin e një variabli, dhe variabli ose konstanta “global” b të përdorej për të shumëzuar a. Nëse funksioni foo thirret me parametrin a‑c, zgjerimi i makros prodhon udhëzimin load a-c*b.

Për të shmangur çdo paqartësi të mundshme, përdoruesit e përpunuesve të makrove mund të vendosin parametra formalë në kllapa brenda përkufizimeve të makros, ose thirrësit mund të vendosin në kllapa parametrat e dhënë si hyrje.

Mbështetje për programimin e strukturuar    

Paketa makrosh janë shkruar për të ofruar elemente të programimit të strukturuar që kodifikojnë rrjedhën e ekzekutimit. Shembulli më i hershëm i këtij qasjeje ishte seti i makrove Concept‑14, i propozuar fillimisht nga Harlan Mills (mars 1970) dhe i implementuar nga Marvin Kessler në Divizionin e Sistemeve Federale të IBM. Ky set ofronte blloqe kontrolli si IF/ELSE/ENDIF dhe struktura të ngjashme për programet assembler të OS/360.

Ky ishte një mënyrë për të reduktuar ose eliminuar përdorimin e operacioneve GOTO në kodin e asamblimit, një nga faktorët kryesorë që shkaktonin spaghetti code në gjuhën e asamblimit. Kjo qasje u pranua gjerësisht në fillim të viteve 1980, në periudhën e fundit të përdorimit në shkallë të gjerë të gjuhës së asamblimit. IBM High Level Assembler Toolkit përfshin një paketë të tillë makrosh.

Një tjetër dizajn ishte A‑Natural, një assembler “stream‑oriented” për procesorët 8080/Z80, i zhvilluar nga Whitesmiths Ltd. (krijuesit e sistemit operativ Idris, i ngjashëm me Unix, dhe asaj që raportohet të ketë qenë kompajleri i parë komercial i gjuhës C).

Gjuha u klasifikua si assembler sepse punonte me elementë të pastër të makinës, si opcode, regjistra dhe referenca kujtese; por ajo inkorporonte një sintaksë shprehjesh për të treguar rendin e ekzekutimit. Kllapat dhe simbole të tjera speciale, së bashku me konstruktet e programimit të strukturuar të orientuara në blloqe, kontrollonin sekuencën e udhëzimeve të gjeneruara.

A‑Natural u ndërtua si gjuhë objekt e një kompajleri C, dhe jo për kodim manual, por sintaksa e tij logjike fitoi disa mbështetës.

Ka pasur pak kërkesë të dukshme për assemblerë më të sofistikuar që nga rënia e zhvillimit në shkallë të gjerë të gjuhës së asamblimit. Megjithatë, ata vazhdojnë të zhvillohen dhe të përdoren në raste kur kufizimet e burimeve ose veçoritë e veçanta të arkitekturës së sistemit të synuar pengojnë përdorimin efektiv të gjuhëve të nivelit më të lartë.

Assemblerët me motor të fuqishëm makrosh lejojnë programimin e strukturuar përmes makrove, si p.sh. . makroja switch e ofruar me paketën Masm32 (ky kod përbën një program të plotë).

 Shembull kodi 
include \masm32\include\masm32rt.inc    ; use the Masm32 library

.code
demomain:
  REPEAT 20
    switch rv(nrandom, 9)    ; generate a number between 0 and 8
    mov ecx, 7
    case 0
        print "case 0"
    case ecx                 ; Masm32 switch allows "variable cases"
        print "case 7"
    case 1 .. 3
        .if eax==1
            print "case 1"
        .elseif eax==2
            print "case 2"
        .else
            print "cases 1 to 3: other"
        .endif
    case 4, 6, 8
        print "cases 4, 6 or 8"
    default
        mov ebx, 19
        .Repeat
            print "*"
            dec ebx
        .Until Sign?
    endsw
    print chr$(13, 10)
  ENDM
  exit
end demomain

 Përdorimi i gjuhës së assemblerit 
Kur u prezantua kompjuteri me program të ruajtur, programet shkruheshin në kod makine dhe ngarkoheshin në kompjuter nga shirita letre të shpuar ose futeshin drejtpërdrejt në kujtesë përmes çelësave të konsolës. [citation needed]

Kathleen Booth “i atribuohet shpikja e gjuhës së asamblimit” bazuar në punën teorike që ajo filloi në vitin 1947, ndërsa punonte në ARC2 në Birkbeck, University of London, pas konsultimeve të Andrew Booth (më vonë bashkëshorti i saj) me matematicienin John von Neumann dhe fizikantin Herman Goldstine në Institute for Advanced Study.  

Në fund të vitit 1948, kompjuteri Electronic Delay Storage Automatic Calculator (EDSAC) kishte një assembler (i quajtur “initial orders”) të integruar në programin e nisjes (bootstrap). Ai përdorte mnemonikë me një shkronjë të vetme, të zhvilluara nga David Wheeler, i cili njihet nga IEEE Computer Society si krijuesi i parë i një “assembleri”.

Raportet mbi EDSAC prezantuan termin “assembly” për procesin e kombinimit të fushave në një fjalë udhëzimi.

SOAP (Symbolic Optimal Assembly Program) ishte një gjuhë asamblimi për kompjuterin IBM 650, e shkruar nga Stan Poley në vitin 1955.

Gjuhët e asamblimit eliminuan pjesën më të madhe të programimit të gjeneratës së parë, i cili ishte i prirur ndaj gabimeve, i lodhshëm dhe që kërkonte shumë kohë në kompjuterët më të hershëm. Ato i çliruan programuesit nga detyra të mërzitshme si kujtimi i kodeve numerike dhe llogaritja e adresave. Dikur ato përdoroheshin gjerësisht për çdo lloj programimi.

Në fund të viteve 1950, përdorimi i tyre u zëvendësua kryesisht nga gjuhët e nivelit më të lartë, në kërkim të produktivitetit më të madh në programim.

Sot, gjuha e asamblimit vazhdon të përdoret për manipulim të drejtpërdrejtë të harduerit, për qasje në udhëzime të specializuara të procesorit, ose për të adresuar çështje kritike të performancës. Përdorimet tipike përfshijnë driverët e pajisjeve, sistemet e integruara të nivelit të ulët dhe sistemet në kohë reale.

Shumë programe u shkruan plotësisht në gjuhën e asamblimit. Burroughs MCP (1961) ishte kompjuteri i parë për të cilin sistemi operativ nuk u zhvillua tërësisht në gjuhën e asamblimit; ai u shkrua në Executive Systems Problem Oriented Language (ESPOL), një dialekt i Algol.

Shumë aplikacione komerciale u shkruan gjithashtu në gjuhën e asamblimit, përfshirë një pjesë të madhe të softuerit për IBM mainframe të zhvilluar nga korporata të mëdha. COBOL, FORTRAN dhe disa PL/I eventualisht e zëvendësuan gjuhën e asamblimit, megjithatë një numër organizatash të mëdha e ruajtën infrastrukturën e aplikacioneve të shkruara në gjuhën e asamblimit deri në vitet 1990.

Gjuha e assemblerit ishte gjuha kryesore e zhvillimit për kompjuterët personalë 8‑bit, si Apple II, Atari 8‑bit, ZX Spectrum dhe Commodore 64. BASIC i interpretuar në këto sisteme nuk ofronte shpejtësinë maksimale të ekzekutimit dhe as përdorimin e plotë të kapaciteteve për të shfrytëzuar harduerin e disponueshëm.

Gjuha e assemblerit ishte zgjedhja e paracaktuar për programimin e konzolave 8‑bit, si Atari 2600 dhe Nintendo Entertainment System (NES).

Softueri kryesor për kompjuterët IBM PC kompatibilë, si MS‑DOS, Turbo Pascal dhe tabela elektronike Lotus 1‑2‑3, u shkrua në gjuhën e asamblimit. Me rritjen eksponenciale të shpejtësisë së kompjuterëve, gjuha e asamblimit u bë një mjet për përshpejtimin e pjesëve të caktuara të programeve, si p.sh. . renderimi i lojës Doom, në vend që të mbetej gjuha dominuese e zhvillimit.

Në vitet 1990, gjuha e assemblerit u përdor për të maksimizuar performancën në sisteme si Sega Saturn, dhe si gjuhë kryesore për harduerin e arcade‑ve që përdorte CPU/GPU të integruar TMS34010, si në lojërat Mortal Kombat dhe NBA Jam.

Përdorimi aktual

Ka pasur debat mbi dobishmërinë dhe performancën e gjuhës së asamblimit në krahasim me gjuhët e nivelit të lartë.

Megjithëse gjuha e asamblimit ka përdorime të veçanta në fusha të caktuara ku është e rëndësishme (shih më poshtë), ekzistojnë mjete të tjera për optimizim.

Që nga korriku 2017, indeksi TIOBE i popullaritetit të gjuhëve programuese e renditi gjuhën e asamblimit në vendin e 11‑të, përpara Visual Basic, për shembull.

Assembleri mund të përdoret për optimizim të shpejtësisë ose për optimizim të madhësisë. Në rastin e optimizimit për shpejtësi, pretendohet se kompajlerët modernë optimizues arrijnë të gjenerojnë kod nga gjuhët e nivelit të lartë që mund të ekzekutohet po aq shpejt sa kodi i shkruar me dorë në assembler, megjithëse ekzistojnë disa kundër‑shembuj.

Kompleksiteti i procesorëve modernë dhe i nën‑sistemeve të kujtesës e bën optimizimin efektiv gjithnjë e më të vështirë si për kompajlerët, ashtu edhe për programuesit e assemblerit. Rritja e performancës së procesorëve ka bërë që shumica e CPU‑ve të qëndrojnë të papërdorura për pjesën më të madhe të kohës, me vonesa të shkaktuara nga ngushticat e parashikueshme si cache misses, operacionet I/O dhe paging, duke e bërë shpejtësinë e ekzekutimit të kodit një çështje jo‑kritike për shumë programues.

Ekzistojnë ende disa fusha të programimit kompjuterik ku përdorimi i gjuhës së asamblimit është më i zakonshëm:

Shkrimi i kodit për sisteme me procesorë të vjetër që kanë mundësi të kufizuara për gjuhë të nivelit të lartë, si Atari 2600, Commodore 64 dhe kalkulatorët grafikë. Programet për këto kompjuterë të viteve 1970 dhe 1980 shpesh shkruheshin në kontekstin e demoscene ose nënkulturave të retrogaming.

Kodi që duhet të ndërveprojë drejtpërdrejt me harduerin, për shembull në driverë pajisjesh dhe interrupt handlers. Në një procesor të integruar ose DSP, ndërprerjet me përsëritje të lartë kërkojnë numrin më të shkurtër të cikleve për ndërprerje, si p.sh. . një ndërprerje që ndodh 1000 ose 10000 herë në sekondë.

Programet që duhet të përdorin udhëzime specifike të procesorit që nuk implementohen nga kompajleri. Një shembull i zakonshëm është udhëzimi i rotacionit bitwise, i përdorur në shumë algoritme enkriptimi, si dhe pyetja për paritetin e një byte ose mbartjen 4‑bit të një mbledhjeje.

Ekzekutuesit e pavarur që duhet të funksionojnë pa komponentë të kohës së ekzekutimit ose biblioteka të lidhura me gjuhët e nivelit të lartë, si firmware për telefona, sisteme karburanti dhe ndezjeje në automjete, sisteme kontrolli të kondicionimit të ajrit dhe sisteme sigurie.

Programet me loop‑e të ndjeshme ndaj performancës, ku gjuha e asamblimit ofron mundësi optimizimi që janë të vështira për t’u arritur në gjuhë të nivelit të lartë. Shembuj tipikë janë algebra lineare me BLAS ose transformimi kosinus diskret (p.sh. versioni SIMD assembly nga x264).

Programet që krijojnë funksione të vektorizuara për gjuhë të nivelit të lartë si C. Në gjuhën e nivelit të lartë kjo ndihmohet ndonjëherë nga funksionet intrinseke të kompajlerit që lidhen drejtpërdrejt me mnemonikët SIMD, por gjithsesi rezultojnë në një konvertim një‑më‑një në assembler specifik për procesorin e dhënë.

Programet në kohë reale, si simulimet, sistemet e navigimit të fluturimit dhe pajisjet mjekësore. Për shembull, në një sistem fly‑by‑wire, telemetria duhet të interpretohet dhe të veprohet mbi të brenda kufizimeve të rrepta kohore. Këto sisteme duhet të eliminojnë burimet e vonesave të paparashikueshme, që mund të krijohen nga gjuhët e interpretuara, mbledhja automatike e mbeturinave, operacionet e paging ose multitasking‑u parandalues. Zgjedhja e gjuhës së asamblimit ose gjuhëve të tjera të nivelit të ulët u jep programuesve më shumë kontroll mbi detajet e përpunimit.

Algoritmet kriptografike që duhet të ekzekutohen gjithmonë në të njëjtën kohë, për të parandaluar sulmet e bazuara në kohë.

Video encoder‑ët dhe decoder‑ët si rav1e (encoder për AV1) dhe dav1d (decoder referencë për AV1) përmbajnë kod assembler për të shfrytëzuar udhëzimet AVX2 dhe ARM Neon kur janë të disponueshme.

Modifikimi dhe zgjerimi i kodit të trashëguar të shkruar për IBM mainframe computers.

Situata ku kërkohet kontroll i plotë mbi mjedisin, në raste me siguri shumë të lartë ku asgjë nuk mund të merret e mirëqenë.

Viruset kompjuterike, bootloader‑ët, disa driverë pajisjesh ose elementë të tjerë shumë pranë harduerit ose sistemit operativ të nivelit të ulët.

Simulatorët e seteve të udhëzimeve për monitorim, gjurmim dhe debugging, ku mbingarkesa shtesë mbahet në minimum.

Situata ku nuk ekziston gjuhë e nivelit të lartë, në një procesor të ri ose të specializuar për të cilin nuk ka kompajler të kryqëzuar.

Reverse engineering dhe modifikimi i skedarëve të programeve, si:

Binarë ekzistues që mund të jenë ose jo të shkruar fillimisht në gjuhë të nivelit të lartë, për shembull kur tentohet rikrijimi i     p     rogrameve për të cilat kodi burimor nuk është i disponueshëm ose është humbur, ose thyerja e mbrojtjes së kopjimit të softuerit pronësor.

 Video lojëra (ROM hacking), e cila është e mundur përmes disa metodave. Metoda më e përdorur është ndryshimi i kodit të programit në nivelin e gjuhës së asamblimit.
 Gjuha e asamblimit vazhdon të mësohet në shumicën e programeve të shkencave kompjuterike dhe inxhinierisë elektronike. Megjithëse sot pak programues punojnë rregullisht me gjuhën e asamblimit si mjet, konceptet themelore mbeten të rëndësishme. Tema të tilla bazë si aritmetika binare, alokimi i kujtesës, përpunimi i stack‑ut, kodifikimi i seteve të karaktereve, përpunimi i ndërprerjeve dhe dizajni i kompajlerëve do të ishte e vështirë të studioheshin në detaje pa një kuptim të funksionimit të kompjuterit në nivel harduerik.  Meqenëse sjellja e një kompjuteri përcaktohet në mënyrë themelore nga seti i udhëzimeve, mënyra logjike për të mësuar këto koncepte është studimi i një gjuhe asamblimi. Shumica e kompjuterëve modernë kanë sete udhëzimesh të ngjashme. Prandaj, studimi i një gjuhe të vetme asamblimi është i mjaftueshëm për të mësuar konceptet bazë, për të njohur situatat ku përdorimi i gjuhës së asamblimit mund të jetë i përshtatshëm, dhe për të parë se si mund të krijohet kod ekzekutues efikas nga gjuhët e nivelit të lartë.

Aplikime tipike

Gjuha e assemblerit përdoret zakonisht në kodin e nisjes së sistemit (boot code), kod i nivelit të ulët që inicializon dhe teston harduerin e sistemit para se të nisë sistemi operativ, dhe shpesh ruhet në ROM. (BIOS në sistemet IBM‑compatible PC dhe CP/M është një shembull.)

Gjuha e assemblerit përdoret shpesh për kodin e nivelit të ulët, për shembull në kernelët e sistemeve operative, të cilët nuk mund të mbështeten në thirrje ekzistuese të sistemit dhe duhet t’i implementojnë ato për arkitekturën specifike të procesorit ku do të funksionojë sistemi.

Disa kompajlerë e përkthejnë fillimisht gjuhën e nivelit të lartë në assembler para kompilimit të plotë, duke lejuar që kodi assembler të shihet për debugging dhe optimizim.

Disa kompajlerë për gjuhë relativisht të nivelit të ulët, si Pascal ose C, i lejojnë programuesit të fusin gjuhën e asamblimit drejtpërdrejt në kodin burimor (inline assembly). Programet që përdorin këto mundësi mund të ndërtojnë abstraksione duke përdorur gjuhë të ndryshme asamblimi në secilën platformë harduerike. Kodi portabël i sistemit mund të përdorë më pas këto komponentë specifikë për procesorin përmes një ndërfaqeje uniforme.

Gjuha e assemblerit është e dobishme në reverse engineering. Shumë programe shpërndahen vetëm në formë machine code, e cila është e thjeshtë për t’u përkthyer në gjuhën e asamblimit nga një disassembler, por më e vështirë për t’u përkthyer në gjuhë të nivelit të lartë përmes një decompiler. Mjete si Interactive Disassembler përdorin gjerësisht disassembler‑in për këtë qëllim. Kjo teknikë përdoret nga hackerët për të thyer softuerin komercial, si dhe nga konkurrentët për të prodhuar softuer me rezultate të ngjashme.

Gjuha e assemblerit përdoret për të rritur shpejtësinë e ekzekutimit, veçanërisht në kompjuterët personalë të hershëm me fuqi të kufizuar përpunimi dhe RAM.

Assemblerët mund të përdoren për të gjeneruar blloqe të dhënash, pa mbingarkesën e gjuhëve të nivelit të lartë, nga kod burimor i formatuar dhe i komentuar, për t’u përdorur nga kode të tjera.

 Shiko edhe 

 Kompajler – Softuer që përkthen kodin nga një gjuhë programimi në një tjetër
 Krahasimi i assemblerëve
 Disassembler – Program kompjuterik që përkthen gjuhën e makinës në gjuhën e asamblimit
 Heksadecimal – Paraqitje numerike me bazë 16
 Gjuha e Përpunimit të Informacionit (Information Processing Language) – Gjuhë e hershme programimi për lista
 Arkitektura e setit të udhëzimeve (Instruction set architecture) – Model që përshkruan ndërfaqen e programueshme të një procesori kompjuterik
 Kompjuteri “Little man” – Model instruksional i një kompjuteri
 Nibble – Njësi e të dhënave binare me katër bita
 Gjuha e asamblimit të tipizuar (Typed assembly language)

 Referime