Kommandostrukturen för assemblerspråket innehåller: Allmänna egenskaper hos kommandosystemet för Assembler-språket för IBM-PC (grundläggande uppsättning kommandon, grundläggande metoder för att adressera operander). Programstruktur i Assembler-språk. Programsegment. anta direktiv

Ämne 1.4 Monteringsmnemonics. Kommandostruktur och format. Typer av adressering. Mikroprocessor instruktionssystem

Planen:

1 Monteringsspråk. Grundläggande koncept

2 Samla språksymboler

3 typer av assembler uttalanden

4 Monteringsdirektiv

5 Processorinstruktionssystem

1 jagassembleringsspråk. Grundläggande koncept

assembleringsspråkär en symbolisk representation av maskinspråk. Alla processer i en maskin på den lägsta hårdvarunivån drivs endast av maskinspråkkommandon (instruktioner). Av detta framgår att, trots det vanliga namnet, är assemblerspråket olika för varje typ av dator.

Ett assemblerspråksprogram är en samling minnesblock som kallas minnessegment. Ett program kan bestå av ett eller flera sådana blocksegment. Varje segment innehåller en samling språkmeningar, som var och en upptar en separat rad med programkod.

Det finns fyra typer av assembler-påståenden:

1) kommandon eller instruktioner som är symboliska analoger till maskininstruktioner. Under översättningsprocessen omvandlas assemblerinstruktioner till motsvarande kommandon för mikroprocessorinstruktionsuppsättningen;

2) makrokommandon -meningar i programtexten, formaterade på ett visst sätt, ersatta under sändning med andra meningar;

3) direktiv,som är instruktioner till assembleröversättaren att utföra vissa åtgärder. Direktiven har inga motsvarigheter i maskinrepresentation;

4) kommentarsrader , som innehåller alla symboler, inklusive bokstäver i det ryska alfabetet. Kommentarer ignoreras av översättaren.

­ Monteringsprogrammets struktur. Sammansättningssyntax.

De meningar som utgör ett program kan vara en syntaktisk konstruktion som motsvarar ett kommando, makro, direktiv eller kommentar. För att assembleröversättaren ska känna igen dem måste de vara utformade enligt vissa syntaktiska regler. För att göra detta är det bäst att använda en formell beskrivning av språkets syntax, som grammatikens regler. De vanligaste sätten att beskriva ett programmeringsspråk på detta sätt - syntaxdiagram Och utökade Backus-Naur-former. För praktisk användning mer bekvämt syntaxdiagram. Till exempel kan syntaxen för assemblermeningar beskrivas med hjälp av syntaxdiagram som visas i följande figurer 10, 11, 12.

Figur 10 - Sammansättningssatsformat


­ Figur 11 - Direktivformat

­ Figur 12 - Format för kommandon och makron

På dessa bilder:

­ etikettens namn- en identifierare, vars värde är adressen till den första byten i meningen i källtexten för programmet som den betecknar;

­ Namn -En identifierare som skiljer detta direktiv från andra direktiv med samma namn. Som ett resultat av montörens bearbetning av ett visst direktiv kan vissa egenskaper tilldelas det namnet;

­ operationskod (OPC) och direktiv - dessa är mnemonics för motsvarande maskininstruktion, makroinstruktion eller översättardirektiv;

­ operander -delar av ett kommando-, makro- eller assemblerdirektiv som anger de objekt på vilka åtgärder utförs. Assembly språkoperander beskrivs av uttryck med numeriska och textkonstanter, etiketter och variabelidentifierare med operatortecken och några reserverade ord.

Syntaxdiagram hjälper hitta och följ sedan vägen från diagrammets ingång (vänster) till dess utgång (höger). Om en sådan väg finns är meningen eller konstruktionen syntaktisk korrekt. Om det inte finns någon sådan väg kommer kompilatorn inte att acceptera denna konstruktion.

­ 2 Samlingsspråksymboler

Godkända tecken när du skriver programtext är:

1) alla latinska bokstäver: A-Z,a-z. I det här fallet anses stora och små bokstäver vara likvärdiga;

2) nummer från 0 innan 9 ;

3) tecken ? , @ , $ , _ , & ;

4) separatorer , . () < > { } + / * % ! " " ? = # ^ .

Församlingens språkuttalanden bildas av lexem, som är syntaktiskt oskiljaktiga sekvenser av giltiga språksymboler som är meningsfulla för översättaren.

Lexemesär:

1) identifierare - sekvenser av giltiga tecken som används för att representera programobjekt såsom opkoder, variabelnamn och etikettnamn. Regeln för att skriva identifierare är följande: en identifierare kan bestå av ett eller flera tecken;

2) strängar av tecken - sekvenser av tecken inneslutna i enstaka eller dubbla citattecken;

3) heltal i något av följande talsystem : binär, decimal, hexadecimal. Identifiering av nummer när du skriver dem i assemblerprogram utförs enligt vissa regler:

4) decimaltal kräver inga ytterligare tecken för att identifieras, till exempel 25 eller 139. För identifiering i programmets källtext binära tal Efter att ha skrivit ner nollorna och de som utgör dem, är det nödvändigt att sätta det latinska " b”, till exempel 10010101 b.

5) Hexadecimala tal har fler konventioner när du skriver dem:

För det första består de av siffror 0...9 , gemener och versaler i det latinska alfabetet a,b, c,d,e,f eller A,B,C,D,E,F.

För det andra kan översättaren ha svårt att känna igen hexadecimala tal på grund av att de endast kan bestå av siffrorna 0...9 (till exempel 190845) eller börja med en bokstav i det latinska alfabetet (t.ex. ef15). För att "förklara" för översättaren att en given token inte är ett decimaltal eller en identifierare, måste programmeraren markera det hexadecimala numret på ett speciellt sätt. För att göra detta, i slutet av sekvensen av hexadecimala siffror som utgör ett hexadecimalt tal, skriv den latinska bokstaven " h" Detta är ett måste. Om ett hexadecimalt tal börjar med en bokstav, skrivs en inledande nolla före den: 0 ef15 h.

Nästan varje mening innehåller en beskrivning av ett objekt på vilket eller med hjälp av vilket någon handling utförs. Dessa objekt kallas operander. De kan definieras så här: operander- det här är objekt (vissa värden, register eller minnesceller) som instruktioner eller direktiv verkar på, eller så är det objekt som definierar eller förtydligar verkan av instruktioner eller direktiv.

Det är möjligt att klassificera operanderna enligt följande:

­ konstanta eller omedelbara operander;

­ adressoperander;

­ rörliga operander;

adressräknare;

­ registeroperand;

­ bas- och indexoperander;

­ strukturoperander;

uppgifter.

Operander är de elementära komponenterna som ingår i en maskininstruktion som betecknar de objekt på vilka en operation utförs. I ett mer allmänt fall kan operander inkluderas som komponenter i mer komplexa formationer som kallas uttryck.

Uttryck är kombinationer av operander och operatorer betraktade som en helhet. Resultatet av att utvärdera ett uttryck kan vara adressen till någon minnescell eller något konstant (absolut) värde.

­ 3 typer av assembler uttalanden

Låt oss lista de möjliga typerna montöroperatörer och syntaktiska regler för bildandet av assembleruttryck:

­ aritmetiska operatorer;

­ skiftoperatörer;

­ jämförelseoperatörer;

­ logiska operatorer;

­ indexoperatör;

­ typomdefinieringsoperatör;

­ segmentöverstyrningsoperatör;

­ strukturtyp namngivningsoperator;

­ operator för att erhålla segmentkomponenten av en uttrycksadress;

­ operator för att erhålla förskjutningen av ett uttryck.

1 Monteringsdirektiv

­ Det finns monteringsdirektiv:

1) Segmenteringsdirektiv. Under den tidigare diskussionen fick vi reda på alla grundläggande regler för att skriva instruktioner och operander i ett assemblerprogram. Frågan är fortfarande öppen om hur man korrekt formaterar sekvensen av kommandon så att översättaren kan bearbeta dem och mikroprocessorn kan utföra dem.

När vi övervägde mikroprocessorns arkitektur, lärde vi oss att den har sex segmentregister genom vilka den kan arbeta samtidigt:

­ med ett kodsegment;

­ med ett stacksegment;

­ med ett datasegment;

­ med ytterligare tre datasegment.

Fysiskt sett är ett segment ett minnesområde som upptas av instruktioner och (eller) data, vars adresser beräknas i förhållande till värdet i motsvarande segmentregister. Den syntaktiska beskrivningen av ett segment i assembler är konstruktionen som visas i figur 13:


­ Figur 13 - Syntaktisk beskrivning av ett segment i assembler

Det är viktigt att notera att funktionaliteten för ett segment är något bredare än att bara dela upp ett program i block med kod, data och stack. Segmentering är en del av en mer allmän mekanism förknippad med begreppet modulär programmering. Det innebär att förena designen av objektmoduler skapade av kompilatorn, inklusive de från olika programmeringsspråk. Detta gör att du kan kombinera program skrivna på olika språk. Operanderna i SEGMENT-direktivet är avsedda att implementera olika alternativ för en sådan förening.

