Kommandostrukturen för assemblerspråket innehåller: Kommandostruktur i programmering på assemblerspråknivå. Dataformat och kommandostruktur för assemblerspråk

Assembly språkkommandon (föreläsning)

FÖRELÄSNINGSPLAN

1. Huvudgrupper av verksamheter.

Pentium.

1. Huvudgrupper av verksamheter

Mikroprocessorer utför en uppsättning kommandon som implementerar följande huvudgrupper av operationer:

Vidarebefordran

Aritmetiska operationer,

Logiska operationer

Skiftoperationer

Jämförelse och testning

Bitoperationer

Programhanteringsverksamhet;

Processorkontrolloperationer.

2. Mnemoniska koder för processorkommandon Pentium

Vid beskrivning av kommandon används vanligtvis deras mnemoniska beteckningar (mnemoniska koder), som används för att specificera kommandot vid programmering i Assembly-språk. För olika versioner av Assembler kan mnemonkoderna för vissa kommandon skilja sig åt. Till exempel, för kommandot att anropa en subrutin, används mnemonkodenRING UPP eller JSR ("Hoppa till Subrutin"). Mnemonkoderna för de flesta kommandon för huvudtyperna av mikroprocessorer är dock desamma eller skiljer sig något, eftersom de är förkortningar av motsvarande engelska ord som definierar operationen som utförs. Låt oss titta på kommandomnemoniska koder som används för processorer Pentium.

Vidarebefordra kommandon. Huvudlaget i denna grupp är lagetMOV , som tillhandahåller dataöverföring mellan två register eller mellan ett register och en minnescell. Vissa mikroprocessorer implementerar överföringar mellan två minnesceller, såväl som bulköverföringar av innehållet i flera register från minnet. Till exempel mikroprocessorer i 68-familjen Motorola xxx kör kommandotFLYTTA , tillhandahåller överföring från en minnescell till en annan, och kommandotMOVEM , som skriver till minnet eller laddar från minnet innehållet i en specificerad uppsättning register (upp till 16 register). TeamXCHG utbyter ömsesidigt innehållet i två processorregister eller ett register och en minnescell.

Mata in kommandon I och utgång UT implementera att skicka data från ett processorregister till en extern enhet eller ta emot data från en extern enhet till ett register. Dessa kommandon anger numret på gränssnittsenheten (ingång/utgångsport) genom vilken data överförs. Observera att många mikroprocessorer inte har speciella kommandon för åtkomst till externa enheter. I detta fall utförs inmatning och utmatning av data i systemet med kommandotMOV , som anger adressen till den nödvändiga gränssnittsenheten. Således adresseras den externa enheten som en minnescell, och en viss sektion tilldelas i adressutrymmet där adresserna för gränssnittsenheter (portar) som är anslutna till systemet finns.

Aritmetiska operationskommandon. Huvudkommandona i denna grupp är addition, subtraktion, multiplikation och division, som har ett antal alternativ. Tilläggskommandon LÄGG TILL och subtraktion SUB utföra motsvarande operationer medcinnehas av två register, ett register och en minnesplats, eller använder en omedelbar operand. Lag AD C , S.B. B utföra addition och subtraktion med hänsyn till attributets värdeC, ställs in när en överföring bildas under utförandet av föregående operation. Genom att använda dessa kommandon implementeras sekventiell addition av operander, vars antal bitar överstiger processorkapaciteten. Team N.E.G. ändrar operandens tecken och konverterar den till tvåkomplement.

