Forsamlingsspråk | ||
---|---|---|
Motorola MC6800 Assembler oppføring | ||
? | ||
Generell informasjon | ||
Vanlige utvidelser | .asm | |
Paradigme | Imperativ , ustrukturert | |
Dukket opp i | 1949 | |
Assembly language eller assembler (på engelsk : assembler language og forkortelsen asm ) er et programmeringsspråk på lavt nivå . Den består av et sett med mnemonikk som representerer grunnleggende instruksjoner for datamaskiner , mikroprosessorer , mikrokontrollere og andre programmerbare integrerte kretser . Den implementerer en symbolsk representasjon av de binære maskinkodene og andre konstanter som er nødvendige for å programmere en prosessorarkitektur og er den mest direkte representasjonen av den spesifikke maskinkoden for hver arkitektur som kan leses av en programmerer. Hver prosessorarkitektur har sitt eget assembly-språk som vanligvis er definert av maskinvareprodusenten , og er basert på mnemonics som symboliserer prosesseringstrinn ( instruksjoner ), prosessorregistre , minneplasseringer og andre språkfunksjoner. Et monteringsspråk er derfor spesifikt for en viss fysisk (eller virtuell) datamaskinarkitektur . Dette er i motsetning til de fleste programmeringsspråk på høyt nivå , som ideelt sett er bærbare .
Et hjelpeprogram kalt en assembler brukes til å oversette assembly-språkutsagn til maskinkoden til måldatamaskinen. Montøren utfører en omtrent isomorf oversettelse (en en-til-en-kartlegging) fra mnemoniske uttalelser til maskininstruksjonene og dataene. Dette er i motsetning til språk på høyt nivå, der en enkelt setning generelt gir opphav til mange maskininstruksjoner.
Mange sofistikerte montører tilbyr tilleggsmekanismer for å lette programutvikling, kontrollere monteringsprosessen og hjelpe til med feilsøking . Spesielt inkluderer de fleste moderne montører et makroanlegg (beskrevet nedenfor), og kalles makromontører .
Det ble hovedsakelig brukt i de tidlige dagene av programvareutvikling , da kraftige høynivåspråk ennå ikke var tilgjengelig og ressursene var begrenset. Den brukes for tiden ofte i akademiske miljøer og forskningsmiljøer, spesielt når direkte manipulering av maskinvare , høy ytelse eller kontrollert og redusert ressursbruk er nødvendig. Det brukes også i utviklingen av enhetsdrivere (på engelsk enhetsdrivere ) og i utviklingen av operativsystemer, på grunn av behovet for direkte tilgang til maskininstruksjoner. Mange programmerbare enheter (som mikrokontrollere) er fortsatt avhengige av assembleren som den eneste måten å manipulere dem på.
Vanligvis lager et moderne monteringsprogram objektkode ved å oversette mnemonic assembly- språkinstruksjoner til opkoder og løse symbolske navn for minneplasseringer og andre enheter. [ 2 ] Bruken av symbolske referanser er en nøkkelfunksjon i assembly-språket, og unngår kjedelige beregninger og manuell oppdatering av adresser etter hver programmodifikasjon. De fleste montører inkluderer også makrofasiliteter for å utføre tekstsubstitusjon - f.eks. generere korte sekvenser med instruksjoner som innebygd utvidelse i stedet for å ringe subrutiner .
Assemblere er generelt enklere å skrive enn kompilatorer for språk på høyt nivå , og har vært tilgjengelig siden 1950-tallet. Moderne assemblere, spesielt for RISC -baserte arkitekturer som MIPS , Sun SPARC og HP PARISC , samt for x86 ( -64 ), optimalisere instruksjonsplanlegging for å utnytte CPU-rørledningen effektivt.
I kompilatorer for høynivåspråk er de det siste trinnet før du genererer kjørbar kode.
Det er to typer samlere basert på hvor mange passeringer gjennom kilden som kreves for å produsere det kjørbare programmet.
Fordelen med en enkelt-pass assembler er hastighet, som ikke er så viktig som det en gang ble gitt fremskritt i datamaskinens hastighet og kapasitet. Fordelen med to-trinns assembler er at symbolene kan defineres hvor som helst i kildekoden til programmet. Dette gjør at programmer kan defineres på mer logiske og meningsfulle måter, noe som gjør to-trinns assemblerprogrammer lettere å lese og vedlikeholde. [ 3 ]
De mest sofistikerte høynivåmontørene gir språkabstraksjoner som:
Merk at, i normal profesjonell bruk, brukes begrepet assembler ofte for å referere til både assemblerspråk og assemblerprogram (som konverterer kildekode skrevet på assemblerspråk til objektkode som deretter vil bli koblet til å produsere maskinspråk ). Følgende to uttrykk bruker begrepet "montør":
Assembly språk reflekterer direkte arkitekturen og maskinspråkinstruksjonene til CPU, og kan være svært forskjellig fra én CPU-arkitektur til en annen.
Hver mikroprosessorarkitektur har sitt eget maskinspråk, og følgelig sitt eget assemblyspråk, siden den er nært knyttet til strukturen til maskinvaren den er programmert for. Mikroprosessorer er forskjellige i typen og antall operasjoner de støtter; de kan også ha ulikt antall registre, og ulik representasjon av datatyper i minnet. Selv om de fleste mikroprosessorer er i stand til i det vesentlige de samme funksjonene, er måten de gjør det på, forskjellig, og de respektive monteringsspråkene gjenspeiler den forskjellen.
De fleste CPUer har mer eller mindre de samme gruppene av instruksjoner, selv om de ikke nødvendigvis har alle instruksjonene i hver gruppe. Operasjonene som kan utføres varierer fra én CPU til en annen. En bestemt CPU kan ha instruksjoner som en annen ikke har, og omvendt.
Tidlige 8-bits mikroprosessorer hadde ikke operasjoner for å multiplisere eller dividere tall, for eksempel, og du måtte lage subrutiner for å utføre disse operasjonene. Andre CPUer har kanskje ikke flyttalloperasjoner, og du må lage eller skaffe biblioteker som utfører disse operasjonene.
CPU-instruksjoner kan grupperes, i henhold til deres funksjonalitet, i:
Heltallsoperasjoner: (8, 16, 32 og 64 bits avhengig av CPU-arkitekturen, på svært gamle systemer også 12, 18, 24, 36 og 48 biter).
Dette er operasjoner utført av den aritmetiske logiske enheten til CPU:
Dataflytteoperasjoner:
Mellom registre og minne: Selv om instruksjonen kalles "move", i CPU, betyr "move data" faktisk å kopiere data, fra en kilde til en destinasjon, uten at dataene forsvinner fra kilden. Verdier kan flyttes:Operasjoner for programflytkontroll:
Operasjoner med reelle tall:
Standarden for reelle talloperasjoner i CPUer er definert av IEEE 754 .
En CPU kan ha flyttallsoperasjoner med reelle tall ved å bruke den numeriske koprosessoren (hvis noen), for eksempel følgende:
Assembly-språket har mnemonics for hver av CPU-instruksjonene i tillegg til andre mnemonics som skal behandles av monteringsprogrammet (som makroer og andre setninger på monteringstidspunktet).
Transformasjonen fra assemblerspråk til maskinkode gjøres av et assemblerprogram , og den omvendte oversettelsen kan gjøres av en disassembler . I motsetning til høynivåspråk , er det her vanligvis en 1-til-1-korrespondanse mellom enkle monteringsinstruksjoner og maskinspråk. Men i noen tilfeller kan en montør gi "pseudo-instruksjoner" som utvides til større maskinkode for å gi nødvendig funksjonalitet og forenkle programmering. For eksempel, for betinget maskinkode som "hvis X større enn eller lik", kan en assembler bruke en pseudo-instruksjon for å gruppere "gjør hvis mindre enn", og "hvis = 0" på resultatet av den forrige betingelsen. Mer komplette Assemblers gir også et rikt makrospråk som brukes til å generere mer kompleks kode og datastrømmer.
For den samme prosessoren og det samme settet med CPU-instruksjoner kan forskjellige monteringsprogrammer hver ha variasjoner og forskjeller i settet med mnemonics eller i syntaksen til assemblerspråket deres. For eksempel, i et assemblerspråk for x86-arkitekturen, kan instruksjonen om å flytte 5til registeret uttrykkes ALsom følger: MOV AL, 5, mens for en annen assembler for samme arkitektur vil den bli uttrykt omvendt: MOV 5, AL. Begge assembly-språkene ville gjøre nøyaktig det samme, bare uttrykt annerledes. Førstnevnte bruker Intel -syntaksen , mens sistnevnte bruker AT&T -syntaks .
Bruken av assembler løser ikke definitivt problemet med hvordan man programmerer et mikroprosessorbasert system på en enkel måte, siden man for å gjøre effektiv bruk av det må kjenne mikroprosessoren grundig , arbeidsregistrene som er tilgjengelige for den, strukturen til minnet, og mange flere ting knyttet til dets grunnleggende driftsstruktur.
Et program skrevet i assemblerspråk består av en serie instruksjoner som tilsvarer strømmen av ordrer som kan utføres av en mikroprosessor.
For eksempel, i assemblerspråk for en x86 -prosessor :
Setning
Tildeler den heksadesimale 61 verdien (97 desimaler ) til " AL"-registeret.
Monteringsprogrammet leser setningen ovenfor og produserer sin binære ekvivalent i maskinspråk .
Mnemonikken MOVer en operasjonskode eller " opcode ". Op -koden følges av en liste over argumenter eller parametere , og fullfører en typisk assembler-instruksjon. I eksemplet er ALdet et 8-bits prosessorregister, som vil bli tildelt den angitte heksadesimale verdien 61.
Maskinkoden generert av assembleren består av 2 byte. Den første byten inneholder den pakkede MOV-instruksjonen og registerkoden der dataene skal flyttes til:
1011 0000 01100001 | | | | | +---- Tall 61h i binær | | | +--- Registrer AL +-------- MOV instruksjonI den andre byten er tallet 61h spesifisert, skrevet i binært som 01100001, som vil bli tildelt registeret AL, og etterlater den kjørbare setningen som:
Som kan forstås og utføres direkte av prosessoren.
Det er en stor grad av mangfold i måten assembler-forfattere kategoriserer utsagn på og i nomenklaturen de bruker. Spesielt beskriver noen alt som en pseudooperasjon (pseudo-Op), med unntak av den maskinelle mnemonicen eller den utvidede mnemonicen.
Et typisk assemblerspråk består av 3 typer instruksjonssetninger som brukes til å definere operasjonene til programmet:
I motsetning til instruksjonene (utsagnene) for språk på høyt nivå , er instruksjonene på assembler-språk generelt veldig enkle. Generelt er en mnemonic et symbolsk navn for en enkelt kjørbar maskinspråkinstruksjon (en opcode ), og det er minst én opcode-mnemonic definert for hver maskinspråkinstruksjon. Hver instruksjon består vanligvis av en operasjon eller opkode pluss null eller flere operander . De fleste instruksjoner refererer til en enkelt verdi, eller et par verdier. Operandene kan være umiddelbare (typisk én-byte-verdier, kodet i selve instruksjonen), registre spesifisert i instruksjonen, implisitte eller adressene til data som ligger andre steder i minnet. Dette bestemmes av den underliggende arkitekturen til prosessoren, assembleren gjenspeiler ganske enkelt hvordan denne arkitekturen fungerer. Utvidet mnemonikk brukes ofte til å spesifisere en kombinasjon av en op-kode med en spesifikk operand, for eksempel bruker System/360-montøren a Bsom en utvidet mnemonikk for el BCmed en maske på 15 og NOPal BCmed en maske på 0.
Utvidet mnemonikk brukes ofte for å støtte spesialisert bruk av instruksjoner, ofte for formål som ikke er tydelige fra navnet på instruksjonen. For eksempel har mange CPUer ikke en eksplisitt NOP(No Operation) instruksjon, men de har instruksjoner som kan brukes til det formålet. På 8086 CPU brukes instruksjonen XCHG AX,AX(bytter AX-registeret med seg selv) for NOP, med NOPå være en pseudo-op-kode for å kode instruksjonen XCHG AX,AX. Noen demontører gjenkjenner dette og vil dekode instruksjonen XCHG AX,AXsom NOP. På samme måte bruker IBM-montører for System/360 den utvidede mnemonics NOPy NOPRmed null masker for BCog BCR.
Noen montører støtter også enkle innebygde makroinstruksjoner som genererer to eller flere maskininstruksjoner. For eksempel, med noen montører for Z80 , instruksjonen
LD HL, BCgenerere instruksjonene
LD L, C LD H, B. [ 4 ]LD HL, BCer en pseudo-op-kode , som i dette tilfellet simulerer å være en 16-bits instruksjon. Når den utvides, produseres to 8-biters instruksjoner som tilsvarer den simulerte 16-biters.
DataseksjonerDet er instruksjoner som brukes til å definere dataelementer for å håndtere data og variabler. De definerer datatypen, lengden og justeringen av dataene. Disse instruksjonene kan også definere om dataene er tilgjengelige for eksterne programmer (separat sammensatte programmer) eller kun for programmet der datadelen er definert. Noen montører klassifiserer disse instruksjonene som pseudo-instruksjoner.
Assembler-direktiverAssembler-direktiver, også kalt pseudo-op-koder, pseudo-operasjoner eller pseudo-ops, er instruksjoner som utføres av en assembler på monteringstidspunktet, ikke av CPU-en ved kjøretid . De kan gjøre sammenstillingen av programmet avhengig av parametere spesifisert av programmereren, slik at et program kan settes sammen på forskjellige måter, kanskje for forskjellige applikasjoner. De kan også brukes til å manipulere visningen av et program for å gjøre det enklere å lese og vedlikeholde.
For eksempel kan direktiver brukes til å reservere lagringsområder og eventuelt tildele deres opprinnelige innhold. Direktivnavn begynner ofte med et punktum for å skille dem fra maskininstruksjoner.
Symboliske samlere lar programmerere assosiere vilkårlige navn (etiketter eller symboler) med minneplasseringer. Vanligvis har hver konstant og variabel et navn slik at instruksjoner kan referere til disse stedene ved navn, og dermed fremme selvdokumenterende kode. I kjørbar kode er navnet på hvert underprogram knyttet til inngangspunktet, så ethvert kall til et underprogram kan bruke navnet. Innenfor underprogrammer er GOTO- destinasjoner gitt etiketter. Noen samlere støtter lokale symboler som er leksikalsk forskjellige fra vanlige symboler (f.eks. bruken av "10$" som GOTO-destinasjon).
De fleste montører gir fleksibel symbolhåndtering, slik at programmerere kan håndtere ulike navneområder , automatisk beregne forskyvninger i datastrukturer og tilordne etiketter som refererer til bokstavelige verdier eller resultatet av enkle beregninger utført av samleren. Etiketter kan også brukes til å initialisere konstanter og variabler med flyttbare adresser.
Assembly-språk, som de fleste andre dataspråk, lar kommentarer legges til kildekoden , som ignoreres av monteringsprogrammet. God bruk av kommentarer er enda viktigere med monteringskode enn med språk på høyt nivå, siden meningen og hensikten med en instruksjonssekvens kan være vanskeligere å forstå ut fra selve koden.
Fornuftig bruk av disse fasilitetene kan betydelig forenkle problemene med koding og vedlikehold av lavnivåkode. Rå assembly-språkkildekode generert av kompilatorer eller disassemblere - kode uten noen kommentarer, meningsfulle symboler eller datadefinisjoner - er svært vanskelig å lese når endringer må gjøres.
Mange samlere støtter forhåndsdefinerte makroer, og andre støtter makroer definert (og gjentatte ganger omdefinert) av programmereren som involverer sekvenser av tekstlinjer, der variabler og konstanter er innebygd. Denne sekvensen av tekstlinjer kan inkludere opkoder eller direktiver. Når en makro er definert, kan navnet brukes i stedet for en mnemonikk. Når assembleren behandler en slik setning, erstatter den setningen med tekstlinjene som er knyttet til den makroen. Den behandler dem deretter som om de hadde eksistert i den originale kildekodefilen (inkludert, i noen assemblers, utvidelse av makroer som finnes i erstatningsteksten).
Siden makroer kan ha korte navn, men spenner over flere, eller faktisk mange, kodelinjer, kan de brukes til å få assembly-språkprogrammer til å virke mye kortere, og krever færre linjer med kildekode, slik tilfellet er med språk på høyt nivå. De kan også brukes til å legge til høyere nivåer av struktur til monteringsprogrammer; de introduserer eventuelt innebygd feilsøkingskode via parametere og andre lignende funksjoner.
Mange samlere har innebygde (eller forhåndsdefinerte) makroer for systemanrop og andre spesielle kodesekvenser, som datagenerering og lagring utført gjennom avanserte bitvise operasjoner og boolske operasjoner brukt i spill, sikkerhetsprogramvare, administrasjonsdata og kryptografi.
Makromontører lar ofte makroer ta parametere . Noen samlere inkluderer sofistikerte makrospråk, som inkluderer språkelementer på høyt nivå som valgfrie parametere, symbolske variabler, betingelser, strengmanipulasjoner , aritmetiske operasjoner, alt som kan brukes under utførelse av en gitt makro, og lar makroer lagre konteksten eller utveksle informasjon. Dermed kan en makro generere et stort antall assembly-språkinstruksjoner eller datadefinisjoner, basert på makroens argumenter. Dette kan brukes til å generere for eksempel datastrukturer i rekordstil eller "utrullede" løkker, eller det kan generere hele algoritmer basert på komplekse parametere. En organisasjon som bruker assemblerspråk, som har blitt kraftig utvidet ved å bruke en slik pakke med makroer, kan betraktes som å jobbe i et språk på høyt nivå, siden slike programmerere ikke jobber med de konseptuelle elementene på lavere nivå på datamaskinen.
Makroer ble brukt til å tilpasse storskala programvaresystemer for spesifikke kunder i stormaskintiden . Makroer ble også brukt av brukerne selv for å møte behovene til organisasjonene deres ved å lage spesifikke versjoner av produsentens operativsystemer. Dette ble for eksempel gjort av systemprogrammerere som jobbet med IBMs Conversational Monitor System/Virtual Machine (CMS/VM) og IBMs sanntidstransaksjonsbehandlings -plugins , CICS , Customer Information Control System , flyselskapet/finanssystemet som startet på 1970-tallet og kjører fortsatt med mange datareservasjonssystemer (CRS) og kredittkortsystemer i dag.
Det er også mulig å bruke bare makrobehandlingsevnene til en assembler for å generere kode skrevet på helt andre språk. For eksempel for å generere en COBOL -versjon av et program ved å bruke et rent assembler-makroprogram som inneholder linjer med COBOL-kode inne i monteringstidsoperatører som instruerer assembleren om å generere vilkårlig kode.
Dette var fordi, som 1970-tallet bemerket, begrepet "makrobehandling" er uavhengig av begrepet "montering", det førstnevnte er, i moderne termer, mer av tekstbehandling enn objektkodegenerering. Konseptet med makrobehandling dukket opp, og dukker opp, i programmeringsspråket C, som støtter "forbehandlerinstruksjoner" for å sette variabler, og utfører betinget testing på verdiene deres. Legg merke til at i motsetning til visse tidligere makroprosessorer innen montører, var ikke C-forprosessoren Turing-komplett fordi den manglet loop eller gå til kapasitet , sistnevnte tillot programmer å loope.
Til tross for kraften til makrobehandling, falt den ut av bruk på mange høynivåspråk (et viktig unntak er C/C++), men det vedvarte i assemblers. Dette var fordi mange programmerere var ganske forvirret av makroparametersubstitusjon og ikke skilte forskjellen mellom makrobehandling, montering og utførelse.
Makroparametererstatning er strengt tatt etter navn: ved makrobehandlingstid erstattes verdien av en parameter ordrett med navnet. Den mest kjente typen resulterende feil var bruken av en parameter som i seg selv var et uttrykk og ikke et primærnavn når makroforfatteren forventet et navn. I makroen:
foo: makro til last a*bhensikten var at den kallende rutinen skulle oppgi navnet på en variabel, og den "globale b"-variabelen eller konstanten ville bli brukt til å multiplisere "a". Hvis foo kalles med parameteren a-c, skjer makroutvidelse load a-c*b. For å unngå mulig tvetydighet kan brukere av makroprosessorer legge inn formelle parametere innenfor makrodefinisjoner i parentes, eller anropsrutiner kan omslutte inndataparametere i parentes. [ 5 ] Den korrekte makroen, med parentesene, ville altså være:
foo: makro til belastning (a)*bog utvidelsen av den, ville resultere i:load (a-c)*b
PL /I og C/C++ tilbyr makroer, men denne funksjonen kan bare manipulere tekst. På den annen side beholder homoikoniske språk , som Lisp , Prolog og Forth , kraften til assembly-språkmakroer fordi de kan manipulere sin egen kode som data.
Noen montører har innlemmet elementer av strukturert programmering for å kode utførelsesflyten. Det tidligste eksemplet på denne tilnærmingen var i Concept-14 makrosettet, opprinnelig foreslått av Dr. HD Mills (mars 1970), og implementert av Marvin Kessler ved IBMs Federal Systems Division , som utvidet S /360 med IF/ELSE/ENDIF strømningskontrollblokker og lignende. [ 6 ] Dette var en måte å redusere eller eliminere bruken av GOTO-operasjoner i assembly-språkkode, en av hovedfaktorene som forårsaker spaghetti-kode i assembly-språk. Denne tilnærmingen ble allment akseptert på begynnelsen av 1980-tallet (de siste dagene med storskala bruk av forsamlingsspråk).
Et merkelig design var A-natural, en "strømorientert" assembler for 8080 / Z80-prosessorene [ referanse nødvendig ] fra Whitesmiths Ltd. (utviklere av det Unix - lignende Idris-operativsystemet ), og det som ble rapportert som den første kommersielle C-en. kompilator). Språket ble klassifisert som en assembler, fordi det fungerte med rå maskinelementer som opkoder, registre og minnereferanser; men den inkorporerte en uttrykkssyntaks for å angi rekkefølgen for utførelse. Parenteser og andre spesielle symboler, sammen med blokkorienterte strukturerte programmeringskonstruksjoner, kontrollerte sekvensen av genererte instruksjoner. A-natural ble bygget som objektspråket til en C-kompilator, snarere enn håndkoding, men dens logiske syntaks fikk noen tilhengere.
Det har vært liten tilsynelatende etterspørsel etter mer sofistikerte montører på grunn av nedgangen i storskala utvikling av forsamlingsspråk. [ 7 ] Til tross for dette, utvikles og brukes de fortsatt i tilfeller der ressursbegrensninger eller særtrekk i målsystemarkitekturen hindrer effektiv bruk av høynivåspråk. [ 8 ]
Forsamlingsspråk ble først utviklet på 1950-tallet, da de ble referert til som andre generasjons programmeringsspråk. For eksempel var SOAP (Symbolic Optimal Assembly Program) et monteringsspråk fra 1957 for IBM 650 -datamaskinen . Monteringsspråk eliminerte mye av den feilutsatte og tidkrevende programmeringen av førstegenerasjonsspråk, som var nødvendig med tidlige datamaskiner, og frigjorde programmerere fra kjedelighet som å huske numeriske koder og beregne adresser. De ble en gang mye brukt til all slags programmering. På 1980-tallet (1990-tallet på mikrodatamaskiner ) hadde imidlertid bruken i stor grad blitt erstattet av språk på høyt nivå , [ referanse nødvendig ] i søken etter forbedret programmeringsproduktivitet. I dag, selv om assembly-språk nesten alltid håndteres og genereres av kompilatorer , brukes det fortsatt til direkte maskinvaremanipulering, tilgang til spesialiserte prosessorinstruksjoner eller for å løse kritiske ytelsesproblemer. Typiske bruksområder er enhetsdrivere , innebygde systemer på lavt nivå og sanntidssystemer .
Historisk sett har et stort antall programmer blitt skrevet utelukkende på assemblerspråk. Operativsystemer ble nesten utelukkende skrevet i assemblerspråk frem til den utbredte aksepten av programmeringsspråket C på 1970- og begynnelsen av 1980-tallet. Dessuten ble mange kommersielle applikasjoner skrevet på assemblerspråk, inkludert mye av programvaren skrevet av store selskaper for IBM-stormaskiner. COBOL- og FORTRAN -språkene fortrengte etter hvert mye av dette arbeidet, selv om en rekke store organisasjoner beholdt applikasjonsrammeverket for monteringsspråk langt inn på 1990-tallet.
De fleste tidlige mikrodatamaskiner stolte på håndkodet monteringsspråk, inkludert de fleste operativsystemer og store applikasjoner. Dette var fordi disse systemene hadde alvorlige ressursbegrensninger, påførte idiosynkratisk minne og skjermarkitekturer, og ga begrensede og buggy systemtjenester. Kanskje viktigere var mangelen på førsteklasses kompilatorer av høynivåspråk egnet for bruk på mikrodatamaskinen. En psykologisk faktor kan også ha spilt en rolle: den første generasjonen av mikrodatamaskinprogrammerere beholdt en "tråd og tang" hobbyholdning.
I en mer kommersiell sammenheng var de største grunnene til å bruke assemblerspråk å lage programmer med minimum størrelse, minimum overhead og større hastighet og pålitelighet.
Typiske eksempler på datidens store assembly-språkprogrammer er IBM PC DOS- operativsystemer og tidlige applikasjoner som Lotus 1-2-3 - regnearket , og nesten alle de populære spillene for Atari 800 -familien av personlige datamaskiner. Selv på 1990-tallet ble de fleste konsollvideospill skrevet i assembler, inkludert de fleste spill for Mega Drive/Genesis og Super Nintendo Entertainment System . I følge noen bransjeinnsidere var assemblerspråk det beste programmeringsspråket å bruke for å få mest mulig ut av Sega Saturn , en konsoll som det var notorisk utfordrende å utvikle og programmere spill for. [ 9 ] Det populære arkadespillet NBA Jam (1993) er et annet eksempel. Assembler har lenge vært det primære utviklingsspråket på Commodore 64 , Atari ST , samt ZX Spectrum . Dette var i stor grad slik fordi BASIC -dialektene på disse systemene tilbød utilstrekkelig utførelseshastighet, samt utilstrekkelige funksjoner til å dra full nytte av den tilgjengelige maskinvaren. Noen systemer, spesielt Amiga, har til og med IDE-er med svært avanserte makroer og feilsøkingsfunksjoner, for eksempel freeware ASM-One assembler , som kan sammenlignes med Microsoft Visual Studio (ASM-One går foran Microsoft Visual Studio).
Monteringsmaskinen for VIC-20 ble skrevet av Don French og utgitt av French Silk. Med en lengde på 1639 byte, mener forfatteren at det er den minste symbolske samleren som noen gang er skrevet. Samleren støttet den vanlige symbolske adresseringen og definisjonen av tegnstrenger eller heksadesimale strenger. Det tillot også adresseuttrykk som kunne kombineres med operasjonene addisjon , subtraksjon , multiplikasjon , divisjon , logisk OG , logisk ELLER og eksponentiering . [ 10 ]
Det har alltid vært debatter om nytten og ytelsen til forsamlingsspråk i forhold til språk på høyt nivå. Forsamlingsspråk har spesifikke nisjer der det betyr noe (se nedenfor). Men generelt kan moderne optimeringskompilatorer for å oversette høynivåspråk til kode kjøre like raskt som håndskrevne assembly-språk, til tross for moteksempler som kan finnes. [ 11 ] [ 12 ] [ 13 ] Kompleksiteten til moderne prosessorer og minnedelsystemet gjør effektiv optimalisering stadig vanskeligere for kompilatorer, så vel som for assembler-programmerere. [ 14 ] [ 15 ] I tillegg, og til forferdelse for elskere av effektivitet, har stadig økende prosessorytelse ført til at de fleste CPU - er er inaktive mesteparten av tiden, med forsinkelser forårsaket av forutsigbare flaskehalser. som input/output- operasjoner og minne personsøking . Dette har gjort utførelseshastigheten for råkode mindre av et problem for mange programmerere.
Det er noen situasjoner der fagfolk kan velge å bruke assemblerspråk. For eksempel når:
Imidlertid undervises det fortsatt i monteringsspråk i de fleste informatikk- og elektroniske ingeniørprogrammer . Selv om få programmerere i dag jevnlig jobber med assemblerspråk som verktøy, er de grunnleggende konseptene fortsatt svært viktige. Slike grunnleggende emner som binær aritmetikk , minneallokering , stabelbehandling, tegnsettkoding, avbruddsbehandling og kompilatordesign ville være vanskelig å studere i detalj uten en forståelse av hvordan datamaskinen fungerer på maskinvarenivå. Siden oppførselen til datamaskinen er grunnleggende definert av instruksjonssettet , er den logiske måten å lære slike konsepter på å studere et assemblerspråk. De fleste moderne datamaskiner har et lignende sett med instruksjoner. Derfor er det nok å studere et enkelt samlespråk for å lære: i) de grunnleggende konseptene; ii) gjenkjenne situasjoner der bruk av assemblerspråk kan være hensiktsmessig; og iii) se hvordan effektiv kjørbar kode kan lages av høynivåspråk [ 18 ]
Hardkodet assemblyspråk brukes vanligvis i systemets oppstarts-ROM ( BIOS på IBM PC-kompatible systemer ). Denne lavnivåkoden brukes blant annet til å initialisere og teste systemmaskinvaren før du laster operativsystemet , og lagres i ROM . Når et visst nivå av maskinvareinitialisering har funnet sted, overføres kjøringen til annen kode, vanligvis skrevet på høynivåspråk; men koden som kjører umiddelbart etter at strømmen er satt på, er vanligvis skrevet på assemblerspråk. Det samme gjelder for oppstartslastere .
Mange kompilatorer oversetter høynivåspråk til assemblerspråk først, før full kompilering, slik at assemblykoden kan sees for feilsøking og optimaliseringsformål. Relativt lavnivåspråk, som C , gir ofte spesiell syntaks for å bygge inn monteringsspråk på hver maskinvareplattform. Systemets bærbare kode kan deretter bruke disse prosessorspesifikke komponentene gjennom et enhetlig grensesnitt.
Monteringsspråk er også verdifullt i reverse engineering , siden mange programmer bare distribueres i maskinkodeform. Maskinkode er vanligvis lett å oversette til assemblerspråk og deretter nøye undersøkt på denne måten, men det er svært vanskelig å oversette til et språk på høyt nivå. Verktøy som Interactive Disassembler bruker utstrakt bruk av disassembleren til slike formål.
En nisje som bruker assemblerspråk er demoscenen . Enkelte konkurranser krever at deltakerne begrenser sine kreasjoner til en svært liten størrelse (f.eks. 256 byte , 1 KB , 4 KB eller 64 KB), og assembly-språket er det foretrukne språket for å oppnå dette målet. [ 19 ] Når ressurser er et problem, er monteringskoding en nødvendighet, spesielt på systemer begrenset av CPU-behandling, for eksempel tidlige modeller av Amiga og Commodore 64 . Optimalisert monteringskode skrives "for hånd" av programmerere i et forsøk på å minimere antall CPU-sykluser som brukes. CPU-begrensninger er så store at hver syklus teller. Bruk av slike metoder har gjort det mulig for systemer som Commodore 64 å produsere sanntids 3D-grafikk med avanserte effekter, en prestasjon som kan anses som usannsynlig eller til og med umulig for et system med en 0,99 MHz prosessor . [ referanse nødvendig ]
For enhver gitt personlig datamaskin, stormaskin, innebygd system og spillkonsoll, både tidligere og nåtid, er det skrevet minst én, og muligens dusinvis av montører. For noen eksempler, se listen over montører .
På Unix -systemer kalles assembleren tradisjonelt som , selv om det ikke er en enkel kode, vanligvis skrives en ny for hver port. En rekke Unix-varianter bruker GAS
Innenfor prosessorgruppene har hver assembler sin egen dialekt. Noen ganger kan noen samlere lese en annens dialekt, for eksempel kan TASM lese gammel kode fra MASM , men ikke omvendt. FASM og NASM har lignende syntaks, men hver støtter forskjellige makroer som kan være vanskelige å portere fra den ene til den andre. De grunnleggende tingene er alltid de samme, men de avanserte funksjonene vil være forskjellige [ 20 ]
Dessuten kan monteringsspråk noen ganger være bærbare på tvers av forskjellige operativsystemer på samme type CPU . Ringekonvensjoner mellom operativsystemer varierer ofte litt eller ikke i det hele tatt. og med forsiktighet er det mulig å få portabilitet i assemblerspråk, vanligvis ved å koble til et C-språkbibliotek som ikke endres mellom operativsystemer. En instruksjonssettsimulator (som ideelt sett ville vært skrevet i assemblerspråk) kan i teorien behandle binær- / objektkoden til en hvilken som helst assembler) for å oppnå portabilitet selv på tvers av plattformer (med ikke mer overhead enn en tolk). av typisk bytekode ). Dette er i hovedsak hva mikrokode oppnår når en maskinvareplattform endres internt.
For eksempel avhenger mange ting i libc av at forprosessoren gjør ting med programmet før kompilering som er OS-spesifikke eller C-spesifikke. Faktisk er noen funksjoner og symboler ikke engang garantert å eksistere utenfor forprosessoren. Enda verre er størrelsen og rekkefølgen på feltene med strukturer, så vel som størrelsen på visse typedefs som off_t , ikke tilgjengelig i assemblerspråk uten hjelp av et konfigureringsskript, og varierer selv mellom Linux- versjoner , noe som gjør det umulig å portere funksjonskall i libc andre enn de som tar enkle heltall eller pekere som parametere. For å håndtere disse problemene tilbyr FASMLIB-prosjektet et bærbart assembly-språkbibliotek for Win32- og Linux-plattformene, men det er fortsatt svært ufullstendig. [ 21 ]
Noen språk på svært høyt nivå, som C og Borland/Pascal, støtter inline-montering, der relativt korte deler av monteringskoden kan bygges inn i språkkoden på høyt nivå. Forth - språket inneholder vanligvis en assembler som brukes til å kode ord.
De fleste bruker en emulator for å feilsøke assemblerspråkprogrammene sine.
Følgende er et eksempel på det klassiske Hello World- programmet skrevet for x86 -prosessorarkitekturen (under DOS- operativsystemet ).
; ---------------------------------------------------- ; Program som skriver ut en streng på skjermen ; ---------------------------------------------- .modell liten ; minnemodell .stack ; stabelsegment .data ; datasegment String1 DB ' Hello World. ; streng som skal skrives ut (avsluttes i $) .kode ; kodesegment ; ---------------------------------------------------- ; Start av programmet ; ---------------------------------------------- program: ; -------------------------------------------------- -------------------------------------------------- ; start datasegment ; -------------------------------------------------- -------------------------------------------------- MOV AXE , @ data ; laster inn i AX adressen til MOV DS datasegmentet , AX ; flytte adresse til segmentregister via AX ; -------------------------------------------------- -------------------------------------------------- ; Skriv ut en streng på skjermen ; -------------------------------------------------- -------------------------------------------------- MOV DX , offset String1 ; flytt til DX adressen til strengen for å skrive ut MOV AH , 9 ; AH = kode for å fortelle MS DOS å skrive ut strengen i DS:DX INT 21 h på skjermen ; kall til MS DOS for å utføre funksjonen (i dette tilfellet spesifisert i AH) ; -------------------------------------------------- -------------------------------------------------- ; Avslutt programmet ; -------------------------------------------------- -------------------------------------------------- INT 20:00 ; _ ring til MS DOS for å avslutte programmet avslutte programmetEt utvalg instruksjoner for en virtuell datamaskin [ 22 ] ) med tilhørende minneadresser der instruksjonene vil være plassert. Disse adressene er IKKE statiske. Hver instruksjon er ledsaget av generert assembly-språkkode (objektkode) som samsvarer med den virtuelle datamaskinarkitekturen, eller ISA -instruksjonssettet .
Dir. | Merkelapp | Instruksjon | Maskinkode [ 23 ] |
---|---|---|---|
.begynne | |||
.org 2048 | |||
a_start | .equ 3000 | ||
2048 | ld [lengde], %r1 | ||
2064 | bli ferdig | 00000010 10000000 00000000 00000110 | |
2068 | addcc %r1,-4,%r1 | 10000010 10000000 01111111 11111100 | |
2072 | addcc %r1,%r2,%r4 | 10001000 10000000 01000000 00000010 | |
2076 | ld %r4,%r5 | 11001010 00000001 00000000 00000000 | |
2080 | ba løkke | 00010000 10111111 11111111 11111011 | |
2084 | addcc %r3,%r5,%r3 | 10000110 10000000 11000000 00000101 | |
2088 | donere: | jmpl %r15+4,%r0 | 10000001 11000011 11100000 00000100 |
2092 | lengde: | tjue | 00000000 00000000 00000000 00010100 |
2096 | adresse: | a_start | 00000000 00000000 00001011 10111000 |
.org a_start | |||
3000 | en: |
ARC er en undergruppe av den SPARC-prosessorbaserte arkitekturmodellen. ARC (A RISC Computer) inneholder de fleste funksjonene
viktige deler av SPARC-arkitekturen.
Adresse | Merkelapp | Instruksjon | Kommentarer |
---|---|---|---|
.begynne | |||
.org 2048 | |||
a_start: | .equ 3000 | ! Array-minneadressen starter på 3000 | |
2048 | ld [lengde], %r1 | ! Angi lengden på matrisen i posten | |
2052 | ld [adresse], %r2 | ! Fiks adresse til | |
2056 | anddcc %r3, %r0, %r3 | ! Delsummen settes til null. | |
2060 | Løkke: | anddcc %r1, %r1, %r0 | ! Jeg sjekker om r1 har gjenværende elementer |
2064 | bli ferdig | ||
2068 | addcc %r1, -4, %r1 | ! Reduser størrelsen på matrisen | |
2072 | ld %r1 + %r2, %r4 | !Last inn neste element i r4 | |
2076 | addcc %r3, %r4, %r3 | ! Jeg oppdaterer delsummen i r3 | |
2080 | ba løkke | ! Kontroller skjæretilstanden på nytt | |
2084 | donere: | jmpl %r15 + 4, %r0 | ! Gå tilbake til hovedrutinen |
2088 | lengde: | tjue | ! Matrisestørrelse i 20 byte, 5 tall |
2092 | adresse: | a_start | |
.org a_start | ! oppstart av arrangement til | ||
en: | 25 | ||
femten | |||
-tjue | |||
-35 | |||
femten | |||
.slutt | ! slutten av programmet |
Monteringsspråkkode for µC Intel 80C51 :
ORG 8030 H inkluderer T05SEG: SETB TR0 JNB uSEG , T05SEG ;denne subrutinen brukes CLR TR0 ;for å telle CPL uSEG ; 0,5 sekunder via MOV R1 , DPL ;avbruddstidtaker 0. INVOKE MOV R2 , DPH CJNE R2 , TPH CJNE R2 CJNE R1 , #78 H , T05SEG MOV DPTR , #0 RETMonteringsspråkkode for Microchips 16F84 mikrokontroller :
ORG 0 Start bcf STATUS , RP0 clrf PORTB movlw 0xFF movwf PORTA bsf STATUS , RP0 Main movf PORTA , W movwf Counter movf Counter , F btfsc STATUS , Z goto Desimalpunkt ' lw d ' s 9 STATUS _ _ _montører
Demontører
skrubbere
Andre
Operativsystemer skrevet helt i assembler :