2) Direktiv för noteringsförvaltning. Direktiv för noteringsförvaltning är indelade i följande grupper:

­ allmänna riktlinjer för listning;

­ direktiv för listning av inkluderade filer;

­ direktiv för utmatning av villkorliga monteringsblock;

­ direktiv för att visa makrokommandon i listan;

­ direktiv för att visa information om korsreferenser i förteckningen;

­ direktiv för att ändra noteringsformatet.

2 Processorinstruktionssystem

Processorns kommandosystem visas i figur 14.

Låt oss titta på huvudgrupperna av kommandon.

­ Figur 14 - Klassificering av monteringsanvisningar

Lagen är:

1 Dataöverföringskommandon. Dessa instruktioner upptar en mycket viktig plats i instruktionsuppsättningen för alla processorer. De utför följande viktiga funktioner:

­ lagra innehållet i processorns interna register i minnet;

­ kopiering av innehåll från ett minnesområde till ett annat;

­ skriva till och läsa från I/O-enheter.

På vissa processorer utförs alla dessa funktioner av en enda instruktion MOV (för byteöverföringar - MOVB ) men med olika operandadresseringsmetoder.

I andra processorer förutom kommandot MOV Det finns flera fler kommandon för att utföra dessa funktioner. Dataöverföringskommandon inkluderar också kommandon för informationsutbyte (deras beteckning är baserad på ordet Utbyta ). Information kan utbytas mellan interna register, mellan två halvor av ett register ( BYTA ) eller mellan ett register och en minnescell.

2 aritmetiska kommandon. Aritmetiska instruktioner behandlar operandkoder som numeriska binära eller BCD-koder. Dessa kommandon kan delas in i fem huvudgrupper:

­ operationsinstruktioner för fast punkt (addition, subtraktion, multiplikation, division);

­ flyttalsinstruktioner (addition, subtraktion, multiplikation, division);

­ rengöringskommandon;

­ kommandon för att öka och minska;

­ jämförelsekommando.

3 Instruktioner med fast punkt behandlar koder i processorregister eller minne som om de vore normala binära koder. Flyttalsinstruktioner (prick) använder ett format för att representera tal med exponent och mantissa (vanligtvis upptar dessa tal två på varandra följande minnesceller). I modern kraftfulla processorer Uppsättningen flyttalsinstruktioner är inte begränsad till bara fyra aritmetiska operationer, utan innehåller också många andra mer komplexa instruktioner, till exempel beräkning av trigonometriska funktioner, logaritmiska funktioner, såväl som komplexa funktioner som är nödvändiga för ljud- och bildbehandling.

4 Tydliga instruktioner är utformade för att skriva en nollkod till ett register eller minnesplats. Dessa kommandon kan ersättas med nollkodskommandon framåt, men speciella tydliga kommandon är vanligtvis snabbare än framåtkommandon.

5 Öka (öka med ett) och minska kommandon

(minskar med en) är också mycket bekväma. De kan i princip ersättas av lägg till eller subtrahera-ett instruktioner, men ökning och minskning är snabbare än lägg till och subtrahera. Dessa instruktioner kräver en ingångsoperand, som också är en utgångsoperand.

6 Compare-instruktionen används för att jämföra två ingångsoperander. I huvudsak beräknar den skillnaden mellan dessa två operander, men genererar inte en utgångsoperand, utan ändrar bara bitarna i processorstatusregistret baserat på resultatet av denna subtraktion. Instruktionen som följer på jämförelseinstruktionen (vanligtvis en hoppinstruktion) kommer att undersöka bitarna i processorns statusregister och utföra åtgärder baserat på deras värden. Vissa processorer tillhandahåller instruktioner för kedjejämförelse av två sekvenser av operander som finns i minnet.

7 logiska kommandon. Logiska instruktioner utför logiska (bitvisa) operationer på deras operander, det vill säga de behandlar koderna för operanderna inte som ett enda nummer, utan som en uppsättning individuella bitar. Det är så de skiljer sig från aritmetiska instruktioner. Logiska kommandon utför följande grundläggande operationer:

­ logisk AND, logisk ELLER, addition modulo 2 (Exklusiv ELLER);

­ logiska, aritmetiska och cykliska skift;

­ kontroll av bitar och operander;

­ ställa in och rensa bitar (flaggor) i processorstatusregistret ( PSW).

Instruktioner för logiska operationer låter dig utvärdera grundläggande logiska funktioner bit för bit från två ingångsoperander. Dessutom används AND-operationen för att framtvinga rensning av specificerade bitar (som en av operanderna används en maskkod där de bitar som kräver rensning sätts till noll). ELLER-operationen används för att tvinga de specificerade bitarna att ställas in (som en av operanderna används en maskkod där de bitar som kräver inställning till ett är lika med ett). Operationen "Exklusiv ELLER" används för att invertera specificerade bitar (en maskkod används som en av operanderna, där bitarna som ska inverteras är satta till en). Instruktionerna kräver två ingångsoperander och producerar en utgångsoperand.

8 Skiftinstruktioner låter dig flytta operandkoden bit för bit åt höger (mot bitarna av låg ordning) eller åt vänster (mot bitar av hög ordning). Typen av skift (logisk, aritmetisk eller cyklisk) bestämmer vad det nya värdet på den höga biten (för ett högerskift) eller lågbiten (för ett vänsterskift) kommer att vara, och bestämmer också om det gamla värdet på den höga biten (för en vänsterväxling) kommer att lagras någonstans, eller minst signifikant bit (när den skiftas åt höger). Cirkulära skift gör att du kan skifta kodbitarna för en operand på ett cirkulärt sätt (medurs för ett högerskifte eller moturs för ett vänsterskift). I detta fall kan växlingsringen inkludera en bärflagga eller inte. Bärflaggabiten (om den används) lagrar värdet på den mest signifikanta biten vid rotation åt vänster och den minst signifikanta biten vid rotation åt höger. Följaktligen kommer värdet på bärflaggabiten att skrivas om till den minst signifikanta biten under ett cykliskt skift till vänster och till den mest signifikanta biten under ett cykliskt skift till höger.

9 Övergångskommandon. Hoppkommandon är utformade för att organisera alla typer av loopar, grenar, subrutinsamtal, etc., det vill säga de stör det sekventiella flödet av programexekvering. Dessa instruktioner skriver ett nytt värde till programräknarregistret och får därigenom processorn att flytta inte till nästa instruktion i ordning, utan till någon annan instruktion i programminnet. Vissa övergångskommandon ger en efterföljande återgång tillbaka till den punkt från vilken övergången gjordes, andra tillhandahåller inte detta. Om en retur tillhandahålls, lagras de aktuella processorparametrarna i stacken. Om en retur inte tillhandahålls, sparas inte de aktuella processorparametrarna.

Hoppkommandon utan retur är indelade i två grupper:

­ ovillkorliga hoppkommandon;

­ villkorliga hoppkommandon.

Dessa kommandon använder orden Förgrening (förgrening) och Hoppa (hopp).

Ovillkorliga hoppkommandon orsakar ett hopp till ny adress oavsett vad. De kan orsaka ett hopp till en specificerad offset-mängd (framåt eller bakåt) eller till en specificerad minnesadress. Offsetvärdet eller det nya adressvärdet anges som ingångsoperand.

Villkorliga hoppkommandon orsakar inte alltid ett hopp, utan endast när specificerade villkor är uppfyllda. Sådana villkor är vanligtvis värdena för flaggor i processorstatusregistret ( P.S.W. ). Det vill säga att övergångsvillkoret är resultatet av en tidigare operation som ändrar flaggornas värden. Totalt kan det finnas från 4 till 16 sådana övergångsförhållanden. Flera exempel på villkorliga övergångskommandon:

­ hoppa om lika med noll;

­ hoppa om inte noll;

­ hoppa om det finns översvämning;

­ hoppa om det inte finns något spill;

­ hoppa om det är större än noll;

­ hoppa om mindre än eller lika med noll.

Om övergångsvillkoret är uppfyllt, laddas ett nytt värde in i kommandoräknarregistret. Om övergångsvillkoret inte är uppfyllt, inkrementeras programräknaren helt enkelt, och processorn väljer och exekverar nästa instruktion i ordning.

Specifikt, för att kontrollera hoppförhållandena, används en jämförelseinstruktion (CMP) som föregår en villkorlig hoppinstruktion (eller till och med flera villkorliga hoppinstruktioner). Men flaggor kan också ställas in med vilket annat kommando som helst, till exempel ett dataöverföringskommando eller vilket aritmetiskt eller logiskt kommando som helst. Observera att själva hoppkommandona inte ändrar flaggorna, vilket är just det som gör att du kan placera flera hoppkommandon efter varandra.

Avbrottskommandon har en speciell plats bland hopp-med-retur-kommandon. Dessa instruktioner kräver ett avbrottsnummer (vektoradress) som en ingångsoperand.

Slutsats:

Monteringsspråk är en symbolisk representation av maskinspråk. Monteringsspråket är olika för varje typ av dator. Ett assemblerspråksprogram är en samling minnesblock som kallas minnessegment. Varje segment innehåller en samling språkmeningar, som var och en upptar en separat rad med programkod. Det finns fyra typer av assembler-satser: kommandon eller instruktioner, makron, direktiv och kommentarsrader.