Multiplikation och division kan utföras på tecken med tecken (kommandonjag MUL, jag DIV ) eller osignerad (kommandon MUL, DIV En av operanderna finns alltid i ett register, den andra kan vara i ett register, en minnescell eller vara en omedelbar operand. Resultatet av operationen finns i registret. När du multiplicerar (kommandonMUL , IMUL ) resultatet är dubbelbit, för vilket två register används. När du delar (kommandonDIV , IDIV ) som utdelning används en dubbelbitsoperand, placerad i två register, och som ett resultat skrivs kvoten och resten till två register.

Logiska operationskommandon . Nästan alla mikroprocessorer utför logiska operationer AND, OR, Exclusive OR, som utförs på samma bitar av operander med hjälp av kommandon OCH, ELLER, X ELLER . Operationer utförs på innehållet i två register, ett register och en minnesplats, eller med användning av en omedelbar operand. Team INTE inverterar värdet för varje bit i operanden.

Skiftkommandon. Mikroprocessorer utför aritmetiska, logiska och cykliska förskjutningar av adresserade operander med en eller flera bitar. Den operand som ska skiftas kan vara i ett register eller en minnesplats, och antalet skiftbitar specificeras av den omedelbara operanden som finns i instruktionen eller bestäms av innehållet i det specificerade registret. Överlåtelseskylten är vanligtvis inblandad i genomförandet av skiftetCi statusregistret (S.R. eller EFLAGS), som innehåller den sista biten av operanden som tas bort från registret eller minnescellen.

Jämförelse- och testkommandon . Jämförelse av operander görs vanligtvis med kommandotCMP , som subtraherar operander och ställer in funktionsvärden N, Z, V, C i statusregistret enligt erhållet resultat. I det här fallet sparas inte resultatet av subtraktionen, och operandernas värden ändras inte. Efterföljande analys av de erhållna funktionsvärdena tillåter oss att bestämma det relativa värdet (>,<, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Vissa mikroprocessorer utför testkommandot TST , som är en enkeloperandversion av jämförelseinstruktionen. När detta kommando utförs sätts tecknen N, Z enligt tecknet och värdet (lika eller icke-noll) för den adresserade operanden.

Bitdriftsinstruktioner . Dessa kommandon anger värdet på attributetCi statusregistret i enlighet med värdet på den bit som testasmiljarder i den adresserade operanden. I vissa mikroprocessorer, baserat på resultatet av bittestning, ställs attributet inZ. Testbitnummernspecificeras antingen av innehållet i registret som anges i kommandot eller av den omedelbara operanden.

Kommandon för denna grupp implementerar olika alternativ för att ändra den bit som testas BT behåller värdet på denna bit oförändrat.Command B T S eftertest ställer in värdet miljarder=1 och kommandot B T C - betydelse miljarder=0.Team B T C inverterar värdet på bit bn efter att ha testat det.

Programledningsverksamhet. För att styra programmet används ett stort antal kommandon, bland annat:

- ovillkorliga kommandon för kontrollöverföring;

- villkorliga hoppkommandon;

- lag för att organisera programcykler;

- avbryta kommandon;

- kommandon för att ändra attribut.

Ovillkorlig överföring av kontroll utförs av kommandotJMP , som laddas i programräknarenPCnytt innehåll som är adressen till nästa kommando som ska köras. Denna adress anges antingen direkt i kommandotJMP (direktadressering), eller beräknas som summan av det aktuella innehålletPCoch den offset som anges i kommandot, vilket är ett signerat nummer (relativ adressering). Därför attPCinnehåller adressen för nästa programkommando, den senare metoden specificerar hoppadressen, förskjuten i förhållande till nästa adress med ett specificerat antal byte. Med en positiv offset görs övergången till efterföljande kommandon i programmet, med en negativ offset - till de föregående.

En subrutin anropas också genom att ovillkorligen överföra kontroll med kommandotRING UPP (eller JSR ). Men i det här fallet innan du laddar inPC nytt innehåll som anger adressen för det första kommandot i subrutinen, är det nödvändigt att spara dess nuvarande värde (adressen för nästa kommando) för att säkerställa en återgång till huvudprogrammet efter exekvering av subrutinen (eller till föregående subrutin vid kapsling av subrutiner). Villkorliga hoppkommandon (programgrenar) laddas in iPCnytt innehåll om vissa villkor är uppfyllda, vilka vanligtvis sätts efter det aktuella värdet av olika attribut i statusregistret. Om villkoret inte är uppfyllt, exekveras nästa programkommando.

Funktionskontrollkommandon ger skrivning - läser innehållet i statusregistret där funktioner lagras, samt ändrar värdena för individuella funktioner. Till exempel implementerar Pentium-processorer kommandona LAHF Och SAHF , som laddar den låga byten, som innehåller tecknen, från statusregistret EFLAG till registrets låga byte EAX och utfyllnad av den låga byten EFLAGS från register E AX.. Lag CLC, STC utför inställning av värdena för överföringstecknet CF=0, CF=1 och kommandot CMC gör att värdet på detta attribut inverteras. Eftersom attribut bestämmer flödet av programexekvering under villkorliga övergångar, används vanligtvis attributändringskommandon för att styra programmet.

Processorkontrollkommandon . Denna grupp inkluderar stoppkommandon, inga operationskommandon och ett antal kommandon som bestämmer driftsättet för processorn eller dess individuella block. TeamHLT stoppar programexekveringen och sätter processorn i ett stoppläge, som avslutas när en avbrotts- eller omstartssignal tas emot (Återställa). Team NEJ ("empty"-kommando), som inte gör att några operationer utförs, används för att implementera programfördröjningar eller fylla luckor som bildas i programmet.

Speciallag CLI, STI förbjuda och möjliggöra service av avbrottsbegäranden. I processorer Pentium en kontrollbit (flagga) används för dettaOM i registret EFLAGS.

Många moderna mikroprocessorer utfärdar ett identifieringskommando som gör att användaren eller andra enheter kan få information om vilken typ av processor som används i ett givet system. I processorer Pentuim kommandot för detta är CPUID , under vilken de nödvändiga uppgifterna om processorn kommer in i registren EAXEBXECXEDX och kan sedan läsas av användaren eller operativsystemet.

Beroende på de driftlägen som implementeras av processorn och de specificerade typerna av data som bearbetas, kan uppsättningen av utförda kommandon utökas avsevärt.

Vissa processorer utför aritmetiska operationer med binära decimaltal eller exekverar speciella instruktioner för att korrigera resultatet vid bearbetning av sådana tal. Många högpresterande processorer inkluderar FPU - nummerbehandlingsenhet c "flytpunkt".

Ett antal moderna processorer implementerar gruppbehandling av flera heltal eller tal c "flytande komma" med ett kommando enligt principen SIMD ("Single Instruction – Multiple Data" ") - "Ett kommando - massor av data." Samtidigt utförande av operationer på flera operander förbättrar avsevärt processorprestanda när du arbetar med video- och ljuddata. Sådana operationer används ofta för att bearbeta bilder, ljudsignaler och andra tillämpningar. För att utföra dessa operationer har speciella block införts i processorerna som implementerar motsvarande uppsättningar instruktioner, som i olika typer av processorer ( Pentium, Athlon) fick namnetMMX (“ Milti- Media Extension ”) – Multimedia Extension,SSE("Streaming SIMD Extension") – Strömmande SIMD - förlängning, “3 DFörlängning– Tredimensionell expansion.

En karakteristisk egenskap hos företagets processorer Intel , från och med 80286-modellen, är prioritetskontroll vid åtkomst till minne, som tillhandahålls när processorn arbetar i skyddat virtuellt adressläge - " Skyddat läge " (skyddat läge). För att implementera detta läge används speciella grupper av kommandon, som tjänar till att organisera minnesskydd i enlighet med den antagna prioritetsåtkomstalgoritmen.

Kommandostruktur i assemblerspråk Programmering på nivå med maskinkommandon är den miniminivå 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. Maximal längd Identifieraren har 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 assemblerspråk minnesmodeller: Minnesmodell Kodadressering Dataadressering Operativsystem Kod och datainterleaving TINY NEAR MS-DOS Acceptabel SMALL NEAR MS-DOS, Windows Nej MEDIUM FAR NEAR MS-DOS, Windows Nej KOMPAKT NÄRA LÅNGT MS-DOS, Windows Inget STORT LÅNGT MS-DOS, Windows Inget ENORMT LÅNGT MS-DOS, Windows Inget NÄRA Windows 2000, Windows XP, Windows Acceptable FLAT NÄRA 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 är för närvarande 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 operationssalen Windows-system. 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. Detta program 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 för att markera slutet källkod program. 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.

Assembly language översättare En översättare är ett program eller tekniskt verktyg som konverterar ett program som presenteras 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. Operativsystemet Windows 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

Strukturer i assemblerspråk

De arrayer vi övervägde ovan är en samling element av samma typ. Men ofta i applikationer finns det ett behov av att överväga en viss uppsättning data olika typer som någon enskild typ.

Detta är mycket viktigt, till exempel för databasprogram, där det är nödvändigt att associera en samling data av olika typer till ett objekt.

Till exempel har vi tidigare tittat på Listing 4, där vi arbetade med en array av tre-byte element. Varje element bestod i sin tur av två element av olika typer: ett en-byte räknarfält och ett två-byte fält, som kunde bära en del annan information som är nödvändig för lagring och bearbetning. Om läsaren är bekant med ett av högnivåspråken, då vet han att ett sådant objekt vanligtvis beskrivs med en speciell datatyp - strukturer.

För att förbättra användbarheten av assemblerspråket introducerades även denna datatyp i det.

A-priory strukturera är en datatyp som består av ett fast antal element av olika typer.

För att använda strukturer i ett program måste du utföra tre steg:

    Uppsättning strukturmall .

    Detta innebär i huvudsak att definiera en ny datatyp, som sedan kan användas för att definiera variabler av denna typ.

    Definiera strukturinstans .

    Detta steg involverar initialisering av en specifik variabel med en fördefinierad (med hjälp av mall) struktur.

    Organisera åtkomst till strukturelement .

Det är mycket viktigt att du redan från början förstår vad skillnaden är mellan beskrivning strukturer i programmet och dess definition.

Beskriva struktur i ett program betyder helt enkelt att ange dess kontur eller mönster; minne är inte tilldelat.

Denna mall kan endast betraktas som information för översättaren om fältens placering och deras standardvärde.

Definiera struktur innebär att instruera översättaren att allokera minne och tilldela ett symboliskt namn till detta minnesområde.

En struktur kan beskrivas i ett program endast en gång, men definieras hur många gånger som helst.

Beskrivning av strukturmallen

Strukturmallsbeskrivningen har följande syntax:

strukturnamn STRUC

strukturnamn SLUTAR

Här är en sekvens av databeskrivningsdirektiv db, dw, dd, dq Och dt.

Deras operander bestämmer storleken på fälten och vid behov de initiala värdena. Dessa värden kommer förmodligen att initiera motsvarande fält när strukturen definieras.

Som vi redan noterade när vi beskrev mallen, tilldelas inte minne, eftersom detta bara är information för översättaren.

Plats Mallen i programmet kan vara godtycklig, men enligt logiken hos enpassöversättaren måste den placeras före den plats där variabeln med typen av den givna strukturen definieras. Det vill säga, när man beskriver en variabel med typen av en viss struktur i ett datasegment, måste dess mall placeras i början av datasegmentet eller före det.

Låt oss överväga att arbeta med strukturer med exemplet att modellera en databas om anställda på en viss avdelning.

För enkelhets skull, för att undvika problem med att konvertera information vid inmatning, kommer vi överens om att alla fält är teckenfält.

Låt oss definiera poststrukturen för denna databas med följande mall:

Definiera data med strukturtyp

För att använda en struktur som beskrivs med hjälp av en mall i ett program måste du definiera en variabel med typen av denna struktur. För detta används följande syntaktiska konstruktion:

[variabelnamn] strukturnamn

    variabelnamn- identifierare för en variabel av denna strukturtyp.

    Att ange ett variabelnamn är valfritt. Om du inte anger det, ett minnesområde av storlek lika med summan av längderna av alla strukturelement.

    värdelista- en lista över initiala värden för strukturelement omgivna av vinkelparenteser, separerade med kommatecken.

    Hans uppdrag är också frivilligt.

    Om listan inte är fullständigt specificerad, initieras alla fält i strukturen för denna variabel med värden från mallen, om några är specificerade.

    Det är möjligt att initiera enskilda fält, men i detta fall måste de saknade fälten separeras med kommatecken. Utelämnade fält kommer att initieras med värdena från strukturmallen. Om vi, när vi definierar en ny variabel med typen av en given struktur, håller med alla fältvärden i dess mall (det vill säga de som anges som standard), behöver vi bara skriva vinkelparenteser.

    T.ex: segrararbetare.

Låt oss till exempel definiera flera variabler med den typ av struktur som beskrivs ovan.

Metoder för att arbeta med struktur

Tanken med att introducera en strukturerad typ i alla programmeringsspråk är att kombinera variabler av olika typer till ett objekt.

Språket måste ha ett sätt att komma åt dessa variabler inom en specifik instans av strukturen. För att referera till ett fält av någon struktur i ett kommando, används en speciell operatör - symbol ". " (prick). Det används i följande syntax:

    adressuttryck- identifierare för en variabel av någon strukturell typ eller uttryck inom parentes i enlighet med syntaxreglerna som anges nedan (fig. 1);

    strukturfältsnamn- fältnamn från strukturmallen.

    Detta är faktiskt också en adress, eller snarare, förskjutningen av fältet från början av strukturen.

Således operatören " . " (punkt) utvärderar uttryck

Ris. 5. Syntax för ett adressuttryck i en strukturfältåtkomstoperator

Låt oss demonstrera med hjälp av exemplet på den struktur vi har definierat. arbetstagare några tekniker för att arbeta med strukturer.

Till exempel, extrahera till yxa fältvärden med ålder. Eftersom det är osannolikt att en arbetande persons ålder kommer att vara högre än 99 år, efter att innehållet i detta teckenfält har placerats i registret yxa Det kommer att vara bekvämt att konvertera den till binär representation med kommandot aad.

Var försiktig eftersom på grund av principen om datalagring "låg byte vid låg adress" den högsta siffran i åldern kommer att placeras i al, och den yngsta - in ah.

För att göra justeringar, använd bara kommandot xchg al, ah:

mov axe,ord ptr sotr1.ålder ;i al ålder sotr1

eller så kan du göra så här:

Ytterligare arbete med en rad strukturer utförs på samma sätt som med en endimensionell matris. Flera frågor uppstår här:

Vad ska man göra med storleken och hur man organiserar indexering av arrayelement?

I likhet med andra identifierare som definieras i programmet, tilldelar översättaren ett typattribut till namnet på strukturtypen och namnet på variabeln med strukturtypen. Värdet på detta attribut är storleken i byte som upptas av fälten i denna struktur. Du kan hämta detta värde med operatorn typ.

När storleken på en strukturinstans väl är känd är det inte särskilt svårt att organisera indexering i en uppsättning strukturer.

T.ex:

Hur kopierar man ett fält från en struktur till motsvarande fält i en annan struktur? Eller hur kopierar man hela strukturen? Låt oss kopiera fältet nam tredje anställd på området nam femte anställd:

mas_sotr worker 10 dup()

mov bx,offset mas_sotr

mov si,(typ arbetare)*2 ;si=77*2

mov di,(typ arbetare)*4 ;si=77*4

Det verkar för mig som att vara programmerare förr eller senare får en person att se ut som en bra hemmafru. Han, precis som hon, är ständigt på jakt efter var man kan spara något, skära ner och göra en underbar middag av ett minimum av ingredienser. Och om detta lyckas, då är den moraliska tillfredsställelsen du får inte mindre, och kanske till och med mer, än från en underbar middag med en hemmafru. Graden av denna tillfredsställelse, förefaller det mig, beror på graden av kärlek till ens yrke.

Å andra sidan avslappnar framgångarna i utvecklingen av mjukvara och hårdvara programmeraren något, och ganska ofta observeras en situation som liknar det välkända ordspråket om en fluga och en elefant - för att lösa något mindre problem används tunga verktyg, vars effektivitet, i det allmänna fallet, är betydande endast vid genomförandet av relativt stora projekt.

Förekomsten av följande två typer av data på språket förklaras förmodligen av "hemmafruns" önskan att använda arbetsområdet på bordet (RAM) så effektivt som möjligt när du lagar mat eller för att placera produkter (programdata ).

Kommandon kan särskiljas efter syfte (exempel på mnemoniska operationskoder för IBM PC assembler-kommandon anges inom parentes):

l utföra aritmetiska operationer (ADD och ADC - addition och addition med bär, SUB och SBB - subtraktion och subtraktion med lån, MUL och IMUL - osignerad och signerad multiplikation, DIV och IDIV - osignerad och signerad division, CMP - jämförelser etc.);

l utföra logiska operationer (OR, AND, NOT, XOR, TEST, etc.);

l dataöverföring (MOV - framåt, XCHG - utbyte, IN - gå in i mikroprocessorn, OUT - utmatning från mikroprocessorn, etc.);

l överföring av kontroll (programgrenar: JMP - ovillkorligt hopp, CALL - proceduranrop, RET - retur från procedur, J* - villkorligt hopp, LOOP - loopkontroll, etc.);

l bearbetar teckensträngar (MOVS - överföringar, CMPS - jämförelser, LODS - laddningar, SCAS - skanningar. Dessa kommandon används vanligtvis med prefixet (repetitionsmodifierare) REP;

l programavbrott (INT - mjukvaruavbrott, INTO - villkorligt avbrott vid spill, IRET - retur från avbrott);

l mikroprocessorstyrning (ST* och CL* - inställning och återställning av flaggor, HLT - stopp, WAIT - väntar, NOP - tomgång, etc.).

MED full lista Monteringskommandon finns på gång.

Dataöverföringskommandon

l MOV dst, src - dataöverföring (flytta - skicka från src till dst).

Överföringar: en byte (om src och dst är i byteformat) eller ett ord (om src och dst är i ordformat) mellan register eller mellan ett register och minne, och skriver ett direkt värde till ett register eller minne.

Operanderna dst och src måste ha samma format - byte eller word.

Src kan vara av följande typ: r (register) - register, m (minne) - minne, i (impedans) - omedelbart värde. Dst kan vara av typen r, m. Du kan inte använda följande operander i ett kommando: rsegm tillsammans med i; två operander av typ m och två operander av typ rsegm). i-operanden kan också vara ett enkelt uttryck:

mov AX, (152 + 101B) / 15

Uttrycksutvärdering utförs endast under översättning. Byter inte flaggor.

l PUSH src - trycka ett ord på högen (push - trycka igenom; tryck på stapeln från src). Placerar innehållet i src - vilket 16-bitars register som helst (inklusive segmentregister) eller två minnesceller som innehåller ett 16-bitars ord - på toppen av stacken. Flaggorna ändras inte;

l POP dst - poppa ett ord från stapeln (pop - pop; räkna från stack till dst). Tar bort ett ord från toppen av stacken och placerar det i dst - valfritt 16-bitars register (inklusive segmentregister) eller i två minnesceller. Flaggorna ändras inte.

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). Den maximala etikettlängden är 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 operativ system Windows. 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 som markerar slutet på programmets källkod. 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.




Topp