Godtagbara tecken när du skriver programtext är alla latinska bokstäver: A-Z,a-z. I det här fallet anses stora och små bokstäver vara likvärdiga; siffror från 0 innan 9 ; tecken ? , @ , $ , _ , & ; separatorer , . () < > { } + / * % ! " " ? = # ^ .

Följande typer av assembleroperatorer och syntaktiska regler för att bilda assembleruttryck används. aritmetiska operatorer, skiftoperatorer, jämförelseoperatorer, logiska operatorer, indexoperator, typomdefinieringsoperator, segmentomdefinitionsoperator, strukturtypsnamnoperator, operator för att erhålla segmentkomponenten av adressen till ett uttryck, operator för att erhålla förskjutningen av ett uttryck.

Kommandosystemet är indelat i 8 huvudgrupper.

­ Kontrollfrågor:

1 Vad är assemblerspråk?

2 Vilka symboler kan användas för att skriva kommandon i assemblerspråk?

3 Vad är taggar och deras syfte?

4 Förklara strukturen för assemblerkommandon.

5 Lista 4 typer av assemblermeningar.

NATIONELLA UNIVERSITETET I UZBEKISTAN UPPGIFT EFTER MIRZO ULUGBEK

DATORTEKNISK FAKULTET

Om ämnet: Semantisk analys av en EXE-fil.

Avslutad:

Tasjkent 2003.

Förord.

Monteringsspråk och kommandostruktur.

EXE-filstruktur (semantisk analys).

COM-filstruktur.

Principen för verkan och spridning av viruset.

Demonterare.

Program.

Förord

Yrket som programmerare är fantastiskt och unikt. Nuförtiden är det omöjligt att föreställa sig vetenskap och liv utan den senaste tekniken. Allt relaterat till mänsklig aktivitet kan inte göras utan datateknik. Och detta bidrar till dess höga utveckling och perfektion. Även om utvecklingen av persondatorer började för inte så länge sedan, har under denna tid kolossala steg tagits i mjukvaruprodukter och dessa produkter kommer att användas i stor utsträckning under lång tid. Området datorrelaterad kunskap har genomgått en explosion, liksom motsvarande teknik. Om vi ​​inte tar hänsyn till den kommersiella sidan kan vi säga att det inte finns några främlingar inom detta område av yrkesverksamhet. Många människor utvecklar program inte för vinst eller inkomst, utan av egen fri vilja, av passion. Detta ska givetvis inte påverka kvaliteten på programmet, och i den här branschen finns det så att säga konkurrens och efterfrågan på kvalitetsutförande, stabilt arbete och att uppfylla alla moderna krav. Här är det också värt att notera utseendet på mikroprocessorer på 60-talet, som kom att ersätta ett stort antal lampuppsättningar. Det finns vissa typer av mikroprocessorer som skiljer sig mycket från varandra. Dessa mikroprocessorer skiljer sig från varandra i deras bitdjup och inbyggda systemkommandon. De vanligaste är: Intel, IBM, Celeron, AMD, etc. Alla dessa processorer är relaterade till den avancerade arkitekturen hos Intel-processorer. Spridningen av mikrodatorer orsakade en omprövning av attityder till assemblerspråk av två huvudsakliga skäl. För det första kräver program skrivna i assemblerspråk betydligt mindre minne och körningstid. För det andra ger kunskap om assemblerspråk och den resulterande maskinkoden en förståelse för maskinens arkitektur, vilket är osannolikt att tillhandahållas när man arbetar på ett språk på hög nivå. Även om de flesta mjukvaruproffs utvecklar på högnivåspråk som Pascal, C eller Delphi, vilket är lättare när man skriver program, är den mest kraftfulla och effektiva programvara skrivs helt eller delvis på assemblerspråk. Språk på hög nivå har utformats för att undvika speciella tekniska funktioner specifika datorer. Och assemblerspråk är i sin tur designat för processorns specifika detaljer. För att kunna skriva ett assemblerprogram för en specifik dator måste du därför känna till dess arkitektur. Dessa dagar, utsikten över de viktigaste mjukvaruproduktär en EXE-fil. Med tanke på positiva sidor Detta innebär att författaren till programmet kan vara säker på dess integritet. Men ofta är detta långt ifrån fallet. Det finns även en demonteringsmaskin. Med hjälp av en disassembler kan du ta reda på avbrott och programkoder. Det kommer inte att vara svårt för en person som är väl insatt i assembler att göra om hela programmet efter sin smak. Det är kanske här det mest olösliga problemet uppstår - viruset. Varför skriver folk ett virus? Vissa ställer den här frågan med förvåning, andra med ilska, men ändå finns det fortfarande människor som är intresserade av denna uppgift, inte ur synvinkeln att orsaka skada, utan som ett intresse för systemprogrammering. Virus skrivs av olika anledningar. Vissa människor gillar systemanrop, andra förbättrar sina kunskaper om assembler. Jag ska försöka förklara allt detta i min kursarbete. Den säger också inte bara om strukturen för EXE-filen utan också om assemblerspråket.

^ Församlingsspråk.

Det är intressant att följa, från tiden för de första datorernas uppkomst till idag, omvandlingen av programmerares idéer om assemblerspråk.

En gång i tiden var montering ett språk utan vilket man inte kunde få en dator att göra något användbart. Gradvis förändrades situationen. Mer bekväma sätt att kommunicera med en dator dök upp. Men, till skillnad från andra språk, dog inte assembler, dessutom kunde den inte göra detta i princip. Varför? På jakt efter ett svar, låt oss försöka förstå vad assemblerspråk är i allmänhet.

Kort sagt, assemblerspråk är en symbolisk representation av maskinspråk. Alla processer i en maskin på den lägsta hårdvarunivån drivs endast av maskinspråkkommandon (instruktioner). Av detta framgår att, trots det vanliga namnet, är assemblerspråket olika för varje typ av dator. Detta gäller också utseende program skrivna på assemblerspråk och idéer som detta språk är en återspegling av.

Det är omöjligt att verkligen lösa problem relaterade till hårdvara (eller till och med, dessutom beroende av hårdvara, som att öka hastigheten på ett program), utan kunskap om assembler.

En programmerare eller vilken annan användare som helst kan använda alla verktyg på hög nivå, till och med program för att konstruera virtuella världar, och kanske inte ens misstänka att datorn faktiskt inte utför kommandona för det språk som dess program är skrivet på, utan deras transformerade representation i form av tråkiga och tråkiga sekvenser av kommandon från ett helt annat språk - maskinspråk. Låt oss nu föreställa oss att en sådan användare har ett icke-standardproblem eller att något helt enkelt inte fungerar. Till exempel måste hans program fungera med någon ovanlig enhet eller utföra andra åtgärder som kräver kunskap om datorhårdvarans driftsprinciper. Oavsett hur smart programmeraren är, hur bra språk han än skrev sitt underbara program på, kan han inte klara sig utan kunskap om assembler. Och det är ingen slump att nästan alla språkkompilatorer på hög nivå innehåller sätt att koppla ihop sina moduler med assemblermoduler eller stödja åtkomst till assemblernivån för programmering.

Datageneralisternas tid är förstås redan förbi. Som de säger, du kan inte omfamna det oerhörda. Men det finns något gemensamt, en sorts grund som varje seriös datautbildning bygger på. Detta är kunskap om principerna för datordrift, dess arkitektur och assemblerspråk som en reflektion och förkroppsligande av denna kunskap.

En typisk modern dator (i486- eller Pentium-baserad) består av följande komponenter (Figur 1).

Ris. 1. Dator och kringutrustning

Ris. 2. Blockschema över en persondator

Av figuren (Figur 1) kan man se att datorn är uppbyggd av flera fysiska enheter som var och en är kopplad till en enhet, kallad systemenheten. Om vi ​​tänker logiskt är det tydligt att det spelar rollen som någon form av koordinerande enhet. Låt oss ta en titt inuti systemenhet(du behöver inte försöka komma in i monitorn - det finns inget intressant där, och dessutom är det farligt): öppna höljet och se några brädor, block, anslutningskablar. För att förstå deras funktionella syfte, låt oss titta på blockschemat för en typisk dator (Fig. 2). Den gör inte anspråk på absolut noggrannhet och är endast avsedd att visa syftet, sammankopplingen och den typiska sammansättningen av elementen i en modern persondator.

Låt oss diskutera diagrammet i fig. 2 i en något okonventionell stil.
Det är vanligt att en person, när man möter något nytt, letar efter några associationer som kan hjälpa honom att förstå det okända. Vilka associationer väcker datorn? Jag associerar till exempel ofta en dator med personen själv. Varför?

När en person skapade en dator, någonstans djupt inne i sig själv trodde han att han skapade något som liknade honom själv. Datorn har organ för att ta emot information från omvärlden - ett tangentbord, en mus och magnetiska diskenheter. I fig. 2 är dessa organ placerade till höger om systembussarna. Datorn har organ som "smälter" den mottagna informationen - de är CPU Och Bagge. Och slutligen har datorn talorgan som producerar resultatet av bearbetningen. Det här är också några av enheterna till höger.

Moderna datorer, naturligtvis, är långt ifrån mänsklig. De kan jämföras med varelser som interagerar med omvärlden på nivån av en stor men begränsad uppsättning ovillkorliga reflexer.
Denna uppsättning reflexer bildar ett system av maskinkommandon. Oavsett hur hög nivå du kommunicerar med en dator, handlar det i slutändan om en tråkig och monoton sekvens av maskinkommandon.
Varje maskinkommando är ett slags stimulans för att excitera en eller annan obetingad reflex. Reaktionen på denna stimulans är alltid entydig och "hardwired" i mikrokommandoblocket i form av ett mikroprogram. Detta mikroprogram implementerar åtgärder för att implementera ett maskinkommando, men på nivån för signaler som levereras till vissa logik dator, och styr därigenom olika delsystem i datorn. Detta är den så kallade principen för mikroprogramstyrning.

För att fortsätta analogin med en person, noterar vi: för att en dator ska äta ordentligt har många operativsystem, kompilatorer för hundratals programmeringsspråk, etc. uppfunnits. Men alla är i själva verket bara en tallrik som mat (program) levereras enligt vissa regler mage (dator). Endast datorns mage älskar kost, monoton mat - ge den strukturerad information, i form av strikt organiserade sekvenser av nollor och ettor, vars kombinationer utgör maskinspråk.

Således, även om den utåt är en polyglot, förstår datorn bara ett språk - språket för maskininstruktioner. Naturligtvis, för att kommunicera och arbeta med en dator, är det inte nödvändigt att kunna det här språket, men nästan alla professionella programmerare ställs förr eller senare inför behovet av att studera det. Lyckligtvis behöver programmeraren inte försöka förstå innebörden av olika kombinationer av binära tal, eftersom programmerare på 50-talet började använda en symbolisk analog av maskinspråk för programmering, som kallades assemblerspråk. Detta språk återspeglar exakt alla funktioner i maskinspråket. Det är därför, till skillnad från högnivåspråk, assemblerspråk är olika för varje typ av dator.

Av allt ovanstående kan vi dra slutsatsen att eftersom assemblerspråk är "inhemskt" för en dator, kan det mest effektiva programmet bara skrivas i det (förutsatt att det är skrivet av en kvalificerad programmerare). Det finns ett litet "men" här: det här är en mycket arbetsintensiv process som kräver mycket uppmärksamhet och praktisk erfarenhet. Därför skriver de i verkligheten främst program i assembler som ska ge effektivt arbete med hårdvara. Ibland skrivs programavsnitt som är kritiska vad gäller körtid eller minnesförbrukning i assembler. Därefter formaliseras de i form av subrutiner och kombineras med kod på ett högnivåspråk.

Det är vettigt att börja lära sig assemblerspråket för vilken dator som helst efter att ha tagit reda på vilken del av datorn som är synlig och tillgänglig för programmering på detta språk. Detta är den så kallade datorprogrammodellen, varav en del är mikroprocessorprogrammodellen, som innehåller 32 register, i en eller annan grad, tillgängliga för programmeraren.

Dessa register kan delas in i två stora grupper:

^ 16 användarregister;

16 systemregister.

Assembly språkprogram använder register mycket intensivt. De flesta register har ett specifikt funktionssyfte.

Som namnet antyder kallas användarregister för användarregister eftersom programmeraren kan använda dem när han skriver sina program. Dessa register inkluderar (Fig. 3):

Åtta 32-bitars register som kan användas av programmerare för att lagra data och adresser (även kallade allmänna register (GPR)):

sex segmentregister: cs, ds, ss, es, fs, gs;

status- och kontrollregister:

Flaggor register eflags/flaggor;

Kommandopekarregister eip/ip.

Ris. 3. Användarregister för mikroprocessorer i486 och Pentium

Varför visas många av dessa register med snedstreck? Nej, det här är inte olika register - de är delar av ett stort 32-bitars register. De kan användas i programmet som separata objekt. Detta gjordes för att säkerställa funktionaliteten hos program skrivna för yngre 16-bitars modeller av Intel-mikroprocessorer, med början i i8086. Mikroprocessorerna i486 och Pentium har mestadels 32-bitars register. Deras antal, med undantag för segmentregister, är detsamma som i8086, men dimensionen är större, vilket återspeglas i deras beteckningar - de har
prefix e (Utökad).

^ Register för allmänna ändamål
Alla register i denna grupp ger dig tillgång till deras "nedre" delar (se fig. 3). Om du tittar på denna figur, notera att endast de nedre 16- och 8-bitarsdelarna av dessa register kan användas för självadressering. De övre 16 bitarna i dessa register är inte tillgängliga som oberoende objekt. Detta gjordes, som vi noterade ovan, för kompatibilitet med yngre 16-bitars modeller av Intel-mikroprocessorer.

Låt oss lista de register som hör till gruppen allmänna register. Eftersom dessa register är fysiskt placerade i mikroprocessorn inuti en aritmetisk logisk enhet (ALU), kallas de också för ALU-register:

eax/ax/ah/al (Ackumulatorregister) - batteri.
Används för att lagra mellanliggande data. Vissa kommandon kräver användning av detta register;

ebx/bx/bh/bl (Basregister) - basregister.
Används för att lagra basadressen för något objekt i minnet;

ecx/cx/ch/cl (Räkneregister) - räknareregister.
Används i team som utför vissa repetitiva åtgärder. Dess användning är ofta implicit och dold i algoritmen för motsvarande kommando.
Till exempel, kommandot för att organisera en slinga, förutom att överföra kontroll till ett kommando som finns på en viss adress, analyserar och minskar värdet på ecx/cx-registret med ett;

edx/dx/dh/dl (Dataregister) - dataregister.
Precis som eax/ax/ah/al-registret lagrar det mellanliggande data. I vissa kommandon är dess användning obligatorisk; För vissa kommandon sker detta implicit.

Följande två register används för att stödja så kallade kedjeoperationer, det vill säga operationer som sekventiellt bearbetar kedjor av element, som var och en kan vara 32, 16 eller 8 bitar långa:

esi/si (Källindexregister) - källindex.
Detta register i kedjade operationer innehåller den aktuella adressen för elementet i källkedjan;

edi/di (Destination Index register) - index för mottagaren (mottagaren).
Detta register i kedjade operationer innehåller den aktuella adressen i destinationskedjan.

I mikroprocessorarkitekturen stöds en datastruktur som en stack på hård- och mjukvarunivå. För att arbeta med stacken finns det speciella kommandon i mioch i programmodell Mikroprocessorn har speciella register för detta:

esp/sp (Stack Pointer register) - stack pointer register.
Innehåller en pekare till toppen av stapeln i det aktuella stapelsegmentet.

ebp/bp (Base Pointer register) - stapelrams baspekareregister.
Designad för att organisera slumpmässig tillgång till data inuti stacken.

En stack är ett programområde för tillfällig lagring av godtyckliga data. Naturligtvis kan data också lagras i ett datasegment, men i detta fall måste för varje tillfälligt lagrad data skapas en separat namngiven minnescell, vilket ökar programmets storlek och antalet namn som används. Bekvämligheten med stacken ligger i det faktum att dess område är återanvändbart, och att lagra data på stacken och hämta den därifrån görs med de effektiva push- och pop-kommandona utan att ange några namn.
Stacken används traditionellt, till exempel för att spara innehållet i register som används av ett program innan en subrutin anropas, som i sin tur kommer att använda processorregistren "för sina egna syften". Det ursprungliga innehållet i registren tas bort från stacken efter att subrutinen återvänder. En annan vanlig teknik är att skicka de parametrar som krävs till en subrutin via stacken. Subrutinen, som vet i vilken ordning parametrarna är placerade på stacken, kan ta dem därifrån och använda dem under dess exekvering. Utmärkande drag Stacken är en unik ordning i vilken data som finns i den hämtas: vid varje given tidpunkt är endast det översta elementet tillgängligt på stacken, d.v.s. elementet senast tryckt på stapeln. Genom att skjuta upp det översta elementet från stapeln blir nästa element tillgängligt. Stackelement är belägna i minnesområdet som är tilldelat för stacken, med början från botten av stacken (dvs från dess maximala adress) vid sekventiellt minskande adresser. Adressen för det översta, tillgängliga elementet lagras i stackpekarregistret SP. Som alla andra delar av programminnet måste stacken vara en del av något segment eller bilda ett separat segment. I båda fallen placeras segmentadressen för detta segment i segmentstackregistret SS. Sålunda beskriver registerparet SS:SP adressen för en tillgänglig stackcell: SS lagrar segmentadressen för stacken och SP lagrar förskjutningen av den senast lagrade datan i stacken (fig. 4, a). Observera att i utgångsläget pekar stackpekaren SP på en cell som ligger under stapelns botten och som inte ingår i den.

Fig 4. Stackorganisation: a - initialt tillstånd, b - efter laddning av ett element (i detta exempel, innehållet i AX-registret), c - efter laddning av det andra elementet (innehållet i DS-registret), d - efter urladdning av ett element, e - efter att ha lossat två element och återgått till deras ursprungliga tillstånd.

Lastning i stapeln utförs av ett speciellt kommando för att arbeta med stapeln (push). Denna instruktion minskar först innehållet i stackpekaren med 2 och placerar sedan operanden på adressen i SP. Om vi ​​till exempel vill lagra innehållet i AX-registret på stacken, bör vi köra kommandot

Stacken går in i det tillstånd som visas i fig. 1,10, b. Det kan ses att stackpekaren flyttas upp två byte (mot lägre adresser) och operanden som anges i push-kommandot skrivs till denna adress. Följande stack loading kommando är t.ex.

kommer att sätta stacken i det tillstånd som visas i fig. 1,10, c. Stacken kommer nu att lagra två element, och endast det översta, som pekas på av stackpekaren SP, kommer att vara tillgängligt. Om vi ​​efter en tid behöver återställa det ursprungliga innehållet i registren som är lagrade på stacken, måste vi utföra pop (push)-kommandon för att ladda ner från stacken:

pop DS
pop AX

Hur stor ska stapeln vara? Det beror på hur intensivt det används i programmet. Om du till exempel planerar att lagra en array på 10 000 byte i stacken, måste stacken vara minst denna storlek. Man bör komma ihåg att i vissa fall används stacken automatiskt av systemet, i synnerhet när man kör int 21h interrupt-kommandot. Med detta kommando trycker processorn först returadressen till stacken och sedan skickar DOS innehållet i registren och annan information relaterad till det avbrutna programmet till stacken. Därför, även om ett program inte använder en stack alls, måste den fortfarande finnas i programmet och vara minst flera dussin ord i storlek. I vårt första exempel tilldelade vi 128 ord till stacken, vilket säkert räcker.

^ Struktur för ett assemblerprogram

Ett assemblerspråksprogram är en samling minnesblock som kallas minnessegment. Ett program kan bestå av ett eller flera sådana blocksegment. Varje segment innehåller en samling språkmeningar, som var och en upptar en separat rad med programkod.

Det finns fyra typer av assembler-påståenden:

kommandon eller instruktioner som är symboliska analoger till maskinkommandon. Under översättningsprocessen omvandlas assemblerinstruktioner till motsvarande kommandon för mikroprocessorinstruktionsuppsättningen;

makrokommandon - meningar av programtext formaterad på ett visst sätt, ersatta under sändning med andra meningar;

direktiv, som är instruktioner till assembleröversättaren att utföra vissa åtgärder. Direktiven har inga motsvarigheter i maskinrepresentation;

kommentarsrader som innehåller alla tecken, inklusive bokstäver i det ryska alfabetet. Kommentarer ignoreras av översättaren.

^ Sammansättningssyntax

De meningar som utgör ett program kan vara en syntaktisk konstruktion som motsvarar ett kommando, makro, direktiv eller kommentar. För att assembleröversättaren ska känna igen dem måste de vara utformade enligt vissa syntaktiska regler. För att göra detta är det bäst att använda en formell beskrivning av språkets syntax, som grammatikens regler. De vanligaste sätten att beskriva ett programmeringsspråk på detta sätt är syntaxdiagram och utökade Backus-Naur-former. För praktisk användning är syntaxdiagram mer bekväma. Till exempel kan syntaxen för assemblerspråkssatser beskrivas med hjälp av syntaxdiagrammen som visas i följande figurer.

Ris. 5. Monteringssatsformat

Ris. 6. Direktivformat

Ris. 7. Format för kommandon och makron

På dessa bilder:

etikettnamn - en identifierare vars värde är adressen till den första byten i meningen i källkoden för programmet som den anger;

namn - en identifierare som skiljer detta direktiv från andra direktiv med samma namn. Som ett resultat av montörens bearbetning av ett visst direktiv kan vissa egenskaper tilldelas det namnet;

en operationskod (OPC) och ett direktiv är mnemoniska symboler för motsvarande maskininstruktion, makroinstruktion eller översättardirektiv;

operander är delar av ett kommando-, makro- eller assemblerdirektiv som anger de objekt på vilka åtgärder utförs. Assembly språkoperander beskrivs av uttryck med numeriska och textkonstanter, etiketter och variabelidentifierare med operatortecken och några reserverade ord.

^ Hur använder man syntaxdiagram? Det är väldigt enkelt: allt du behöver göra är att hitta och sedan följa vägen från diagrammets ingång (till vänster) till dess utgång (till höger). Om en sådan väg finns är meningen eller konstruktionen syntaktisk korrekt. Om det inte finns någon sådan väg kommer kompilatorn inte att acceptera denna konstruktion. När du arbetar med syntaxdiagram, var uppmärksam på riktningen för korsningen som anges av pilarna, eftersom det bland banorna kan finnas några som kan följas från höger till vänster. I grund och botten återspeglar syntaxdiagram logiken i översättarens operation vid analys av inmatningsmeningarna i programmet.

Godkända tecken när du skriver programtext är:

Alla latinska bokstäver: A-Z, a-z. I det här fallet anses stora och små bokstäver vara likvärdiga;

Siffror från 0 till 9;

Tecken ?, @, $, _, &;

Separatorer, . ()< > { } + / * % ! " " ? \ = # ^.

Sammansättningsspråkssatser bildas av lexem, som är syntaktiskt oskiljaktiga sekvenser av giltiga språksymboler som är meningsfulla för översättaren.

Lexem är:

identifierare är sekvenser av giltiga tecken som används för att beteckna programobjekt såsom operationskoder, variabelnamn och etikettnamn. Regeln för att skriva identifierare är följande: en identifierare kan bestå av ett eller flera tecken. Som symboler kan du använda bokstäver i det latinska alfabetet, siffror och några specialtecken - _, ?, $, @. En identifierare kan inte börja med ett siffror. Längden på identifieraren kan vara upp till 255 tecken, även om översättaren bara accepterar de första 32 och ignorerar resten. Du kan justera längden på möjliga identifierare med alternativet kommandorad mv. Dessutom är det möjligt att instruera översättaren att skilja mellan stora och små bokstäver eller att ignorera deras skillnad (vilket görs som standard).

^Assembler-kommandon.

Assembler-kommandon avslöjar möjligheten att överföra dina krav till datorn, en mekanism för att överföra kontroll i ett program (cykler och övergångar) för logiska jämförelser och programorganisation. Men programmerbara uppgifter är sällan så enkla. De flesta program innehåller en serie loopar där flera kommandon upprepas tills ett visst krav uppnås, och olika kontroller som avgör vilken av flera åtgärder som ska utföras. Vissa instruktioner kan överföra kontroll genom att ändra den normala sekvensen av steg genom att direkt modifiera offsetvärdet i instruktionspekaren. Som nämnts tidigare finns det olika kommandon för olika processorer, men vi kommer att titta på ett antal några kommandon för 80186, 80286 och 80386 processorer.

För att beskriva flaggornas tillstånd efter att ha utfört ett visst kommando, kommer vi att använda ett urval från en tabell som återspeglar strukturen för eflags flaggregister:

Den nedre raden i denna tabell visar värdena för flaggorna efter att kommandot har utförts. Följande beteckningar används:

1 - efter att kommandot har utförts sätts flaggan (lika med 1);

0 - efter att kommandot har utförts återställs flaggan (lika med 0);

r - flaggans värde beror på resultatet av kommandot;

Efter att kommandot har utförts är flaggan inte definierad;

mellanslag - efter att kommandot har utförts ändras inte flaggan;

Följande notation används för att representera operander i syntaxdiagram:

r8, r16, r32 - en operand i ett av registren för bytestorlek, ord eller dubbelord;

m8, m16, m32, m48 - minnesoperandstorlek byte, ord, dubbelord eller 48 bitar;

i8, i16, i32 - omedelbar operandstorlek byte, ord eller dubbelord;

a8, a16, a32 - relativ adress (offset) i kodsegmentet.

Kommandon (i alfabetisk ordning):

*Dessa kommandon beskrivs i detalj.

LÄGG TILL
(Tillägg)

Tillägg

^ Kommandodiagram:

lägg till destination, källa

Syfte: tillägg av två käll- och måloperander av storlek byte, ord eller dubbelord.

Arbetsalgoritm:

lägg till käll- och destinationsoperander;

skriv tilläggsresultatet till mottagaren;

sätta flaggor.

Tillstånd för flaggor efter kommandoexekvering:

Ansökan:
Kommandot add används för att lägga till två heltalsoperander. Resultatet av tillägget placeras på adressen till den första operanden. Om resultatet av tillägget går utanför gränserna för mottagaroperanden (ett spill inträffar), bör denna situation beaktas genom att analysera cf-flaggan och den efterföljande möjliga användningen av adc-kommandot. Låt oss till exempel lägga till värdena i axregistret och ch-minnesområdet. När du lägger till, ta hänsyn till möjligheten för översvämning.

Registrera plus register eller minne:

|000000dw|modregr/rm|

AX-register (AL) plus omedelbart värde:

|0000010w|--data--|data om w=1|

Register eller minne plus omedelbart värde:

|100000sw|mod000r/m|--data--|data om BW=01|

RING UPP
(RING UPP)

Anropa en procedur eller uppgift

^ Kommandodiagram:

Syfte:

överföring av kontroll till en nära eller fjärran procedur med lagring av adressen för returpunkten på stapeln;

byta uppgifter.

Arbetsalgoritm:
bestäms av operandtypen:

Nära etikett - innehållet i eip/ip-kommandopekaren skjuts in i stacken och det nya adressvärdet som motsvarar etiketten laddas in i samma register;

Far-etikett - innehållet i eip/ip och cs-kommandopekaren skjuts in i stacken. Sedan laddas nya adressvärden som motsvarar den bortre etiketten in i samma register;

R16, 32 eller m16, 32 - definiera ett register eller minnescell som innehåller förskjutningar i det aktuella instruktionssegmentet till vilket styrningen överförs. När kontrollen överförs, skjuts innehållet i eip/ip-kommandopekaren till stacken;

Minnespekare - definierar en minnesplats som innehåller en 4 eller 6 byte pekare till den anropade proceduren. Strukturen för en sådan pekare är 2+2 eller 2+4 byte. Tolkningen av en sådan pekare beror på mikroprocessorns driftläge:

^ Tillstånd för flaggor efter kommandoexekvering (förutom uppgiftsbyte):

att köra kommandot påverkar inte flaggorna

När en uppgift byts ändras flaggvärdena enligt information om eflagsregistret i TSS-statussegmentet för uppgiften som byts till.
Ansökan:
Anropskommandot låter dig organisera en flexibel och multivariant överföring av kontroll till en subrutin samtidigt som adressen till returpunkten bevaras.

Objektkod (fyra format):

Direktadressering i ett segment:

|11101000|disp-låg|djup-hög|

Indirekt adressering i ett segment:

|11111111|mod010r/m|

Indirekt adressering mellan segment:

|11111111|mod011r/m|

Direkt adressering mellan segment:

|10011010|offset-låg|offset-hög|seg-låg|seg-hög|

CMP
(Jämför operander)

Operand jämförelse

^ Kommandodiagram:

cmp operand1,operand2

Syfte: jämförelse av två operander.

Arbetsalgoritm:

utför subtraktion(operand1-operand2);

beroende på resultatet, ställ in flaggorna, ändra inte operand1 och operand2 (det vill säga kommer inte ihåg resultatet).

Ansökan:
Detta kommando används för att jämföra två operander genom subtraktion utan att ändra operanderna. Baserat på resultatet av kommandot sätts flaggor. Kommandot cmp används med de villkorliga hoppkommandona och kommandot set byte byte setcc.

Objektkod (tre format):

Register eller minne med register:

|001110dw|modregr/m|

Omedelbart värde med AX (AL) register:

|0011110w|--data--|data om w=1|

Omedelbart värde med register eller minne:

|100000sw|mod111r/m|--data--|data if sw=0|

DEC
(Dekrementera operand med 1)

Minska en operand med en

^ Kommandodiagram:

dec operand

Syfte: Minska värdet på en operand i minnet eller registret med 1.

Arbetsalgoritm:
kommandot subtraherar 1 från operanden. Tillstånd för flaggor efter kommandoexekvering:

Ansökan:
Dec-instruktionen används för att minska värdet på en byte, ord, dubbelord i minnet eller register med ett. Observera dock att kommandot inte påverkar cf-flaggan.

Registrera: |01001reg|

^ Register eller minne: |1111111w|mod001r/m|

DIV
(DIVide osignerad)

Osignerad division

Lagöversikt:

div avdelare

Syfte: Utför en divisionsoperation mellan två binära värden utan tecken.

^ Driftsalgoritm:
Kommandot kräver två operander - utdelningen och divisorn. Utdelningen anges implicit och dess storlek beror på storleken på divisorn, som anges i kommandot:

om divisorn är en byte stor måste utdelningen finnas i yxregistret. Efter operationen placeras kvoten i al och resten i ah;

om divisor är ett ord i storlek, så måste utdelningen placeras i registerparet dx:ax, med den låga delen av utdelningen placerad i ax. Efter operationen placeras kvoten i ax och resten i dx;

om divisor är ett dubbelord i storlek, så måste utdelningen placeras i registerparet edx:eax, med den låga delen av utdelningen placerad i eax. Efter operationen placeras kvoten i eax och resten i edx.

^ Tillstånd för flaggor efter kommandoexekvering:

Ansökan:
Kommandot utför en heltalsdelning av operanderna, vilket ger resultatet av divisionen som kvoten och resten av divisionen. När du utför en divisionsoperation kan ett undantag inträffa: 0 - divisionsfel. Denna situation uppstår i ett av två fall: divisorn är 0 eller kvoten är för stor för att passa in i eax/ax/al-registret.

Objektkod:

|1111011w|mod110r/m|

INT
(Avbryta)

Anropar avbrottsservicerutinen

^ Kommandodiagram:

int interrupt_number

Syfte: anropa avbrottsservicerutinen med det avbrottsnummer som anges av kommandooperanden.

^ Driftsalgoritm:

tryck på flaggregistret eflags/flaggor och returadressen till stacken. Vid skrivning av en returadress skrivs först innehållet i segmentregistret cs, sedan innehållet i kommandopekaren eip/ip;

återställ if och tf flaggorna till noll;

överföra kontrollen till avbrottstjänstprogrammet med angivet nummer. Styröverföringsmekanismen beror på mikroprocessorns driftläge.

^ Tillstånd för flaggor efter kommandoexekvering:

Ansökan:
Som du kan se från syntaxen finns det två former av detta kommando:

int 3 - har sin egen individuella operationskod 0cch och upptar en byte. Denna omständighet gör det mycket bekvämt för användning i olika programvarufelsökningar att ställa in brytpunkter genom att ersätta den första byten i ett kommando. Mikroprocessorn, som möter ett kommando med operationskoden 0cch i sekvensen av kommandon, anropar avbrottsbehandlingsprogrammet med vektornummer 3, som tjänar till att kommunicera med mjukvarufelsökaren.

Den andra formen av kommandot upptar två byte, har en opkod på 0cdh och låter dig initiera ett anrop till en avbrottstjänstrutin med ett vektornummer i intervallet 0–255. Funktioner för kontrollöverföring, som nämnts, beror på mikroprocessorns driftläge.

Objektkod (två format):

Registrera: |01000reg|

^ Register eller minne: |1111111w|mod000r/m|

J.C.C.
JCXZ/JECXZ
(Hoppa om skick)

(Hoppa om CX=Noll/ Hoppa om ECX=Noll)

Hoppa om villkoret är uppfyllt

Hoppa om CX/ECX är noll

^ Kommandodiagram:

jcc etikett
jcxz etikett
jecxz etikett

Syfte: övergång inom det aktuella kommandosegmentet beroende på något tillstånd.

^ Kommandoalgoritm (förutom jcxz/jecxz):
Kontrollera flaggornas tillstånd beroende på op-koden (den återspeglar tillståndet som kontrolleras):

om villkoret som testas är sant, gå sedan till cellen som indikeras av operanden;

om villkoret som kontrolleras är falskt, överför sedan kontrollen till nästa kommando.

Algoritm för kommandot jcxz/jecxz:
Kontrollera villkoret att innehållet i ecx/cx-registret är lika med noll:

om tillståndet kontrolleras

Programmering på maskininstruktionsnivå är den lägsta nivån på vilken program kan skrivas. Systemet med maskininstruktioner måste vara tillräckligt för att genomföra de nödvändiga åtgärderna genom att utfärda instruktioner till datorhårdvaran.

Varje maskinkommando består av två delar:

  • operativt - bestämma "vad man ska göra";
  • operand - definierar bearbetningsobjekt, "vad man ska göra med."

Kommandot för mikroprocessormaskin, skrivet i assemblerspråk, är en rad med följande syntaktiska form:

kommando/direktiv etikett operand(er) ;kommentarer

I det här fallet är det obligatoriska fältet på raden ett kommando eller direktiv.

Etiketten, kommandot/direktivet och operander (om några) är åtskilda av minst ett mellanslag eller tabbtecken.

Om ett kommando eller direktiv behöver fortsätta på nästa rad, används ett omvänt snedstreck: \.

Som standard skiljer inte assemblerspråk mellan stora och små bokstäver när du skriver kommandon eller direktiv.

Exempel på kodrader:

Räkna db 1 ;Namn, direktiv, en operand
mov eax,0 ;Kommando, två operander
cbw ; Team

Taggar

Märka i assemblerspråk kan innehålla följande symboler:

  • alla bokstäver i det latinska alfabetet;
  • siffror från 0 till 9;
  • specialtecken: _, @, $, ?.

En punkt kan användas som det första tecknet i en etikett, men vissa kompilatorer rekommenderar inte att du använder detta tecken. Reserverade assemblernamn (direktiv, operatorer, kommandonamn) kan inte användas som etiketter.

Det första tecknet i etiketten måste vara en bokstav eller specialtecken (men inte en siffra). Maximal längd taggar – 31 tecken. Alla etiketter som är skrivna på en rad som inte innehåller ett assemblerdirektiv måste sluta med ett kolon: .

Lag

Team talar om för översättaren vilken åtgärd mikroprocessorn ska utföra. I ett datasegment definierar ett kommando (eller direktiv) ett fält, en arbetsyta eller en konstant. I ett kodsegment specificerar ett kommando en åtgärd, som att flytta (mov) eller lägga till (lägg till).

direktiv

Montören har ett antal operatörer som låter dig styra processen för montering och listning. Dessa operatörer kallas direktiv . De agerar bara under processen att montera programmet och, till skillnad från kommandon, genererar inte maskinkod.

Operander

Operand – ett objekt på vilket ett maskinkommando eller programmeringsspråkssats exekveras.
En instruktion kan ha en eller två operander, eller inga operander alls. Antalet operander anges implicit av instruktionskoden.
Exempel:

  • Inga operander ret ;Retur
  • En operand inc ecx ;Öka ecx
  • Två operander lägger till eax,12 ;Lägg till 12 till eax

Etiketten, kommandot (direktivet) och operanden behöver inte starta på någon speciell position på raden. Det rekommenderas dock att skriva dem i en kolumn för att göra programmet lättare att läsa.

Operanderna kan vara

  • identifierare;
  • teckensträngar omslutna av enkla eller dubbla citattecken;
  • heltal i binära, oktala, decimala eller hexadecimala talsystem.
Identifierare

Identifierare – sekvenser av giltiga tecken som används för att beteckna programobjekt såsom operationskoder, variabelnamn och etikettnamn.

Regler för registrering av identifierare.

  • Identifieraren kan bestå av ett eller flera tecken.
  • Som symboler kan du använda bokstäver i det latinska alfabetet, siffror och några specialtecken: _, ?, $, @.
  • En identifierare kan inte börja med ett siffror.
  • Längden på identifieraren kan vara upp till 255 tecken.
  • Översättaren accepterar de första 32 tecknen i identifieraren och ignorerar resten.
Kommentarer

Kommentarer separeras från den körbara raden med ett tecken; . I det här fallet är allt som skrivs efter semikolon och fram till slutet av raden en kommentar. Att använda kommentarer i ett program förbättrar dess tydlighet, särskilt när syftet med en uppsättning kommandon är oklart. Kommentaren kan innehålla alla utskrivbara tecken, inklusive mellanslag. En kommentar kan sträcka sig över hela raden eller följa ett kommando på samma rad.

Monteringsprogrammets struktur

Ett program skrivet på assemblerspråk kan bestå av flera delar som kallas moduler . Varje modul kan ha ett eller flera data-, stack- och kodsegment definierade. Alla kompletta assemblerprogram måste innehålla en huvud- eller huvudmodul från vilken körningen börjar. En modul kan innehålla kodsegment, datasegment och stacksegment, deklarerade med hjälp av lämpliga direktiv. Innan du deklarerar segment måste du ange minnesmodellen med .MODEL-direktivet.

Ett exempel på ett "gör ingenting"-program i assemblerspråk:

686P
.MODEL FLAT, STDCALL
.DATA
.KODA
START:

RÖTA
SLUT START

Detta program innehåller endast ett mikroprocessorkommando. Detta kommando är RET. Det säkerställer att programmet avslutas korrekt. I allmänhet används detta kommando för att avsluta en procedur.
Resten av programmet gäller driften av översättaren.
.686P - Kommandon i skyddat läge Pentium 6 (Pentium II) är tillåtna. Detta direktiv väljer den uppsättning assemblerinstruktioner som stöds, som anger processormodellen. Bokstaven P som anges i slutet av direktivet informerar översättaren om att processorn arbetar i skyddat läge.
.MODEL FLAT, stdcall - platt minnesmodell. Denna minnesmodell används i Windows operativsystem. stdcall
.DATA är ett programsegment som innehåller data.
.CODE är ett programblock som innehåller kod.
START - etikett. I assembler spelar taggar en stor roll, vilket inte kan sägas om moderna högnivåspråk.
END START - slutet av programmet och ett meddelande till översättaren att programexekveringen ska börja med START-etiketten.
Varje modul måste innehålla ett END-direktiv för att markera slutet källkod program. Alla rader som följer END-direktivet ignoreras. Om du utelämnar END-direktivet genereras ett fel.
Etiketten som anges efter END-direktivet talar om för översättaren namnet på huvudmodulen från vilken programkörningen börjar. Om programmet innehåller en modul kan etiketten efter END-direktivet utelämnas.

Kommandostruktur i assemblerspråk Programmering på nivå med maskinkommandon är den lägsta nivån på vilken datorprogrammering är möjlig. Maskinens kommandosystem måste vara tillräckligt för att genomföra de nödvändiga åtgärderna genom att utfärda instruktioner till maskinutrustningen. Varje maskininstruktion består av två delar: en operationell, som bestämmer "vad man ska göra" och en operand, som bestämmer bearbetningsobjekten, det vill säga "vad man ska göra". En mikroprocessormaskininstruktion, skriven på Assembly-språk, är en enda rad som har följande form: etikettkommando/direktivoperand(er); kommentarer Etiketten, kommandot/direktivet och operanden är åtskilda av minst ett mellanslag eller tabbtecken. Kommandots operander separeras med kommatecken.

Assembly Language Kommandostruktur Ett assembler-kommando talar om för översättaren vilken åtgärd mikroprocessorn ska utföra. Monteringsdirektiv är parametrar som anges i programtexten som påverkar sammansättningsprocessen eller egenskaperna för utdatafilen. Operaanden anger det initiala värdet för datan (i datasegmentet) eller de element på vilka kommandoåtgärden utförs (i kodsegmentet). En instruktion kan ha en eller två operander, eller inga operander. Antalet operander anges implicit av instruktionskoden. Om ett kommando eller direktiv behöver fortsätta på nästa rad, används ett omvänt snedstreck: "" . Som standard skiljer assembler inte mellan stora och små bokstäver när du skriver kommandon och direktiv. Exempel på direktiv och kommandon Räkna db 1 ; Namn, direktiv, en operand mov eax, 0 ; Kommando, två operander

Identifierare är sekvenser av giltiga tecken som används för att beteckna variabelnamn och etikettnamn. Identifieraren kan bestå av ett eller flera av följande tecken: alla bokstäver i det latinska alfabetet; siffror från 0 till 9; specialtecken: _, @, $, ? . En prick kan användas som det första tecknet på etiketten. Reserverade assemblernamn (direktiv, operatorer, kommandonamn) kan inte användas som identifierare. Det första tecknet i identifieraren måste vara en bokstav eller ett specialtecken. Den maximala längden på en identifierare är 255 tecken, men översättaren accepterar de första 32 och ignorerar resten. Alla etiketter som är skrivna på en rad som inte innehåller ett assemblerdirektiv måste sluta med ett kolon ":". Etiketten, kommandot (direktivet) och operanden behöver inte starta på någon speciell position på raden. Det rekommenderas att skriva dem i en kolumn för bättre läsbarhet av programmet.

Etiketter Alla etiketter som är skrivna på en rad som inte innehåller ett assemblerdirektiv måste sluta med ett kolon ":". Etiketten, kommandot (direktivet) och operanden behöver inte starta på någon speciell position på raden. Det rekommenderas att skriva dem i en kolumn för bättre läsbarhet av programmet.

Kommentarer Att använda kommentarer i ett program förbättrar dess tydlighet, särskilt när syftet med en uppsättning kommandon är oklart. Kommentarer börjar på valfri rad i källmodulen med semikolon (;). Alla tecken till höger om "; " till slutet av raden finns en kommentar. En kommentar kan innehålla alla utskrivbara tecken, inklusive blanksteg. En kommentar kan sträcka sig över hela raden eller följa ett kommando på samma rad.

Assembly Language Programstruktur Ett program skrivet i assemblerspråk kan bestå av flera delar som kallas moduler, som var och en kan definiera en eller flera data-, stack- och kodsegment. Alla kompletta program i assemblerspråk måste innehålla en huvud- eller huvudmodul från vilken körningen börjar. En modul kan innehålla program, data och stacksegment, deklarerade med hjälp av lämpliga direktiv.

Minnesmodeller Innan du deklarerar segment måste du specificera minnesmodellen med hjälp av ett direktiv. MODELL modifierare memory_model, calling_convention, OS_type, stack_parameter Grundläggande minnesmodeller av assemblerspråk: Minnesmodell Kodadressering Dataadressering operativ system Interleaving kod och data LITEN NÄRA MS-DOS Acceptabel LITEN NÄRA MS-DOS, Windows Inget MEDELLÅNGT NÄRA MS-DOS, Windows Inget KOMPAKT NÄRA FAR MS-DOS, Windows Inget STORT LÅNGT MS-DOS, Windows Inget ENORMT LÅNGT MS-DOS, Windows No NEAR Windows 2000, Windows XP, Windows Acceptable FLAT NEAR NT,

Minnesmodeller Den lilla modellen fungerar bara i 16-bitars MS-DOS-applikationer. I denna modell finns all data och kod på ett fysiskt segment. Storleken på programfilen i detta fall överstiger inte 64 KB. Den lilla modellen stöder ett kodsegment och ett datasegment. Data och kod adresseras så nära när denna modell används. Mediummodellen stöder flera kodsegment och ett datasegment, med alla referenser i kodsegment som standard som standard och referenser i ett datasegment anses vara nära. Den kompakta modellen stöder flera datasegment som använder fjärrdataadressering (fjärr), och ett kodsegment som använder nära adressering (nära). Den stora modellen stöder flera kodsegment och flera datasegment. Som standard anses alla referenser till kod och data långt. Den enorma modellen motsvarar nästan den stora minnesmodellen.

Minnesmodeller Den platta modellen antar en osegmenterad programkonfiguration och används endast i 32-bitars operativsystem. Denna modell liknar den lilla modellen genom att data och kod finns i ett enda segment, men den är 32-bitars. Att utveckla ett program för den platta modellen före direktivet. modell lägenhet bör placera en av direktiven: . 386, . 486, . 586 eller. 686. Valet av processorvalsdirektiv avgör uppsättningen av instruktioner som är tillgängliga när du skriver program. Bokstaven p efter processorvalsdirektivet betyder skyddat driftläge. Data- och kodadressering är nära, alla adresser och pekare är 32-bitars.

Minnesmodeller. MODELL modifier memory_model, calling_convention, OS_type, stack_parameter Modifieringsparametern används för att definiera segmenttyper och kan ha följande värden: använd 16 (segment av den valda modellen används som 16-bitars) använd 32 (segment av den valda modellen används som 32-bitars). Parametern calling_convention används för att bestämma metoden för att skicka parametrar när en procedur anropas från andra språk, inklusive högnivåspråk (C++, Pascal). Parametern kan ha följande värden: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Minnesmodeller. MODELL modifierare memory_model, calling_convention, OS_type, stack_parameter OS_type-parametern är OS_DOS som standard, och på det här ögonblicket detta är det enda värdet som stöds för denna parameter. Parametern stack_parameter är satt till: NEARSTACK (SS-registret är lika med DS, data och stackområden är belägna i samma fysiska segment) FARSTACK (SS-registret är inte lika med DS, data och stackareor är placerade i olika fysiska segment). Standardvärdet är NEARSTACK.

Ett exempel på ett program som inte gör någonting. 686 P. MODELL PLAT, STDCALL. DATA. KOD START: RET END START RET - mikroprocessorkommando. Det säkerställer att programmet avslutas korrekt. Resten av programmet gäller driften av översättaren. . 686 P - Kommandon i skyddat läge Pentium 6 (Pentium II) är tillåtna. Detta direktiv väljer den uppsättning assemblerinstruktioner som stöds, som anger processormodellen. . MODELL FLAT, stdcall - platt minnesmodell. Denna minnesmodell används i Windows operativsystem. stdcall - den anropskonvention som används.

Ett exempel på ett program som inte gör någonting. 686 P. MODELL PLAT, STDCALL. DATA. KOD START: RET END START. DATA är ett programsegment som innehåller data. Det här programmet använder inte stacken, så segmentet. STACK saknas. . CODE är ett programsegment som innehåller kod. START - etikett. END START - slutet av programmet och ett meddelande till kompilatorn att programkörning ska börja med START-etiketten. Varje program måste innehålla ett END-direktiv som markerar slutet på programmets källkod. Alla rader som följer END-direktivet ignoreras. Etiketten som anges efter END-direktivet talar om för översättaren namnet på huvudmodulen från vilken programkörningen börjar. Om programmet innehåller en modul kan etiketten efter END-direktivet utelämnas.

Montering språköversättare Översättare - program eller tekniska medel, som konverterar ett program representerat på ett av programmeringsspråken till ett program på målspråket, kallat objektkod. Förutom att stödja maskininstruktionsmnemonics har varje översättare sin egen uppsättning direktiv och makroverktyg, ofta inkompatibla med något annat. Huvudtyperna av assemblerspråköversättare: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - en fritt distribuerad multi-pass assembler skriven av Tomasz Gryshtar (polska), NASM (Netwide Assembler) - en gratis assembler för Intel x-arkitekturen 86, skapades av Simon Tatham med Julian Hall och utvecklas för närvarande av ett litet team av utvecklare på Source. Förfalska. netto.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Översätta ett program i Microsoft Visual Studio 2005 1) Skapa ett projekt genom att välja Arkiv->Ny- >Projektmeny Och"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.!}

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Översätta programmet i Microsoft Visual Studio 2005 2) I projektträdet (Visa->Solution Explorer) Lägg till"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Översätta programmet till Microsoft Visual Studio 2005 3) Välj filtypen Code C++, men ange namnet med filtillägget. asm:

Översätta programmet till Microsoft Visual Studio 2005 5) Ställ in kompilatorparametrar. Högerklicka på menyn Custom Build Rules i projektfilen...

Översätt programmet till Microsoft Visual Studio 2005 och välj Microsoft Macro Assembler i fönstret som visas.

Översättning av programmet i Microsoft Visual Studio 2005 Kontrollera med höger knapp i filen hej. asm projektträd i menyn Egenskaper och installera Allmänt->Verktyg: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Översätta programmet i Microsoft Visual Studio 2005 6) Kompilera filen genom att välja Bygg->Bygg hej. prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Programmering i Windows OS Programmering i Windows OS är baserad på användningen av API-funktioner (Application Program Interface, dvs. programgränssnitt). Deras antal når 2000. Windows-programmet består till stor del av sådana samtal. Alla interaktioner med externa enheter och operativsystemsresurser uppstår, som regel, genom sådana funktioner. Operations rum Windows-system använder en platt minnesmodell. Adressen för valfri minnescell kommer att bestämmas av innehållet i ett 32-bitars register. Det finns 3 typer av programstrukturer för Windows: dialog (huvudfönstret är dialog), konsol eller fönsterlös struktur, klassisk struktur (fönster, ram).

Ring upp Windows funktioner API I hjälpfilen presenteras valfri API-funktion som typen funktionsnamn (FA 1, FA 2, FA 3) Typ – returvärdestyp; FAx – en lista över formella argument i den ordning de visas, till exempel int Message. Box(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Typ); Denna funktion visar ett fönster med ett meddelande och en utgångsknapp (eller -knappar). Betydelse av parametrar: h. Wnd är en beskrivning av fönstret där meddelandefönstret kommer att visas, lp. Text - text som visas i fönstret, lp. Bildtext - text i fönstrets titel, u. Typ - fönstertyp; i synnerhet kan du bestämma antalet utgångsknappar.

Anropar Windows API int Message-funktioner. Box(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Typ); Nästan alla API-funktionsparametrar är faktiskt 32-bitars heltal: HWND är ett 32-bitars heltal, LPCTSTR är en 32-bitars pekare till en sträng, UINT är ett 32-bitars heltal. Suffixet "A" läggs ofta till funktionsnamnet för att flytta till nyare versioner av funktionen.

Anropar Windows API int Message-funktioner. Box(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Typ); När du använder MASM måste du lägga till @N N i slutet av namnet - antalet byte som de godkända argumenten upptar i stacken. För Win 32 API-funktioner kan detta antal definieras som antalet argument n multiplicerat med 4 (byte i varje argument): N=4*n. För att anropa en funktion, använd assembler CALL-instruktionen. I detta fall skickas alla funktionsargument till den via stacken (PUSH-kommandot). Riktning för att skicka argument: VÄNSTER TILL HÖGER - NEDAN UPP. Argumentet u kommer att skjutas upp på stapeln först. Typ. Anropet till den angivna funktionen kommer att se ut så här: CALL-meddelande. Låda. A@16

Anropar Windows API int Message-funktioner. Box(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Typ); Resultatet av att köra valfri API-funktion är vanligtvis ett heltal som returneras i EAX-registret. OFFSET-direktivet representerar en "offset i ett segment", eller, översatt till högnivåspråkliga termer, en "pekare" till början av en rad. EQU-direktivet, liksom #define i SI, definierar en konstant. EXTERN-direktivet talar om för översättaren att funktionen eller identifieraren är extern till denna modul.

Exempel på ett "Hej alla!"-program . 686 P. MODELL PLAT, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Mitt första program", 0 STR 2 DB "Hej alla!", 0 HW DD ? EXTERN Meddelande. Låda. A@16: NÄRA. KOD START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Meddelande. Låda. A@16 RET SLUT START

INVOKE-direktivet MASM-språköversättaren låter dig också förenkla funktionsanrop med hjälp av ett makroverktyg - INVOKE-direktivet: INVOKE-funktion, parameter1, parameter2, ... Det finns inget behov av att lägga till @16 ​​till funktionsanropet; parametrar skrivs exakt i den ordning som de anges i funktionsbeskrivningen. Med hjälp av makro med hjälp av översättaren placeras parametrar på stacken. För att använda INVOKE-direktivet måste du ha en beskrivning av funktionsprototypen med hjälp av PROTO-direktivet i formen: Meddelande. Låda. ETT PROTO: DWORD, : DWORD Om ett program använder många Win 32 API-funktioner, är det lämpligt att använda inkluderingsdirektivet C: masm 32includeuser 32. inc




Topp