Heim / Spam / Zusammenfassung: Plan: Vorwort. Assemblersprache und Befehlsstruktur. Die Struktur der Exe-Datei (semantische Analyse). Assemblersprachbefehle (Vorlesung) Tabellenbefehle in Assemblersprache

Zusammenfassung: Plan: Vorwort. Assemblersprache und Befehlsstruktur. Die Struktur der Exe-Datei (semantische Analyse). Assemblersprachbefehle (Vorlesung) Tabellenbefehle in Assemblersprache

Anweisungsstruktur in Assemblersprache Das Programmieren auf der Ebene von Maschinenanweisungen ist die Mindestebene, auf der Computerprogrammierung möglich ist. Das System der Maschinenanweisungen muss ausreichen, um die erforderlichen Aktionen durch die Ausgabe von Anweisungen an die Maschinenhardware umzusetzen. Jeder Maschinenbefehl besteht aus zwei Teilen: einem Betriebsteil, der definiert, „was zu tun ist“, und einem Operanden, der Verarbeitungsobjekte definiert, das heißt, „was zu tun ist“. Die in Assemblersprache geschriebene Maschinenanweisung des Mikroprozessors ist eine einzelne Zeile mit der folgenden Form: Label-Anweisung/Direktive Operand(en); Kommentare Label, Befehl/Anweisung und Operand werden durch mindestens ein Leerzeichen oder Tabulatorzeichen getrennt. Die Anweisungsoperanden werden durch Kommas getrennt.

Struktur eines Assemblersprachbefehls Ein Assemblersprachbefehl teilt dem Compiler mit, welche Aktion der Mikroprozessor ausführen soll. Assembler-Direktiven sind im Programmtext angegebene Parameter, die den Assembler-Prozess oder die Eigenschaften der Ausgabedatei beeinflussen. Der Operand gibt den Anfangswert der Daten (im Datensegment) oder der Elemente an, auf die der Befehl einwirken soll (im Codesegment). Eine Anweisung kann einen oder zwei Operanden oder keine Operanden haben. Die Anzahl der Operanden wird implizit durch den Befehlscode angegeben. Wenn der Befehl oder die Anweisung in der nächsten Zeile fortgesetzt werden muss, wird der umgekehrte Schrägstrich verwendet: "" . Standardmäßig unterscheidet der Assembler in Befehlen und Direktiven nicht zwischen Groß- und Kleinschreibung. Beispiele für Anweisungen und Befehle Count db 1 ; Name, Direktive, ein Operand mov eax, 0 ; Befehl, zwei Operanden

Bezeichner sind Folgen gültiger Zeichen, die zur Bezeichnung von Variablennamen und Bezeichnungsnamen verwendet werden. Die Kennung kann aus einem oder mehreren der folgenden Zeichen bestehen: alle Buchstaben des lateinischen Alphabets; Zahlen von 0 bis 9; Sonderzeichen: _, @, $, ? . Als erstes Zeichen des Labels kann ein Punkt verwendet werden. Reservierte Assemblernamen (Direktiven, Operatoren, Befehlsnamen) können nicht als Bezeichner verwendet werden. Das erste Zeichen der Kennung muss ein Buchstabe oder ein Sonderzeichen sein. Die maximale Bezeichnerlänge beträgt 255 Zeichen, aber der Übersetzer akzeptiert die ersten 32 Zeichen und ignoriert den Rest. Alle Labels, die in eine Zeile geschrieben werden, die keine Assembler-Direktive enthält, müssen mit einem Doppelpunkt ":" enden. Label, Befehl (Direktive) und Operand müssen nicht an einer bestimmten Position im String beginnen. Es wird empfohlen, sie für eine bessere Lesbarkeit des Programms in eine Spalte zu schreiben.

Labels Alle Labels, die in eine Zeile geschrieben werden, die keine Assembler-Direktive enthält, müssen mit einem Doppelpunkt ":" enden. Label, Befehl (Direktive) und Operand müssen nicht an einer bestimmten Position im String beginnen. Es wird empfohlen, sie für eine bessere Lesbarkeit des Programms in eine Spalte zu schreiben.

Kommentare Die Verwendung von Kommentaren in einem Programm verbessert dessen Übersichtlichkeit, insbesondere wenn der Zweck einer Reihe von Anweisungen unklar ist. Kommentare beginnen in jeder Zeile eines Quellmoduls mit einem Semikolon (;). Alle Zeichen rechts von "; ' am Ende der Zeile stehen Kommentare. Der Kommentar kann alle druckbaren Zeichen enthalten, einschließlich „Leerzeichen“. Der Kommentar kann sich über die gesamte Zeile erstrecken oder dem Befehl in derselben Zeile folgen.

Struktur eines Assemblersprachenprogramms Ein Assemblersprachenprogramm kann aus mehreren Teilen bestehen, die als Module bezeichnet werden und von denen jeder ein oder mehrere Daten-, Stack- und Codesegmente definieren kann. Jedes vollständige Assemblersprachenprogramm muss ein Haupt- oder Hauptmodul enthalten, von dem aus seine Ausführung beginnt. Ein Modul kann Programm-, Daten- und Stapelsegmente enthalten, die mit den entsprechenden Direktiven deklariert sind.

Speichermodelle Bevor Sie Segmente deklarieren, müssen Sie das Speichermodell mit einer Direktive angeben. Modifizierer MODEL Speichermodell, Aufrufkonvention, Betriebssystemtyp, Stapelparameter Grundlegende Speichermodelle in Assemblersprache: Speichermodell Codeadressierung Datenadressierung Betriebssystem Code- und Datenverschachtelung TINY NEAR MS-DOS Gültig SMALL NEAR MS-DOS, Windows Nein MEDIUM FAR NEAR NEAR MS-DOS, Windows Nein COMPACT NEAR FAR MS-DOS, Windows Nein LARGE FAR MS-DOS, Windows Nein HUGE FAR MS-DOS, Windows Nein NEAR Windows 2000, Windows XP, Windows Valid FLAT NEAR NT,

Speichermodelle Das winzige Modell funktioniert nur in 16-Bit-MS-DOS-Anwendungen. In diesem Modell befinden sich alle Daten und Codes in einem physischen Segment. Die Größe der Programmdatei überschreitet in diesem Fall 64 KB nicht. Das kleine Modell unterstützt ein Codesegment und ein Datensegment. Daten und Code werden bei Verwendung dieses Modells als near (near) adressiert. Das mittlere Modell unterstützt mehrere Codesegmente und ein Datensegment, wobei alle Links in den Codesegmenten standardmäßig als weit entfernt und Links im Datensegment als nah (near) gelten. Das kompakte Modell unterstützt mehrere Datensegmente, die die Ferndatenadressierung (far) verwenden, und ein Codesegment, das die Nahdatenadressierung (near) verwendet. Das große Modell unterstützt mehrere Codesegmente und mehrere Datensegmente. Standardmäßig werden alle Code- und Datenreferenzen weit berücksichtigt. Das riesige Modell entspricht fast dem großen Speichermodell.

Speichermodelle Das flache Modell geht von einer nicht segmentierten Programmkonfiguration aus und wird nur auf 32-Bit-Betriebssystemen verwendet. Dieses Modell ähnelt dem winzigen Modell darin, dass sich die Daten und der Code im selben 32-Bit-Segment befinden. Entwicklung eines Programms für das flache Modell vor der Richtlinie. model flat sollte eine der Anweisungen platzieren: . 386, . 486, . 586 bzw. 686. Die Wahl der Prozessorauswahldirektive bestimmt den Satz verfügbarer Befehle beim Schreiben von Programmen. Der Buchstabe p nach der Prozessorauswahlanweisung bedeutet Protected Mode of Operation. Die Daten- und Codeadressierung ist nahe, wobei alle Adressen und Zeiger 32-Bit sind.

Gedächtnismodelle. MODEL Modifikator memory_model, calling_convention, OS_type, stack_parameter Der Modifikatorparameter wird verwendet, um Segmenttypen zu definieren und kann die folgenden Werte annehmen: use 16 (Segmente des ausgewählten Modells werden als 16-Bit verwendet) use 32 (Segmente des ausgewählten Modells werden verwendet als 32-Bit). Der Parameter "calling_convention" wird verwendet, um festzulegen, wie Parameter beim Aufrufen einer Prozedur aus anderen Sprachen, einschließlich Sprachen, übergeben werden hohes Level(C++, Pascal). Der Parameter kann folgende Werte annehmen: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Gedächtnismodelle. MODEL-Modifizierer memory_model, calling_convention, OS_type, stack_parameter Der OS_type-Parameter ist standardmäßig OS_DOS und on dieser Moment dies ist der einzige unterstützte Wert für diesen Parameter. Der Parameter stack_param ist gesetzt auf: NEARSTACK (SS-Register ist gleich DS, Daten- und Stack-Regionen befinden sich im selben physikalischen Segment) FARSTACK (SS-Register ist nicht gleich DS, Daten- und Stack-Regionen befinden sich in unterschiedlichen physikalischen Segmenten). Der Standardwert ist NEARSTACK.

Ein Beispiel für ein „Nichtstun“-Programm. 686 P. MODELL WOHNUNG, STDCALL. DATEN. CODE START: RET END START RET - Mikroprozessorbefehl. Es sorgt für die korrekte Beendigung des Programms. Der Rest des Programms bezieht sich auf den Betrieb des Übersetzers. . 686 P - Pentium 6 (Pentium II) geschützte Modusbefehle sind erlaubt. Diese Direktive wählt den unterstützten Assembler-Befehlssatz durch Angabe des Prozessormodells aus. . MODEL FLAT, stdcall - flaches Speichermodell. Dieses Speichermodell wird im Windows-Betriebssystem verwendet. stdcall ist die zu verwendende Prozeduraufrufkonvention.

Ein Beispiel für ein „Nichtstun“-Programm. 686 P. MODELL WOHNUNG, STDCALL. DATEN. CODE START: RET ENDE START . DATA - Programmsegment, das Daten enthält. Dieses Programm verwendet den Stack nicht, also segmentieren. STAPEL fehlt. . CODE - ein Segment des Programms, das den Code enthält. START - Etikett. END START - das Ende des Programms und eine Nachricht an den Compiler, dass das Programm ab dem Label START gestartet werden muss. Jedes Programm muss eine END-Direktive enthalten, die das Ende des Quellcodes des Programms markiert. Alle Zeilen, die auf die END-Direktive folgen, werden ignoriert.Das Label nach der END-Direktive teilt dem Compiler den Namen des Hauptmoduls mit, von dem aus die Programmausführung beginnt. Wenn das Programm ein Modul enthält, kann das Label nach der END-Direktive weggelassen werden.

Assembler-Sprachübersetzer Ein Übersetzer ist ein Programm oder eine Hardware, die ein Programm, das in einer der Programmiersprachen präsentiert wird, in ein Programm in der Zielsprache, Objektcode genannt, umwandelt. Zusätzlich zur Unterstützung von Mnemoniken für Maschinenanweisungen hat jeder Übersetzer seinen eigenen Satz von Anweisungen und Makros, die oft mit nichts anderem kompatibel sind. Die Haupttypen von Assembler-Übersetzern sind: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) – ein frei verteilter Multi-Pass-Assembler, geschrieben von Tomasz Gryshtar (Polnisch), NASM (Netwide Assembler) – a Der kostenlose Assembler für die Intel-x-Architektur 86 wurde von Simon Tatham mit Julian Hall erstellt und wird derzeit von einem kleinen Entwicklerteam bei Source entwickelt. Schmiede. Netz.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="(!LANG:Programmübersetzung in Microsoft Visual Studio 2005 1) Erstellen Sie ein Projekt, indem Sie Datei->Neu->Projekt auswählen Menü u"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В !} Zusatzoptionen Projektassistenten, um „Leeres Projekt“ anzugeben.

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="(!LANG:Programmübersetzung in Microsoft Visual Studio 2005 2) Im Projektbaum (Ansicht->Solution Explorer) hinzufügen"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Übersetzung des Programms in Microsoft Visual Studio 2005 3) Wählen Sie den Dateityp Code C++, aber geben Sie den Namen mit der Erweiterung an. asm:

Übersetzung des Programms in Microsoft Visual Studio 2005 5) Compiler-Optionen setzen. Wählen Sie auf der rechten Schaltfläche im Projektdateimenü Custom Build Rules…

Übersetzung des Programms in Microsoft Visual Studio 2005 und wählen Sie im angezeigten Fenster Microsoft Macro Assembler.

Übersetzung des Programms in Microsoft Visual Studio 2005 Überprüfen Sie mit der rechten Maustaste in der Datei hallo. asm des Projektbaums aus dem Menü Eigenschaften und wählen Sie Allgemein->Tool: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="(!LANG:Programmübersetzung in Microsoft Visual Studio 2005 6) Kompilieren Sie die Datei, indem Sie Build->Build hello.prj auswählen ."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Programmierung im Betriebssystem Windows Die Programmierung im Betriebssystem Windows basiert auf der Verwendung von API-Funktionen (Application Program Interface, d. h. Software-Anwendungsschnittstelle). Ihre Zahl erreicht 2000. Das Programm für Windows besteht größtenteils aus solchen Aufrufen. Alle Interaktionen mit externen Geräten und Ressourcen des Betriebssystems erfolgen in der Regel über solche Funktionen. Operationssaal Windows-System verwendet ein flaches Speichermodell. Die Adresse jeder Speicherstelle wird durch den Inhalt eines 32-Bit-Registers bestimmt. Es gibt 3 Arten von Programmstrukturen für Windows: Dialog (das Hauptfenster ist ein Dialog), Konsolen- oder fensterlose Struktur, klassische Struktur (Fenster, Rahmen).

Aufrufen von Windows-API-Funktionen In der Hilfedatei wird jede API-Funktion als Typ Funktionsname (FA 1, FA 2, FA 3) dargestellt Typ – Typ des Rückgabewerts; FAX – Liste der formalen Argumente in ihrer Reihenfolge, zum Beispiel int Nachricht. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Diese Funktion zeigt ein Fenster mit einer Nachricht und einer oder mehreren Exit-Schaltflächen an. Bedeutung der Parameter: h. Wnd - Handle auf das Fenster, in dem das Nachrichtenfenster erscheinen wird, lp. Text - der Text, der im Fenster erscheint, lp. Beschriftung - Text im Fenstertitel, u. Typ - Fenstertyp, insbesondere können Sie die Anzahl der Exit-Schaltflächen angeben.

Aufrufen von Windows-API-Funktionen int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Fast alle API-Funktionsparameter sind tatsächlich 32-Bit-Ganzzahlen: HWND ist eine 32-Bit-Ganzzahl, LPCTSTR ist ein 32-Bit-String-Zeiger, UINT ist eine 32-Bit-Ganzzahl. Das Suffix "A" wird häufig an den Namen von Funktionen angehängt, um zu neueren Versionen von Funktionen zu springen.

Aufrufen von Windows-API-Funktionen int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Wenn Sie MASM verwenden, müssen Sie am Ende des Namens @N N hinzufügen – die Anzahl der Bytes, die die übergebenen Argumente auf dem Stapel belegen. Für Win 32-API-Funktionen kann diese Zahl als die Anzahl der Argumente n mal 4 (Bytes in jedem Argument) definiert werden: N=4*n. Um eine Funktion aufzurufen, wird die CALL-Anweisung des Assemblers verwendet. In diesem Fall werden der Funktion alle Argumente über den Stack übergeben (PUSH-Befehl). Übergaberichtung des Arguments: LINKS NACH RECHTS – UNTEN NACH OBEN. Das Argument u wird zuerst auf den Stack geschoben. Typ. Der Aufruf der angegebenen Funktion sieht folgendermaßen aus: CALL Message. Kasten. [E-Mail geschützt]

Aufrufen von Windows-API-Funktionen int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Das Ergebnis der Ausführung einer API-Funktion ist normalerweise eine Ganzzahl, die im EAX-Register zurückgegeben wird. Die OFFSET-Direktive ist ein "Segment-Offset" oder, in Hochsprache ausgedrückt, ein "Zeiger" auf den Beginn einer Zeichenkette. Die Direktive EQU definiert wie #define in C eine Konstante. Die Direktive EXTERN teilt dem Compiler mit, dass eine Funktion oder ein Bezeichner außerhalb des Moduls liegt.

Ein Beispiel für das Programm "Hallo alle zusammen!" . 686 P. MODELL WOHNUNG, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Mein erstes Programm", 0 STR 2 DB "Hallo zusammen!", 0 HW DD ? EXTERNE Nachricht. Kasten. [E-Mail geschützt]: NAHE. CODE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Nachricht. Kasten. [E-Mail geschützt] ZURÜCK ENDE START

Die INVOKE-Direktive Der MASM-Sprachübersetzer ermöglicht es auch, den Funktionsaufruf mit einem Makrotool zu vereinfachen - der INVOKE-Direktive: INVOKE-Funktion, Parameter1, Parameter2, ... Es besteht keine Notwendigkeit, @16 zum Funktionsaufruf hinzuzufügen; die Parameter werden genau in der Reihenfolge geschrieben, in der sie in der Funktionsbeschreibung angegeben sind. Übersetzer-Makros schieben Parameter auf den Stack. Um die INVOKE-Direktive verwenden zu können, benötigen Sie eine Beschreibung des Funktionsprototyps mit der PROTO-Direktive in der Form: Nachricht. Kasten. A PROTO: DWORD, : DWORD

Thema 2.5 Grundlagen der Prozessorprogrammierung

Mit zunehmender Länge des Programms wird es schwieriger, sich die Codes für verschiedene Operationen zu merken. Mnemotechniken bieten dabei eine gewisse Hilfe.

Die symbolische Befehlscodierungssprache wird aufgerufen Monteur.

Assemblersprache ist eine Sprache, in der jede Anweisung genau einem Maschinenbefehl entspricht.

Montage als Konvertieren eines Programms aus der Assemblersprache bezeichnet, d. h. Vorbereiten eines Programms in Maschinensprache durch Ersetzen symbolischer Namen von Operationen durch Maschinencodes und symbolischer Adressen durch absolute oder relative Zahlen sowie Einschließen von Bibliotheksprogrammen und Generieren von Folgen symbolischer Anweisungen durch Spezifizieren spezifischer Parameter in Mikrobefehlen. Dieses Programm wird normalerweise im ROM platziert oder von einem externen Medium in den RAM eingegeben.

Die Assemblersprache hat mehrere Merkmale, die sie von Hochsprachen unterscheiden:

1. Dies ist eine Eins-zu-Eins-Entsprechung zwischen Anweisungen in Assemblersprache und Maschinenbefehlen.

2. Der Programmierer der Assemblersprache hat Zugriff auf alle Objekte und Befehle, die auf der Zielmaschine vorhanden sind.

Ein Verständnis der Grundlagen der Programmierung in maschinennahen Sprachen ist hilfreich für:



Besseres Verständnis der PC-Architektur und bessere Nutzung von Computern;

Rationellere Strukturen von Algorithmen für Programme zur Lösung angewandter Probleme zu entwickeln;

Die Möglichkeit, ausführbare Programme mit den Erweiterungen .exe und .com, die aus beliebigen Hochsprachen kompiliert wurden, bei Verlust der Quellprogramme anzuzeigen und zu korrigieren (indem diese Programme in den DEBUG-Programmdebugger aufgerufen und ihre Anzeige in Assemblersprache dekompiliert werden );

Zusammenstellung von Programmen zur Lösung der kritischsten Aufgaben (ein in einer maschinenorientierten Sprache kompiliertes Programm ist normalerweise effizienter - kürzer und schneller um 30-60 Prozent der Programme, die als Ergebnis der Übersetzung aus Hochsprachen erhalten werden)

Zur Implementierung von im Hauptprogramm enthaltenen Prozeduren als separate Fragmente für den Fall, dass diese weder in der verwendeten Hochsprache noch mit OS-Dienstprozeduren implementiert werden können.

Ein Programm in Assemblersprache kann nur auf Computern derselben Familie ausgeführt werden, während ein in einer Hochsprache geschriebenes Programm möglicherweise auf verschiedenen Computern ausgeführt werden kann.

Das Alphabet der Assemblersprache besteht aus ASCII-Zeichen.

Zahlen sind nur ganze Zahlen. Unterscheiden:

Binärzahlen, die mit dem Buchstaben B enden;

Dezimalzahlen, die mit D enden;

Hexadezimalzahlen, die mit dem Buchstaben N enden.

RAM, Register, Datendarstellung

Für eine bestimmte Reihe von MPs wird eine eigene Programmiersprache verwendet - die Assemblersprache.

Die Assemblersprache nimmt eine Zwischenstellung zwischen Maschinencodes und Hochsprachen ein. Das Programmieren in dieser Sprache ist einfacher. Ein Programm in Assemblersprache nutzt die Fähigkeiten einer bestimmten Maschine (genauer gesagt MP) rationeller als ein Programm in einer Hochsprache (was für einen Programmierer einfacher ist als für einen Assembler). Wir betrachten die Grundprinzipien der Programmierung in maschinennahen Sprachen am Beispiel der Assemblersprache für MP KR580VM80. Zum Programmieren in der Sprache wird eine allgemeine Technik verwendet. Spezifische Techniken zum Aufzeichnen von Programmen beziehen sich auf die Architektur und Befehlssystemmerkmale des Ziel-MP.

Softwaremodell eines Mikroprozessorsystems basierend auf MP KR580VM80

Das Programmmodell des MPS gemäß Bild 1

MP Ports Speicher

S Z AC P C

Bild 1

Aus Sicht des Programmierers hat der KR580VM80 MP die folgenden programmzugänglichen Register.

ABER– 8-Bit-Akkuregister. Es ist das Hauptregister von MP. Jede in der ALU durchgeführte Operation beinhaltet das Plazieren eines der zu verarbeitenden Operanden in den Akkumulator. Das Ergebnis der Operation in der ALU wird normalerweise auch in A gespeichert.

B, C, D, E, H, L– 8-Bit-Universalregister (RON). MP interner Speicher. Entwickelt, um die verarbeiteten Informationen sowie die Ergebnisse der Operation zu speichern. Bei der Verarbeitung von 16-Bit-Wörtern aus Registern werden Paare BC, DE, HL gebildet, und das Doppelregister wird als erster Buchstabe bezeichnet - B, D, H. Im Registerpaar ist das erste Register das höchste. Die H-, L-Register, die sowohl zum Speichern von Daten als auch zum Speichern von 16-Bit-Adressen von RAM-Zellen verwendet werden, haben eine besondere Eigenschaft.

FL– Flag-Register (Feature-Register) Ein 8-Bit-Register, das fünf Features des Ergebnisses der Durchführung arithmetischer und logischer Operationen im MP speichert. FL-Format laut Bild

Bit C (CY - Übertrag) - Übertrag, auf 1 gesetzt, wenn bei der Durchführung arithmetischer Operationen ein Übertrag von der höheren Ordnung des Bytes vorhanden war.

Bit P (Parität) - Parität, wird auf 1 gesetzt, wenn die Anzahl der Einheiten in den Bits des Ergebnisses gerade ist.

Das AC-Bit ist ein zusätzlicher Übertrag, der dazu bestimmt ist, den Übertragswert aus der unteren Tetrade des Ergebnisses zu speichern.

Bit Z (Null) – auf 1 gesetzt, wenn das Ergebnis der Operation 0 ist.

Das S-Bit (Vorzeichen) wird auf 1 gesetzt, wenn das Ergebnis negativ ist, und auf 0, wenn das Ergebnis positiv ist.

SP-- der Stapelzeiger, ein 16-Bit-Register, dient zum Speichern der Adresse des Speicherplatzes, an dem das zuletzt in den Stapel eingegebene Byte geschrieben wurde.

RS– Programmzähler (Programmzähler), 16-Bit-Register, zum Speichern der Adresse der nächsten ausführbaren Anweisung. Der Inhalt des Programmzählers wird automatisch um 1 erhöht, sobald das nächste Befehlsbyte geholt wird.

Im anfänglichen Speicherbereich der Adresse 0000H - 07FF befinden sich ein Steuerprogramm und Demoprogramme. Dies ist der ROM-Bereich.

0800 - 0AFF - Adressbereich zur Aufnahme der Studiengänge. (RAM).

0В00 - 0ВВ0 - Adressbereich für die Datenaufzeichnung. (RAM).

0BB0 ist die Startadresse des Stapels. (RAM).

Stack ist ein speziell organisierter RAM-Bereich, der zum vorübergehenden Speichern von Daten oder Adressen bestimmt ist. Die letzte Zahl, die auf den Stapel geschoben wird, ist die erste Zahl, die vom Stapel abgehoben wird. Der Stapelzeiger speichert die Adresse der letzten Stapelstelle, wo Informationen gespeichert sind. Beim Aufruf eines Unterprogramms wird die Rücksprungadresse zum Hauptprogramm automatisch auf dem Stack gespeichert. In der Regel werden zu Beginn jedes Unterprogramms die Inhalte aller an seiner Ausführung beteiligten Register auf dem Stack abgelegt und am Ende des Unterprogramms vom Stack wiederhergestellt.

Datenformat und Befehlsstruktur der Assemblersprache

Der Speicher MP KR580VM80 ist ein Array aus 8-Bit-Wörtern, die Bytes genannt werden.Jedes Byte hat seine eigene 16-Bit-Adresse, die seine Position in der Folge vonSpeicherzellen bestimmt. Der MP kann 65536 Byte Speicher adressieren, der sowohl ROM als auch RAM enthalten kann.

Datei Format

Daten werden im Speicher als 8-Bit-Wörter gespeichert:

D7 D6 D5 D4 D3 D2 D1 D0

Das niedrigstwertige Bit ist Bit 0, das höchstwertige Bit ist Bit 7.

Der Befehl ist durch das Format gekennzeichnet, d. h. die Anzahl der ihm zugeordneten Bits, die byteweise in bestimmte Funktionsfelder unterteilt sind.

Befehlsformat

MP KR580VM80-Befehle haben ein, zwei oder drei Byte Format. Multibyte-Anweisungen müssen in benachbarten PLs platziert werden. Das Format des Befehls hängt von den Besonderheiten der ausgeführten Operation ab.

Das erste Byte des Befehls enthält den in mnemonischer Form geschriebenen Opcode.

Es definiert das Format des Befehls und die Aktionen, die von dem MP an den Daten während seiner Ausführung durchgeführt werden müssen, sowie das Adressierungsverfahren und kann auch Informationen über den Speicherort der Daten enthalten.

Das zweite und dritte Byte können zu bearbeitende Daten oder Adressen enthalten, die den Ort der Daten angeben. Die Daten, an denen Operationen durchgeführt werden, werden Operanden genannt.

Single-Byte-Befehlsformat gemäß Abbildung 2

Figur 4

In Anweisungen in Assemblersprache hat der Opcode eine abgekürzte Schreibweise englischer Wörter - eine mnemonische Notation. Mnemonik (aus dem Griechischen mnemonisch - die Kunst des Auswendiglernens) erleichtert es, sich Befehle entsprechend ihrem funktionalen Zweck zu merken.

Vor der Ausführung wird das Quellprogramm mit einem Übersetzungsprogramm, Assembler genannt, in die Sprache der Codekombinationen – Maschinensprache – übersetzt, in dieser Form im Speicher des MP abgelegt und dann bei der Ausführung des Befehls verwendet.


Adressierungsmethoden

Alle Operandencodes (Ein- und Ausgang) müssen irgendwo stehen. Sie können sich in den internen Registern des MP befinden (die bequemste und schnellste Option). Sie können sich im Systemspeicher befinden (die häufigste Option). Schließlich können sie sich in E / A-Geräten befinden (der seltenste Fall). Die Position der Operanden wird durch den Befehlscode bestimmt. Es gibt verschiedene Verfahren, durch die der Befehlscode bestimmen kann, woher der Eingangsoperand genommen und wo der Ausgangsoperand abgelegt werden soll. Diese Methoden werden als Adressierungsmethoden bezeichnet.

Für MP KR580VM80 gibt es folgende Adressierungsmethoden:

Sofort;

Registrieren;

indirekt;

Stapel.

Sofort Die Adressierung geht davon aus, dass sich der Operand (Eingabe) unmittelbar nach dem Befehlscode im Speicher befindet. Der Operand ist normalerweise eine Konstante, die irgendwo gesendet, zu etwas hinzugefügt werden muss usw. Daten sind im zweiten oder zweiten und dritten Byte der Anweisung enthalten, wobei das niedrige Datenbyte im zweiten Befehlsbyte und das hohe Datenbyte enthalten sind im dritten Befehlsbyte.

Gerade Die (auch als absolute) Adressierung geht davon aus, dass sich der Operand (Eingabe oder Ausgabe) im Speicher an der Adresse befindet, deren Code sich innerhalb des Programms unmittelbar nach dem Befehlscode befindet. Wird in Drei-Byte-Befehlen verwendet.

Registrieren Die Adressierung setzt voraus, dass der Operand (Eingang oder Ausgang) im internen MP-Register steht. Wird in Einzelbyte-Befehlen verwendet

Indirekt Die (implizite) Adressierung geht davon aus, dass das interne Register des MP nicht der Operand selbst ist, sondern seine Adresse im Speicher.

Stapel Die Adressierung setzt voraus, dass der Befehl keine Adresse enthält. Adressierung von Speicherzellen durch den Inhalt des 16-Bit-SP-Registers (Stapelzeiger).

Befehlssystem

Das MP-Befehlssystem ist eine vollständige Liste elementarer Aktionen, die der MP ausführen kann. Der durch diese Befehle gesteuerte MP führt aus einfache Schritte, wie elementare arithmetische und logische Operationen, Datenübertragung, Vergleich zweier Werte usw. Die Anzahl der Befehle MP KR580VM80 - 78 (einschließlich Modifikationen 244).

Es gibt folgende Befehlsgruppen:

Datenübertragung;

Arithmetik;

Rätsel;

Sprungbefehle;

Befehle für Input-Output, Steuerung und Arbeit mit dem Stack.


Symbole und Abkürzungen, die zur Beschreibung von Befehlen und zum Schreiben von Programmen verwendet werden

Symbol Die Ermäßigung
ADDR 16-Bit-Adresse
DATEN 8-Bit-Daten
DATEN 16 16-Bit-Daten
HAFEN 8-Bit-E/A-Adresse (E/A-Geräte)
Byte 2 Zweites Befehlsbyte
Byte 3 Drittes Befehlsbyte
R, R1, R2 Eines der Register: A, B, C, D, E, H, L
RP Eines der Registerpaare: B - stellt ein Flugzeugpaar ein; D - setzt ein Paar DE; H - gibt ein Paar HL an
RH Erstes Register des Paares
RL Zweites Register des Paares
Λ Boolesche Multiplikation
v Boolesche Addition
Modulo-Zwei-Addition
M Speicherzelle, deren Adresse den Inhalt des HL-Registerpaares angibt, also M = (HL)

Befehle der Assemblersprache (Vorlesung)

LEHRPLAN

1. Hauptgruppen von Operationen.

Pentium.

1. Hauptgruppen von Operationen

Mikroprozessoren führen eine Reihe von Anweisungen aus, die die folgenden Hauptgruppen von Operationen implementieren:

Speditionsgeschäfte,

Rechenoperationen,

logische Operationen,

Schichtbetrieb,

Vergleichs- und Testbetrieb,

Bitoperationen,

Programmverwaltungsoperationen;

Prozessorsteuerungsoperationen.

2. Mnemocodes von Prozessorbefehlen Pentium

Bei der Beschreibung von Befehlen werden meist deren mnemotechnische Bezeichnungen (mnemonische Codes) verwendet, die bei der Programmierung in Assembler zur Spezifizierung des Befehls dienen. Für verschiedene Versionen des Assemblers können sich die mnemonischen Codes einiger Befehle unterscheiden. Beispielsweise wird für einen Befehl zum Aufrufen einer Subroutine der mnemonische Code verwendetANRUF oder JSR ("Springen zu Subroutine“). Die mnemonischen Codes der meisten Befehle für die Haupttypen von Mikroprozessoren sind jedoch gleich oder unterscheiden sich geringfügig, da sie Abkürzungen der entsprechenden englischen Wörter sind, die die auszuführende Operation definieren. Betrachten Sie Befehlsmnemoniken, die für Prozessoren übernommen wurden Pentium.

Befehle weiterleiten. Der Hauptbefehl dieser Gruppe ist der BefehlBEWEGUNG , die eine Datenübertragung zwischen zwei Registern oder zwischen einem Register und einer Speicherzelle bereitstellt. Einige Mikroprozessoren implementieren eine Übertragung zwischen zwei Speicherzellen sowie eine Gruppenübertragung der Inhalte mehrerer Register aus dem Speicher. Zum Beispiel Mikroprozessoren der 68er-Familie Motorolaxxx den Befehl ausführenBEWEGUNG , der die Übertragung von einer Speicherzelle zur anderen bereitstellt, und dem BefehlBEWEGUNG , das den Inhalt eines bestimmten Satzes von Registern (bis zu 16 Register) in den Speicher schreibt oder aus dem Speicher lädt. MannschaftXCHG führt einen gegenseitigen Austausch der Inhalte zweier Prozessorregister oder eines Registers und einer Speicherzelle durch.

Befehle eingeben IN und Ausgabe AUS die Übertragung von Daten vom Prozessorregister an ein externes Gerät oder den Empfang von Daten von einem externen Gerät an das Register implementieren. Diese Befehle geben die Nummer des Schnittstellengeräts (I/O-Port) an, über das Daten übertragen werden. Beachten Sie, dass viele Mikroprozessoren keine speziellen Anweisungen für den Zugriff haben Externe Geräte. In diesem Fall erfolgt die Ein- und Ausgabe von Daten im System über den BefehlBEWEGUNG , die die Adresse des erforderlichen Schnittstellengeräts angibt. Somit wird ein externes Gerät als Speicherzelle adressiert und im Adressraum ein bestimmter Abschnitt zugewiesen, in dem sich die Adressen von Schnittstellengeräten (Ports), die mit dem System verbunden sind, befinden.

Befehle für arithmetische Operationen. Die Hauptbefehle in dieser Gruppe sind Addition, Subtraktion, Multiplikation und Division, die eine Reihe von Optionen haben. Additionsbefehle HINZUFÜGEN und Subtraktion SUB Führen Sie entsprechende Operationen mit durchcBesitzen von zwei Registern, einem Register und einer Speicherstelle, oder Verwenden eines unmittelbaren Operanden. Mannschaften ANZEIGE C , SB B Führen Sie Addition und Subtraktion unter Berücksichtigung des Werts des Attributs durchC, gesetzt während der Bildung der Übertragung im Prozess der Durchführung der vorherigen Operation. Mit Hilfe dieser Befehle wird die sequentielle Addition von Operanden realisiert, deren Stellenzahl die Prozessorkapazität übersteigt. Mannschaft NEG ändert das Vorzeichen des Operanden und wandelt ihn in das Zweierkomplement um.

Multiplikations- und Divisionsoperationen können mit vorzeichenbehafteten Zahlen durchgeführt werden (Befehleich MUL, ich DIV ) oder unsigned (commands MUL, DIV ). Das Ergebnis der Operation befindet sich im Register. Beim Multiplizieren (BefehleMUL , IMUL ) ist das Ergebnis der doppelten Bitbreite, die zwei Register zur Unterbringung benötigt. Beim Teilen (BefehleDIV , IDIV ) als Dividende wird ein zweistelliger Operand verwendet, in zwei Registern platziert, und als Ergebnis werden der Quotient und der Rest in zwei Register geschrieben.

Logikbefehle . Nahezu alle Mikroprozessoren führen logische Operationen UND, ODER, Exklusiv-ODER durch, die mit Befehlen auf den gleichnamigen Operandenbits ausgeführt werden UND, ODER, X ODER . Operationen werden an den Inhalten von zwei Registern, einem Register und einer Speicherstelle, oder unter Verwendung eines Direktoperanden durchgeführt. Mannschaft NICHT Invertiert den Wert jedes Bits des Operanden.

Schaltbefehle. Mikroprozessoren führen arithmetische, logische und zyklische Verschiebungen der adressierten Operanden um ein oder mehrere Bits durch. Der zu verschiebende Operand kann sich in einem Register oder einer Speicherstelle befinden, und die Anzahl der Schiebebits wird unter Verwendung des in der Anweisung enthaltenen Direktoperanden angegeben oder durch den Inhalt des angegebenen Registers bestimmt. Das Übergabezeichen ist in der Regel an der Durchführung der Verschiebung beteiligtCim Statusregister (SR oder EFLAGS), die das letzte Bit des Operanden enthält, der aus dem Register oder der Speicherstelle gezogen wird.

Vergleichs- und Testbefehle . Der Operandenvergleich wird normalerweise mit der Anweisung durchgeführtCMP , die die Subtraktion von Operanden mit dem Setzen der Werte der Merkmale durchführt N, Z, V, C im Statusregister entsprechend dem Ergebnis. In diesem Fall wird das Ergebnis der Subtraktion nicht gespeichert und die Werte der Operanden ändern sich nicht. Die anschließende Analyse der erhaltenen Merkmalswerte ermöglicht es Ihnen, den relativen Wert zu bestimmen (>,<, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Einige Mikroprozessoren führen einen Testbefehl aus TST , die eine Einzeloperandenvariante der Vergleichsanweisung ist. Wenn dieser Befehl ausgeführt wird, werden die Zeichen gesetzt N, Z nach Vorzeichen und Wert (gleich oder ungleich Null) des adressierten Operanden.

Anweisungen für Bitoperationen . Diese Befehle setzen den Wert des AttributsCim Statusregister entsprechend dem Wert des getesteten BitsMrd im adressierten Operanden. Bei manchen Mikroprozessoren wird entsprechend dem Testergebnis eines Bits ein Vorzeichen gesetztZ. Testbitnummernwird entweder durch den Inhalt des im Befehl angegebenen Registers oder durch einen Direktoperanden gesetzt.

Die Befehle dieser Gruppe implementieren verschiedene Optionen zum Ändern des getesteten Bits BT behält den Wert dieses Bits unverändert.Befehl B T S nach dem Testen setzt Wert Mrd=1 und der Befehl B T C - Bedeutung Mrd=0.Befehl B T C invertiert den Wert von Bit bn nach dem Testen.

Programmverwaltungsoperationen. Zur Steuerung des Programms wird eine große Anzahl von Befehlen verwendet, darunter:

- unbedingte Steuerübertragungsbefehle;

- bedingte Sprungbefehle;

- Befehle zum Organisieren von Programmzyklen;

- Befehle unterbrechen;

- Befehle zum Ändern von Funktionen.

Die bedingungslose Übergabe der Steuerung erfolgt durch den BefehlJMP , die in den Programmzähler geladen wirdPCneuer Inhalt, der die Adresse des nächsten auszuführenden Befehls ist. Diese Adresse wird entweder direkt im Befehl angegebenJMP (direkte Adresse) oder berechnet als Summe der aktuellen InhaltePCund dem im Befehl angegebenen Offset, der eine vorzeichenbehaftete Zahl ist (relative Adressierung). AlsPCdie Adresse des nächsten Programmbefehls enthält, dann setzt die letzte Methode die Sprungadresse, relativ zur nächsten Adresse um eine bestimmte Anzahl von Bytes versetzt. Bei positivem Offset wird auf die nachfolgenden Befehle des Programms übergegangen, bei negativem Offset auf die vorherigen.

Das Unterprogramm wird auch durch unbedingte Steuerübergabe mit dem Befehl aufgerufenANRUF (oder JSR ). Allerdings in diesem Fall vor dem Laden inPC neuen Inhalt, der die Adresse der ersten Anweisung des Unterprogramms angibt, muss dessen aktueller Wert (die Adresse der nächsten Anweisung) gespeichert werden, um nach der Ausführung des Unterprogramms eine Rückkehr zum Hauptprogramm (bzw vorheriges Unterprogramm beim Verschachteln von Unterprogrammen). Bedingte Sprungbefehle (Programmverzweigungen) werden geladenPCneuen Inhalt, wenn bestimmte Bedingungen erfüllt sind, die normalerweise entsprechend dem aktuellen Wert verschiedener Attribute im Statusregister gesetzt werden. Ist die Bedingung nicht erfüllt, wird der nächste Programmbefehl ausgeführt.

Merkmalsverwaltungsbefehle ermöglichen das Schreiben - Lesen des Inhalts des Statusregisters, in dem Merkmale gespeichert sind, sowie das Ändern der Werte einzelner Merkmale. Beispielsweise implementieren Pentium-Prozessoren Befehle LAHF und SAHF , die das Low-Byte, das die Vorzeichen enthält, aus dem Statusregister laden EFLAG zum niederwertigen Byte des Registers EAX und Auffüllen von Low-Byte EFLAGS aus dem Register E AX.. Befehle CLC, STC Setzen Sie die Werte des Transfer-Flags CF=0, CF=1 und den Befehl CMC bewirkt, dass der Wert dieser Funktion invertiert wird. Da Traits den Ablauf der Programmausführung während bedingter Sprünge bestimmen, werden normalerweise Trait-Änderungsanweisungen verwendet, um das Programm zu steuern.

Prozessorsteuerbefehle . Diese Gruppe umfasst Stoppbefehle, keine Operation und eine Reihe von Befehlen, die den Betriebsmodus des Prozessors oder seiner einzelnen Blöcke bestimmen. MannschaftHLT Beendet die Programmausführung und versetzt den Prozessor in einen Haltezustand, der beim Empfang von Unterbrechungs- oder Neustartsignalen verlassen wird ( zurücksetzen). Mannschaft NOP Eine ("leere" Anweisung), die keine Operationen auslöst, wird verwendet, um Programmverzögerungen zu implementieren oder im Programm gebildete Lücken zu füllen.

Spezielle Teams CLI, ST Deaktivieren und aktivieren Sie den Dienst von Interrupt-Anforderungen. Bei Prozessoren Pentium Dazu wird ein Steuerbit (Flag) verwendetWENN im Register EFLAGS.

Viele moderne Mikroprozessoren geben einen Identifikationsbefehl aus, der es dem Benutzer oder anderen Geräten ermöglicht, Informationen über den Prozessortyp zu erhalten, der in einem gegebenen System verwendet wird. Bei Prozessoren Pentuim dafür ist der Befehl da CPUID , während dessen die notwendigen Daten über den Prozessor in die Register eingetragen werden EAX,ebx,ECX,EDX und kann dann vom Benutzer oder dem Betriebssystem gelesen werden.

Abhängig von den vom Prozessor implementierten Betriebsmodi und den spezifizierten Arten von verarbeiteten Daten kann der Satz von ausführbaren Befehlen erheblich erweitert werden.

Einige Prozessoren führen BCD-Arithmetikoperationen durch oder führen spezielle Ergebniskorrekturanweisungen aus, wenn sie solche Zahlen verarbeiten. Viele Hochleistungsprozessoren enthalten FPU - Nummernverarbeitungseinheit c "Gleitkomma".

In einer Reihe moderner Prozessoren ist eine Gruppenverarbeitung mehrerer Ganzzahlen oder Zahlen implementiert. c „Gleitkomma“ mit einem einzigen Befehl nach dem Prinzip SIMD („Single Instruction – Multiple Data “) – „Ein Befehl – ​​viele Daten“. Die gleichzeitige Ausführung von Operationen auf mehreren Operanden erhöht die Leistung des Prozessors bei der Arbeit mit Video- und Audiodaten erheblich. Solche Operationen werden häufig in der Bildverarbeitung, Tonverarbeitung und anderen Anwendungen verwendet. Um diese Operationen auszuführen, werden spezielle Blöcke in die Prozessoren eingeführt, die die entsprechenden Befehlssätze implementieren, die in verschiedenen Prozessortypen ( Pentium, Athlon) bekam den NamenMMX (“ Milti-Media-Erweiterung “) – Multimedia-Erweiterung,SSE(„ Streaming-SIMD-Erweiterung “) – Streaming-SIMD - Verlängerung, “3 DVerlängerung- 3D-Erweiterung.

Ein charakteristisches Merkmal der Prozessoren des Unternehmens Intel , beginnend mit Modell 80286, ist die Prioritätssteuerung beim Zugriff auf Speicher, die bereitgestellt wird, wenn der Prozessor im geschützten virtuellen Adressmodus arbeitet - „ Sicherheitsmodus " (Sicherheitsmodus). Um diesen Modus zu implementieren, werden spezielle Befehlsgruppen verwendet, die dazu dienen, den Speicherschutz gemäß dem akzeptierten Prioritätszugriffsalgorithmus zu organisieren.

Thema 1.4 Assembler-Mnemonik. Befehlsstruktur und Formate. Arten der Adressierung. Mikroprozessor-Befehlssatz

Planen:

1 Assemblersprache. Grundlegendes Konzept

2 Symbole der Assemblersprache

3 Arten von Assembler-Anweisungen

4 Montagerichtlinien

5 Prozessor-Befehlssatz

1 IchAssemblersprache. Grundlegendes Konzept

Assemblerspracheist eine symbolische Darstellung der Maschinensprache. Alle Prozesse in der Maschine auf der untersten Hardwareebene werden nur durch Befehle (Anweisungen) der Maschinensprache gesteuert. Daraus wird deutlich, dass trotz des gebräuchlichen Namens die Assemblersprache für jeden Computertyp unterschiedlich ist.

Ein Programm in Assemblersprache ist eine Sammlung von Speicherblöcken, die aufgerufen werden Speichersegmente. Ein Programm kann aus einem oder mehreren dieser Blocksegmente bestehen. Jedes Segment enthält eine Sammlung von Sprachsätzen, von denen jeder eine separate Programmcodezeile belegt.

Es gibt vier Arten von Assembly-Anweisungen:

1) Befehle oder Anweisungen die symbolische Analoga von Maschinenbefehlen sind. Während des Übersetzungsprozesses werden Assembleranweisungen in die entsprechenden Befehle des Mikroprozessor-Befehlssatzes umgewandelt;

2) Makros -die auf bestimmte Weise formalisierten Sätze des Programmtextes werden während der Sendung durch andere Sätze ersetzt;

3) Richtlinien,Dies sind Anweisungen an den Assembler-Übersetzer, um einige Aktionen auszuführen. Direktiven haben keine Entsprechungen in der Maschinendarstellung;

4) Kommentarzeilen , die beliebige Zeichen enthält, einschließlich Buchstaben des russischen Alphabets. Kommentare werden vom Übersetzer ignoriert.

­ Aufbau des Montageprogramms. Assembler-Syntax.

Die Sätze, aus denen ein Programm besteht, können ein syntaktisches Konstrukt sein, das einem Befehl, Makro, einer Anweisung oder einem Kommentar entspricht. Damit der Assembler-Übersetzer sie erkennt, müssen sie nach bestimmten syntaktischen Regeln gebildet werden. Verwenden Sie dazu am besten eine formale Beschreibung der Syntax der Sprache, wie die Grammatikregeln. Die gebräuchlichsten Arten, eine Programmiersprache wie diese zu beschreiben - Syntaxdiagramme und erweiterte Formen von Backus-Naur. Bequemer für den praktischen Gebrauch Syntaxdiagramme. Beispielsweise kann die Syntax von Anweisungen in Assemblersprache anhand der in den folgenden Abbildungen 10, 11, 12 gezeigten Syntaxdiagramme beschrieben werden.

Abbildung 10 – Assembly-Satzformat


­ Abbildung 11 – Format der Direktiven

­ Abbildung 12 – Format von Befehlen und Makros

Auf diesen Zeichnungen:

­ Markenname- Identifikator, dessen Wert die Adresse des ersten Bytes des Satzes des Quellcodes des Programms ist, den er bezeichnet;

­ Name -eine Kennung, die diese Direktive von anderen gleichnamigen Direktiven unterscheidet. Durch die Verarbeitung einer bestimmten Direktive durch den Assembler können diesem Namen bestimmte Eigenschaften zugeordnet werden;

­ Betriebscode (COP) und Direktive - dies sind mnemonische Symbole für die entsprechende Maschinenanweisung, Makroanweisung oder Compiler-Anweisung;

­ Operanden -Teile eines Befehls, Makros oder einer Assembler-Direktive, die Objekte bezeichnen, an denen Aktionen ausgeführt werden. Assembler-Operanden werden durch Ausdrücke mit numerischen und Textkonstanten, Variablenlabels und Bezeichnern mit Operatorzeichen und einigen reservierten Wörtern beschrieben.

Syntaxdiagramme helfen Suchen und durchlaufen Sie dann den Pfad von der Eingabe des Diagramms (links) zu seiner Ausgabe (rechts). Wenn ein solcher Pfad existiert, dann ist der Satz oder die Konstruktion syntaktisch korrekt. Wenn es keinen solchen Pfad gibt, akzeptiert der Compiler diese Konstruktion nicht.

­ 2 Symbole der Assemblersprache

Erlaubte Zeichen beim Schreiben des Textes von Programmen sind:

1) alle lateinischen Buchstaben: A-Z,a-z. In diesem Fall werden Groß- und Kleinbuchstaben als gleichwertig betrachtet;

2) Zahlen von 0 Vor 9 ;

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

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

Assemblersätze werden gebildet aus Token, die syntaktisch untrennbare Folgen gültiger Sprachzeichen sind, die für den Übersetzer sinnvoll sind.

Token sind:

1) Identifikatoren - Sequenzen gültiger Zeichen, die zur Bezeichnung von Programmobjekten wie Opcodes, Variablennamen und Labelnamen verwendet werden. Die Regel für das Schreiben von Bezeichnern lautet wie folgt: Ein Bezeichner kann aus einem oder mehreren Zeichen bestehen;

2) Zeichenketten - in einfache oder doppelte Anführungszeichen eingeschlossene Zeichenfolgen;

3) ganze Zahlen in einem der folgenden Zahlensysteme : binär, dezimal, hexadezimal. Die Identifizierung von Zahlen beim Schreiben in Assemblerprogrammen erfolgt nach bestimmten Regeln:

4) Dezimalzahlen benötigen keine zusätzlichen Zeichen zu ihrer Kennzeichnung, zB 25 oder 139. Zur Kennzeichnung im Quellcode des Programms binäre Zahlen Es ist notwendig, nach dem Schreiben der in ihrer Zusammensetzung enthaltenen Nullen und Einsen das lateinische „ b“, zum Beispiel 10010101 b.

5) Hexadezimalzahlen haben mehr Konventionen in ihrer Notation:

Erstens bestehen sie aus Zahlen. 0...9 , Klein- und Großbuchstaben des lateinischen Alphabets a,b, c,d,e,f oder EIN,B,C,D,E,F.

Zweitens kann der Übersetzer Schwierigkeiten haben, Hexadezimalzahlen zu erkennen, da sie sowohl aus den Ziffern 0 ... 9 bestehen können (z. B. 190845) als auch mit einem Buchstaben des lateinischen Alphabets beginnen (z. B. ef15). Um dem Übersetzer zu „erklären“, dass das angegebene Lexem keine Dezimalzahl oder ein Bezeichner ist, muss der Programmierer die Hexadezimalzahl extra zuordnen. Schreiben Sie dazu am Ende der Folge von Hexadezimalziffern, aus denen die Hexadezimalzahl besteht, den lateinischen Buchstaben „ h". Dies ist eine Voraussetzung. Wenn eine Hexadezimalzahl mit einem Buchstaben beginnt, wird ihr eine führende Null vorangestellt: 0 ef15 h.

Fast jeder Satz enthält eine Beschreibung des Objekts, an dem oder mit dessen Hilfe eine Aktion ausgeführt wird. Diese Objekte werden aufgerufen Operanden. Sie können wie folgt definiert werden: Operanden- Dies sind Objekte (einige Werte, Register oder Speicherzellen), die von Anweisungen oder Anweisungen beeinflusst werden, oder dies sind Objekte, die die Aktion von Anweisungen oder Anweisungen definieren oder verfeinern.

Folgende Klassifizierung der Operanden ist möglich:

­ konstante oder unmittelbare Operanden;

­ Adressoperanden;

­ verschobene Operanden;

Adresszähler;

­ Registeroperand;

­ Basis- und Indexoperanden;

­ Strukturoperanden;

Aufzeichnungen.

Operanden sind elementare Komponenten, die einen Teil einer Maschinenanweisung bilden und die Objekte bezeichnen, an denen die Operation ausgeführt wird. In einem allgemeineren Fall können Operanden als Komponenten in komplexeren Formationen genannt werden Ausdrücke.

Ausdrücke sind Kombinationen von Operanden und Operatoren als Ganzes betrachtet. Das Ergebnis der Ausdrucksauswertung kann die Adresse einer Speicherzelle oder ein konstanter (absoluter) Wert sein.

­ 3 Arten von Assembler-Anweisungen

Lassen Sie uns die möglichen Typen auflisten Assembler-Aussagen und syntaktische Regeln zur Bildung von Assembler-Ausdrücken:

­ Rechenzeichen;

­ Schichtoperatoren;

­ Vergleichsoperatoren;

­ logische Operatoren;

­ Indexoperator;

­ geben Sie den Override-Operator ein;

­ Segment-Neudefinitionsoperator;

­ Benennungsoperator für Strukturtypen;

­ Operator zum Erhalten der Segmentkomponente der Adresse des Ausdrucks;

­ Ausdrucks-Offset-Get-Operator.

1 Montagerichtlinien

­ Assembler-Direktiven sind:

1) Segmentierungsrichtlinien. Im Laufe der vorherigen Diskussion haben wir alle Grundregeln für das Schreiben von Anweisungen und Operanden in einem Programm in Assemblersprache herausgefunden. Offen bleibt die Frage, wie die Befehlsfolge richtig formatiert werden muss, damit der Übersetzer sie verarbeiten und der Mikroprozessor sie ausführen kann.

Bei der Betrachtung der Architektur des Mikroprozessors haben wir gelernt, dass er sechs Segmentregister hat, durch die er gleichzeitig arbeiten kann:

­ mit einem Codesegment;

­ mit einem Stapelsegment;

­ mit einem Datensegment;

­ mit drei zusätzlichen Datensegmenten.

Physikalisch ist ein Segment ein Speicherbereich, der von Befehlen und (oder) Daten belegt ist, deren Adressen relativ zum Wert im entsprechenden Segmentregister berechnet werden. Syntaxbeschreibung Segment in Assembler ist die in Abbildung 13 gezeigte Konstruktion:


­ Abbildung 13 – Syntaktische Beschreibung des Segments in Assembler

Es ist wichtig zu beachten, dass die Funktionalität eines Segments etwas breiter ist als das einfache Aufteilen des Programms in Code-, Daten- und Stack-Blöcke. Segmentierung ist Teil eines allgemeineren Mechanismus im Zusammenhang mit Konzept der modularen Programmierung. Es beinhaltet die Vereinheitlichung des Entwurfs von Objektmodulen, die vom Compiler erstellt wurden, einschließlich derjenigen aus verschiedenen Programmiersprachen. Dadurch können Sie Programme kombinieren, die in verschiedenen Sprachen geschrieben sind. Für die Implementierung verschiedener Optionen für eine solche Union sind die Operanden in der SEGMENT-Direktive vorgesehen.

2) Steueranweisungen für die Auflistung. Kotierungskontrollanweisungen werden in folgende Gruppen unterteilt:

­ allgemeine Richtlinien zur Börsenkontrolle;

­ Ausgabeanweisungen zum Einfügen von Dateilisten;

­ Ausgabeanweisungen für bedingte Montageblöcke;

­ Ausgabeanweisungen zur Auflistung von Makros;

­ Anweisungen zum Anzeigen von Informationen über Querverweise in der Auflistung;

­ Anweisungen zum Ändern des Listenformats.

2 Prozessor-Befehlssatz

Der Befehlssatz des Prozessors ist in Abbildung 14 dargestellt.

Betrachten Sie die Hauptgruppen von Befehlen.

­ Abbildung 14 – Klassifizierung von Montageanleitungen

Befehle sind:

1 Datenübertragungsbefehle. Diese Befehle nehmen einen sehr wichtigen Platz im Befehlssatz jedes Prozessors ein. Sie erfüllen die folgenden wesentlichen Funktionen:

­ Speichern der Inhalte der internen Register des Prozessors im Speicher;

­ Kopieren von Inhalten von einem Speicherbereich in einen anderen;

­ Schreiben auf E/A-Geräte und Lesen von E/A-Geräten.

Bei einigen Prozessoren werden alle diese Funktionen durch einen einzigen Befehl ausgeführt BEWEGUNG (für Byte-Übertragungen - MOVB ) Nase verschiedene Methoden Operandenadressierung.

In anderen Prozessoren neben der Anweisung BEWEGUNG Es gibt mehrere weitere Befehle, um die aufgeführten Funktionen auszuführen. Zu den Datenübertragungsbefehlen gehören auch Informationsaustauschbefehle (ihre Bezeichnung basiert auf dem Wort Austausch ). Es kann möglich sein, einen Informationsaustausch zwischen internen Registern, zwischen zwei Hälften eines Registers ( TAUSCHEN ) oder zwischen einem Register und einer Speicherstelle.

2 Arithmetische Befehle. Arithmetische Befehle behandeln Operandencodes als numerische Binär- oder BCD-Codes. Diese Befehle können in fünf Hauptgruppen unterteilt werden:

­ Befehle für Operationen mit einem Fixpunkt (Addition, Subtraktion, Multiplikation, Division);

­ Gleitkommabefehle (Addition, Subtraktion, Multiplikation, Division);

­ Bereinigungsbefehle;

­ Inkrement- und Dekrementbefehle;

­ Vergleichsbefehl.

3 Festkommabefehle arbeiten mit Codes in Prozessorregistern oder im Speicher, wie sie es mit normalen Binärcodes tun würden. Anweisungen für Gleitkommaoperationen (Komma) verwenden ein Format zur Darstellung von Zahlen mit einem Exponenten und einer Mantisse (normalerweise belegen diese Zahlen zwei aufeinanderfolgende Speicherplätze). Im modernen leistungsstarke Prozessoren Der Gleitkomma-Befehlssatz ist nicht auf nur vier arithmetische Operationen beschränkt, sondern enthält auch viele andere komplexere Befehle, wie die Berechnung trigonometrischer Funktionen, logarithmischer Funktionen und komplexer Funktionen, die in der Ton- und Bildverarbeitung benötigt werden.

4 Clear-Befehle dienen dazu, einen Nullcode in ein Register oder eine Speicherzelle zu schreiben. Diese Befehle können durch Null-Code-Übertragungsanweisungen ersetzt werden, aber spezielle Löschanweisungen sind normalerweise schneller als Übertragungsanweisungen.

5 Befehle zum Erhöhen (Erhöhen um eins) und Verringern

(Ermäßigungen um eins) sind auch sehr bequem. Sie könnten im Prinzip durch Add-One- oder Subtract-One-Befehle ersetzt werden, aber Inkrement und Dekrement sind schneller als Addieren und Subtrahieren. Diese Anweisungen erfordern einen Eingabeoperanden, der auch ein Ausgabeoperand ist.

6 Der Vergleichsbefehl dient zum Vergleichen zweier Eingangsoperanden. Tatsächlich berechnet er die Differenz dieser beiden Operanden, bildet aber nicht den Ausgangsoperanden, sondern ändert nur die Bits im Prozessorstatusregister basierend auf dem Ergebnis dieser Subtraktion. Der Befehl, der dem Vergleichsbefehl folgt (normalerweise ein Sprungbefehl), analysiert die Bits im Statusregister des Prozessors und führt Aktionen basierend auf ihren Werten aus. Einige Prozessoren stellen Anweisungen zum Kettenvergleich zweier Sequenzen von Operanden im Speicher bereit.

7 Logikbefehle. Logikbefehle führen logische (bitweise) Operationen an Operanden durch, d. h. sie betrachten die Operandencodes nicht als einzelne Zahl, sondern als einen Satz einzelner Bits. Darin unterscheiden sie sich von arithmetischen Befehlen. Logikbefehle führen die folgenden grundlegenden Operationen aus:

­ logisches UND, logisches ODER, Modulo-2-Addition (XOR);

­ logische, arithmetische und zyklische Verschiebungen;

­ Prüfen von Bits und Operanden;

­ Setzen und Löschen von Bits (Flags) des Prozessorstatusregisters ( PSW).

Logikbefehle ermöglichen die bitweise Berechnung grundlegender Logikfunktionen aus zwei Eingangsoperanden. Zusätzlich wird die UND-Operation verwendet, um das Löschen der angegebenen Bits zu erzwingen (als einer der Operanden verwendet dies den Maskencode, in dem die Bits, die gelöscht werden müssen, auf Null gesetzt werden). Die ODER-Operation wird verwendet, um das Setzen der angegebenen Bits zu erzwingen (als einer der Operanden wird der Maskencode verwendet, bei dem die Bits, die auf eins gesetzt werden müssen, gleich eins sind). Die XOR-Operation wird verwendet, um die gegebenen Bits zu invertieren (als einer der Operanden wird der Maskencode verwendet, in dem die zu invertierenden Bits auf Eins gesetzt werden). Befehle benötigen zwei Eingangsoperanden und bilden einen Ausgangsoperanden.

8 Mit den Shift-Befehlen können Sie den Operandencode bitweise nach rechts (zu den niedrigeren Bits) oder nach links (zu den höheren Bits) verschieben. Die Art der Verschiebung (logisch, arithmetisch oder zyklisch) bestimmt, was der neue Wert des höchstwertigen Bits (bei Rechtsverschiebung) oder des niederwertigsten Bits (bei Linksverschiebung) sein wird, und bestimmt auch, ob der alte Wert der höchstwertige ist Bit wird irgendwo gespeichert (bei Verschiebung nach links) oder niedrigstwertiges Bit (bei Verschiebung nach rechts). Rotationsverschiebungen ermöglichen es Ihnen, die Bits des Operandencodes kreisförmig zu verschieben (im Uhrzeigersinn bei einer Verschiebung nach rechts oder gegen den Uhrzeigersinn bei einer Verschiebung nach links). In diesem Fall kann der Schaltring das Carry-Flag enthalten oder nicht. Das Carry-Flag-Bit (falls verwendet) wird auf das höchstwertige Bit für die Linksrotation und das niedrigstwertige Bit für die Rechtsrotation gesetzt. Dementsprechend wird der Wert des Carry-Flag-Bits bei einer zyklischen Linksverschiebung auf das niedrigstwertige Bit und bei einer zyklischen Rechtsverschiebung auf das höchstwertige Bit umgeschrieben.

9 Sprungbefehle. Sprungbefehle dienen dazu, alle Arten von Schleifen, Verzweigungen, Unterprogrammaufrufen usw. zu organisieren, dh sie unterbrechen den sequentiellen Ablauf des Programms. Diese Befehle schreiben einen neuen Wert in das Befehlszählerregister und bewirken dadurch, dass der Prozessor nicht zum nächsten Befehl in der Reihenfolge springt, sondern zu jedem anderen Befehl im Programmspeicher. Einige Sprungbefehle ermöglichen es Ihnen, zu dem Punkt zurückzukehren, von dem aus der Sprung ausgeführt wurde, während andere dies nicht tun. Wenn eine Rückgabe erfolgt, werden die aktuellen Prozessorparameter auf dem Stack gespeichert. Wenn keine Rückgabe erfolgt, werden die aktuellen Prozessorparameter nicht gespeichert.

Sprungbefehle ohne Backtracking werden in zwei Gruppen eingeteilt:

­ Befehle für unbedingte Sprünge;

­ bedingte Sprunganweisungen.

Diese Befehle verwenden die Wörter Branch (Zweig) und Jump (Sprung).

Unbedingte Sprungbefehle bewirken in jedem Fall einen Sprung zu einer neuen Adresse. Sie können einen Sprung zum angegebenen Offset-Wert (vorwärts oder rückwärts) oder zur angegebenen Speicheradresse bewirken. Als Eingangsoperand wird der Offsetwert bzw. neuer Adresswert angegeben.

Bedingte Sprungbefehle bewirken nicht immer einen Sprung, sondern nur dann, wenn die angegebenen Bedingungen erfüllt sind. Solche Bedingungen sind normalerweise die Werte der Flags im Prozessorstatusregister ( PSW ). Das heißt, die Übergangsbedingung ist das Ergebnis der vorherigen Operation, die die Werte der Flags ändert. Insgesamt kann es 4 bis 16 solcher Sprungbedingungen geben Einige Beispiele für bedingte Sprungbefehle:

­ springe wenn gleich Null;

­ springe, wenn nicht Null;

­ springen, wenn es einen Überlauf gibt;

­ springen, wenn kein Überlauf vorhanden ist;

­ springen, wenn größer als Null;

­ Sprung, wenn kleiner oder gleich Null.

Wenn die Übergangsbedingung erfüllt ist, wird ein neuer Wert in das Befehlszählerregister geladen. Wenn die Sprungbedingung nicht erfüllt ist, wird der Befehlszähler einfach inkrementiert und der Prozessor wählt den nächsten Befehl in Folge aus und führt ihn aus.

Speziell zur Prüfung von Sprungbedingungen wird ein Vergleichsbefehl (CMP) verwendet, der einem bedingten Sprungbefehl (oder auch mehreren bedingten Sprungbefehlen) vorangestellt ist. Aber Flags können durch jeden anderen Befehl gesetzt werden, wie zum Beispiel einen Datenübertragungsbefehl, jeden arithmetischen oder logischen Befehl. Beachten Sie, dass die Sprungbefehle selbst die Flags nicht ändern, was Ihnen nur erlaubt, mehrere Sprungbefehle hintereinander zu setzen.

Unter den Sprungbefehlen mit Return nehmen Unterbrechungsbefehle eine Sonderstellung ein. Diese Befehle benötigen als Eingangsoperanden eine Interrupt-Nummer (Vektoradresse).

Fazit:

Die Assemblersprache ist eine symbolische Darstellung der Maschinensprache. Die Assemblersprache für jeden Computertyp ist unterschiedlich. Ein Assemblersprachenprogramm ist eine Sammlung von Speicherblöcken, die als Speichersegmente bezeichnet werden. Jedes Segment enthält eine Sammlung von Sprachsätzen, von denen jeder eine separate Programmcodezeile belegt. Es gibt vier Arten von Assembly-Anweisungen: Befehle oder Anweisungen, Makros, Direktiven, Kommentarzeilen.

Gültige Zeichen beim Schreiben des Textes von Programmen sind alle lateinischen Buchstaben: A-Z,a-z. In diesem Fall werden Groß- und Kleinbuchstaben als gleichwertig betrachtet; Zahlen aus 0 Vor 9 ; Zeichen ? , @ , $ , _ , & ; Trennzeichen , . () < > { } + / * % ! " " ? = # ^ .

Es gelten die folgenden Arten von Assembler-Anweisungen und Syntaxregeln für die Bildung von Assembler-Ausdrücken. arithmetische Operatoren, Verschiebungsoperatoren, Vergleichsoperatoren, logische Operatoren, Indexoperatoren, Typneudefinitionsoperatoren, Segmentneudefinitionsoperatoren, Strukturtypbenennungsoperatoren, Ausdrucksadressen-Segmentkomponenten-Bezugsoperatoren, Ausdrucks-Offset-Bezugsoperatoren.

Das Befehlssystem ist in 8 Hauptgruppen unterteilt.

­ Testfragen:

1 Was ist Assemblersprache?

2 Welche Symbole können verwendet werden, um Befehle in Assembler zu schreiben?

3 Was sind Etiketten und wozu dienen sie?

4 Erklären Sie den Aufbau einer Montageanleitung.

5 Nennen Sie 4 Arten von Assembler-Anweisungen.

NATIONALE UNIVERSITÄT VON USBEKISTAN BENANNT NACH MIRZO ULUGBEK

FAKULTÄT FÜR COMPUTERTECHNOLOGIEN

Zum Thema: Semantische Analyse einer EXE-Datei.

Abgeschlossen:

Taschkent 2003.

Vorwort.

Assemblersprache und Befehlsstruktur.

EXE-Dateistruktur ( semantische Analyse).

Aufbau einer COM-Datei.

Wie das Virus funktioniert und sich verbreitet.

Disassembler.

Programme.

Vorwort

Der Beruf eines Programmierers ist erstaunlich und einzigartig. In unserer Zeit sind Wissenschaft und Leben nicht mehr wegzudenken neueste Technik. Alles, was mit menschlicher Aktivität zusammenhängt, ist ohne Computertechnologie nicht vollständig. Und dies trägt zu seiner hohen Entwicklung und Perfektion bei. Obwohl die Entwicklung von Personal Computern vor nicht allzu langer Zeit begann, wurden in dieser Zeit kolossale Schritte bei Softwareprodukten und mehr unternommen. lange Zeit Diese Produkte werden weit verbreitet sein. Das Gebiet des computerbezogenen Wissens ist explodiert, ebenso wie die damit verbundene Technologie. Wenn wir die kaufmännische Seite nicht berücksichtigen, dann können wir sagen, dass es in diesem Bereich der beruflichen Tätigkeit keine Unbekannten gibt. Viele beschäftigen sich mit der Entwicklung von Programmen nicht aus Profit- oder Verdienstgründen, sondern aus freiem Willen, aus Leidenschaft. Natürlich soll dies die Qualität des Programms nicht beeinträchtigen, und in diesem Geschäft gibt es sozusagen Konkurrenz und Nachfrage nach Qualitätsleistung, z stabile Arbeit und alle modernen Anforderungen erfüllen. Erwähnenswert ist hier auch das Erscheinen von Mikroprozessoren in den 60er Jahren, die eine große Anzahl von Lampensätzen ersetzten. Es gibt einige Arten von Mikroprozessoren, die sich stark voneinander unterscheiden. Diese Mikroprozessoren unterscheiden sich hinsichtlich Bitkapazität und eingebauter Systembefehle voneinander. Die gebräuchlichsten sind: Intel, IBM, Celeron, AMD usw. Alle diese Prozessoren beziehen sich auf die fortschrittliche Prozessorarchitektur von Intel. Die Verbreitung von Mikrocomputern hat aus zwei Hauptgründen zu einem Umdenken in der Einstellung zur Assemblersprache geführt. Erstens benötigen in Assemblersprache geschriebene Programme erheblich weniger Speicher und Laufzeit. Zweitens vermittelt die Kenntnis der Assemblersprache und des daraus resultierenden Maschinencodes ein Verständnis der Maschinenarchitektur, das beim Arbeiten in einer Hochsprache kaum gegeben ist. Obwohl die meisten Software-Profis in Hochsprachen wie Pascal, C oder Delphi entwickeln, ist das Schreiben von Programmen am leistungsfähigsten und effizientesten Software ganz oder teilweise in Assemblersprache geschrieben. Hochsprachen wurden entwickelt, um die speziellen technischen Besonderheiten bestimmter Computer zu umgehen. Und die Assemblersprache wiederum ist auf die spezifischen Besonderheiten des Prozessors ausgelegt. Um ein Assemblersprachenprogramm für einen bestimmten Computer zu schreiben, muss man daher dessen Architektur kennen. Heutzutage ist der Blick auf die Hauptsache Softwareprodukt ist eine EXE-Datei. Angesichts der positiven Aspekte davon kann sich der Autor des Programms seiner Unverletzlichkeit sicher sein. Aber oft ist dies weit davon entfernt. Es gibt auch einen Disassembler. Mit Hilfe eines Disassemblers können Sie Interrupts und Programmcodes herausfinden. Für jemanden, der sich mit Assembler auskennt, wird es nicht schwierig sein, das gesamte Programm nach seinem Geschmack umzugestalten. Vielleicht kommt daher das unlösbarste Problem – der Virus. Warum schreiben Menschen einen Virus? Manche stellen diese Frage überrascht, manche ärgerlich, aber dennoch gibt es Menschen, die sich für diese Aufgabe nicht aus Schadenssicht, sondern aus Interesse an der Systemprogrammierung interessieren. Viren werden aus verschiedenen Gründen geschrieben. Einige mögen Systemaufrufe, andere verbessern ihre Kenntnisse in Assembler. Ich werde versuchen, das alles in meinem zu erklären Seminararbeit. Es sagt auch nicht nur etwas über die Struktur der EXE-Datei aus, sondern auch über die Assemblersprache.

^ Assemblersprache.

Es ist interessant, von der Zeit des Erscheinens der ersten Computer bis zum heutigen Tag den Wandel der Vorstellungen über Assemblersprache unter Programmierern zu verfolgen.

Assembler war einmal eine Sprache, ohne deren Wissen es unmöglich war, einen Computer dazu zu bringen, irgendetwas Nützliches zu tun. Allmählich änderte sich die Situation. Bequemere Kommunikationsmittel mit einem Computer erschienen. Aber im Gegensatz zu anderen Sprachen starb Assembler nicht, außerdem konnte er dies im Prinzip nicht tun. Wieso den? Auf der Suche nach einer Antwort werden wir versuchen zu verstehen, was Assemblersprache im Allgemeinen ist.

Kurz gesagt, Assemblersprache ist eine symbolische Darstellung der Maschinensprache. Alle Prozesse in der Maschine auf der untersten Hardwareebene werden nur durch Befehle (Anweisungen) der Maschinensprache gesteuert. Daraus wird deutlich, dass trotz des gebräuchlichen Namens die Assemblersprache für jeden Computertyp unterschiedlich ist. Dies gilt auch Aussehen in Assembler geschriebene Programme und die Ideen, die diese Sprache widerspiegelt.

Ohne Assembler-Kenntnisse ist es unmöglich, hardwarebezogene Probleme (oder sogar hardwarebezogene Probleme, wie etwa die Geschwindigkeitssteigerung eines Programms) wirklich zu lösen.

Ein Programmierer oder jeder andere Benutzer kann alle High-Level-Tools verwenden, bis hin zu Programmen zum Erstellen virtueller Welten, und vielleicht nicht einmal ahnen, dass der Computer tatsächlich nicht die Befehle der Sprache ausführt, in der sein Programm geschrieben ist, sondern deren transformierte Darstellung in Form langweiliger und langweiliger Befehlsfolgen einer völlig anderen Sprache - der Maschinensprache. Stellen wir uns nun vor, dass ein solcher Benutzer ein nicht standardmäßiges Problem hat oder einfach etwas schief gelaufen ist. Beispielsweise muss sein Programm mit einem ungewöhnlichen Gerät funktionieren oder andere Aktionen ausführen, die Kenntnisse über die Prinzipien der Computerhardware erfordern. Egal wie schlau ein Programmierer ist, egal wie gut die Sprache ist, in der er sein wunderbares Programm geschrieben hat, ohne Assembler-Kenntnisse kommt er nicht aus. Und es ist kein Zufall, dass fast alle Compiler von Hochsprachen Mittel enthalten, um ihre Module mit Modulen in Assembler zu verbinden oder den Zugriff auf die Assembler-Programmierebene zu unterstützen.

Natürlich ist die Zeit der Computerwagen schon vorbei. Wie das Sprichwort sagt, kann man die Unermesslichkeit nicht umarmen. Aber es gibt etwas Gemeinsames, eine Art Fundament, auf dem jede ernsthafte Computerausbildung aufbaut. Dies ist Wissen über die Prinzipien des Computerbetriebs, seiner Architektur und Assemblersprache als Spiegelung und Verkörperung dieses Wissens.

Ein typischer moderner Computer (i486- oder Pentium-basiert) besteht aus den folgenden Komponenten (Abbildung 1).

Reis. 1. Computer und Peripheriegeräte

Reis. 2. Blockschaltbild eines Personal Computers

Aus der Abbildung (Abbildung 1) ist ersichtlich, dass der Computer aus mehreren physikalischen Geräten besteht, von denen jedes mit einer Einheit verbunden ist, die als Systemeinheit bezeichnet wird. Logischerweise spielt es die Rolle eines koordinierenden Geräts. Werfen wir einen Blick hinein Systemblock(Sie müssen nicht versuchen, in den Monitor zu gelangen - dort ist nichts Interessantes, außerdem ist es gefährlich): Wir öffnen das Gehäuse und sehen einige Bretter, Blöcke, Verbindungsdrähte. Um ihre Funktionalität zu verstehen, schauen wir uns an Blockdiagramm typischer Computer (Abb. 2). Sie erhebt keinen Anspruch auf absolute Genauigkeit und soll nur den Zweck, die Verbindung und die typische Zusammensetzung der Elemente eines modernen Personal Computers zeigen.

Betrachten wir das Diagramm in Abb. 2 in einem etwas unkonventionellen Stil.
Es liegt in der Natur des Menschen, bei der Begegnung mit etwas Neuem nach Assoziationen zu suchen, die ihm helfen können, das Unbekannte zu erkennen. Welche Assoziationen weckt der Computer? Für mich zum Beispiel wird der Computer oft mit dem Menschen selbst in Verbindung gebracht. Wieso den?

Eine Person, die irgendwo in den Tiefen ihrer selbst einen Computer erschuf, dachte, dass sie etwas Ähnliches wie sich selbst erschuf. Der Computer hat Wahrnehmungsorgane für Informationen von der Außenwelt - das sind Tastatur, Maus, Magnetplattenlaufwerke. Auf Abb. 2 Diese Organe befinden sich rechts von den Systembussen. Der Computer verfügt über Organe, die die empfangenen Informationen „verdauen“ - dies ist der Zentralprozessor und Rom. Und schließlich hat der Computer Sprechorgane, die die Ergebnisse der Verarbeitung ausgeben. Dies sind auch einige der Geräte auf der rechten Seite.

Moderne Computer sind natürlich alles andere als menschlich. Sie können mit Wesen verglichen werden, die auf der Ebene einer großen, aber begrenzten Menge unbedingter Reflexe mit der Außenwelt interagieren.
Diese Reihe von Reflexen bildet ein System von Maschinenanweisungen. Egal auf welchem ​​Niveau Sie mit einem Computer kommunizieren, am Ende läuft alles auf eine langweilige und eintönige Abfolge von Maschinenbefehlen hinaus.
Jeder Maschinenbefehl ist eine Art Reiz zur Erregung dieses oder jenes unbedingten Reflexes. Die Reaktion auf diesen Reiz ist immer eindeutig und in Form eines Mikroprogramms im Mikrobefehlsblock „fest verdrahtet“. Dieses Mikroprogramm implementiert auch Aktionen zur Implementierung eines Maschinenbefehls, jedoch bereits auf der Ebene von Signalen, die bestimmten Computerlogikschaltungen zugeführt werden, wodurch verschiedene Computersubsysteme gesteuert werden. Dies ist das sogenannte Prinzip der Mikroprogrammsteuerung.

Um die Analogie mit einer Person fortzusetzen, stellen wir fest, dass viele Betriebssysteme, Compiler für Hunderte von Programmiersprachen erfunden wurden, damit ein Computer richtig essen kann usw. Aber alle von ihnen sind eigentlich nur ein Gericht, auf dem Essen (Programme) wird nach bestimmten Regeln Magen (Computer) geliefert. Nur der Magen eines Computers liebt diätetische, eintönige Kost – gib ihm strukturierte Informationen, in Form von streng organisierten Folgen von Nullen und Einsen, deren Kombinationen die Maschinensprache ausmachen.

Somit versteht der Computer, der äußerlich ein Polyglott ist, nur eine Sprache - die Sprache der Maschinenbefehle. Um mit einem Computer zu kommunizieren und zu arbeiten, ist es natürlich nicht erforderlich, diese Sprache zu beherrschen, aber fast jeder professionelle Programmierer steht früher oder später vor der Notwendigkeit, sie zu lernen. Glücklicherweise muss der Programmierer nicht versuchen, die Bedeutung verschiedener Kombinationen von Binärzahlen herauszufinden, da Programmierer bereits in den 50er Jahren damit begannen, das symbolische Analogon der Maschinensprache zum Programmieren zu verwenden, das als Assemblersprache bezeichnet wurde. Diese Sprache spiegelt alle Merkmale der Maschinensprache genau wider. Aus diesem Grund ist die Assemblersprache im Gegensatz zu Hochsprachen für jeden Computertyp unterschiedlich.

Aus dem Vorhergehenden können wir schließen, dass, da die Assemblersprache für den Computer „nativ“ ist, das effizienteste Programm nur darin geschrieben werden kann (vorausgesetzt, es wird von einem qualifizierten Programmierer geschrieben). Hier gibt es ein kleines „Aber“: Dies ist ein sehr mühsamer Prozess, der viel Aufmerksamkeit und praktische Erfahrung erfordert. In Wirklichkeit schreibt Assembler also hauptsächlich Programme, die ein effizientes Arbeiten mit der Hardware gewährleisten sollen. Manchmal werden kritische Teile des Programms in Bezug auf Ausführungszeit oder Speicherverbrauch in Assembler geschrieben. Anschließend werden sie in Form von Unterprogrammen erstellt und mit Code in einer Hochsprache kombiniert.

Es ist sinnvoll, mit dem Erlernen der Assemblersprache eines beliebigen Computers erst dann zu beginnen, wenn Sie herausgefunden haben, welcher Teil des Computers noch sichtbar und für die Programmierung in dieser Sprache verfügbar ist. Dies ist das sogenannte Computerprogrammmodell, zu dem das Mikroprozessorprogrammmodell gehört, das 32 Register enthält, die dem Programmierer mehr oder weniger zur Verfügung stehen.

Diese Register lassen sich in zwei große Gruppen einteilen:

^16 benutzerdefinierte Register;

16 Systemregister.

Programme in Assemblersprache verwenden Register sehr stark. Die meisten Register haben einen bestimmten funktionalen Zweck.

Wie der Name schon sagt, werden Benutzerregister aufgerufen, weil der Programmierer sie beim Schreiben seiner Programme verwenden kann. Zu diesen Registern gehören (Abb. 3):

Acht 32-Bit-Register, die von Programmierern zum Speichern von Daten und Adressen verwendet werden können (auch Universalregister (RON) genannt):

sechs Segmentregister: cs, ds, ss, es, fs, gs;

Status- und Steuerregister:

Flaggen registrieren Flaggen/Flags;

eip/ip-Befehlszeigerregister.

Reis. 3. Benutzerregister von i486- und Pentium-Mikroprozessoren

Warum werden viele dieser Register mit einem Schrägstrich angezeigt? Nein, das sind keine unterschiedlichen Register – sie sind Teile eines großen 32-Bit-Registers. Sie können im Programm als separate Objekte verwendet werden. Dies geschah, um die Lauffähigkeit von Programmen sicherzustellen, die für die jüngeren 16-Bit-Mikroprozessormodelle von Intel geschrieben wurden, beginnend mit dem i8086. Die i486- und Pentium-Mikroprozessoren haben meistens 32-Bit-Register. Ihre Anzahl, mit Ausnahme der Segmentregister, ist die gleiche wie die des i8086, aber die Dimension ist größer, was sich in ihren Bezeichnungen widerspiegelt - sie haben
Präfix e (Erweitert).

^ Allzweckregister
Alle Register dieser Gruppe erlauben den Zugriff auf ihre „unteren“ Teile (siehe Abb. 3). Beachten Sie beim Betrachten dieser Abbildung, dass nur die unteren 16- und 8-Bit-Teile dieser Register für die Selbstadressierung verwendet werden können. Die oberen 16 Bit dieser Register stehen nicht als eigenständige Objekte zur Verfügung. Dies geschieht, wie oben erwähnt, aus Gründen der Kompatibilität mit den jüngeren 16-Bit-Mikroprozessormodellen von Intel.

Lassen Sie uns die Register auflisten, die zur Gruppe der Mehrzweckregister gehören. Da sich diese Register physisch im Mikroprozessor innerhalb der arithmetischen Logikeinheit (ALU) befinden, werden sie auch als ALU-Register bezeichnet:

eax/ax/ah/al (Akkumulatorregister) - Akkumulator.
Wird zum Speichern von Zwischendaten verwendet. In einigen Befehlen ist die Verwendung dieses Registers obligatorisch;

ebx/bx/bh/bl (Basisregister) - Basisregister.
Wird verwendet, um die Basisadresse eines Objekts im Speicher zu speichern;

ecx/cx/ch/cl (Zählregister) - Zählerregister.
Es wird in Befehlen verwendet, die einige sich wiederholende Aktionen ausführen. Seine Verwendung ist oft implizit und versteckt im Algorithmus des entsprechenden Befehls.
Beispielsweise analysiert der Schleifenorganisationsbefehl zusätzlich zum Übertragen der Steuerung an einen Befehl, der sich an einer bestimmten Adresse befindet, den Wert des ecx/cx-Registers und dekrementiert ihn um eins;

edx/dx/dh/dl (Datenregister) - Datenregister.
Genau wie das eax/ax/ah/al-Register speichert es Zwischendaten. Einige Befehle erfordern seine Verwendung; bei einigen Befehlen geschieht dies implizit.

Die folgenden zwei Register werden verwendet, um die sogenannten Kettenoperationen zu unterstützen, d. h. Operationen, die nacheinander Ketten von Elementen verarbeiten, die jeweils 32, 16 oder 8 Bit lang sein können:

esi/si (Quellindexregister) - Quellindex.
Dieses Register enthält bei Kettenoperationen die aktuelle Adresse des Elements in der Quellkette;

edi/di (Destination Index register) - Index des Empfängers (Empfänger).
Dieses Register enthält bei Kettenoperationen die aktuelle Adresse in der Zielkette.

In der Architektur des Mikroprozessors auf Hardware- und Softwareebene wird eine solche Datenstruktur wie ein Stack unterstützt. Um mit dem Stack zu arbeiten, gibt es im Mikroprozessor-Befehlssystem spezielle Befehle, und im Mikroprozessor-Softwaremodell gibt es dafür spezielle Register:

esp/sp (Stapelzeigerregister) - Stapelzeigerregister.
Enthält einen Zeiger auf den Stapelanfang im aktuellen Stapelsegment.

ebp/bp (Basiszeigerregister) – Stack-Frame-Basiszeigerregister.
Entwickelt, um den wahlfreien Zugriff auf Daten innerhalb des Stacks zu organisieren.

Ein Stack ist ein Programmbereich zur temporären Speicherung beliebiger Daten. Natürlich können auch Daten im Datensegment gespeichert werden, aber in diesem Fall muss für jede temporär gespeicherte Daten eine separate benannte Speicherzelle erstellt werden, was die Größe des Programms und die Anzahl der verwendeten Namen erhöht. Der Vorteil des Stacks besteht darin, dass sein Bereich wiederverwendet wird und das Speichern von Daten auf dem Stack und das Abrufen von Daten von dort mit effizienten Push- und Pop-Befehlen ohne Angabe von Namen erfolgt.
Der Stack wird beispielsweise traditionell verwendet, um den Inhalt der vom Programm verwendeten Register zu speichern, bevor eine Subroutine aufgerufen wird, die wiederum die Prozessorregister "für ihre eigenen Zwecke" verwendet. Die ursprünglichen Inhalte der Register werden bei der Rückkehr von der Subroutine aus dem Stapel entleert. Eine andere gängige Technik besteht darin, die erforderlichen Parameter über den Stapel an eine Unterroutine zu übergeben. Die Subroutine, die weiß, in welcher Reihenfolge die Parameter auf dem Stack platziert sind, kann sie von dort nehmen und sie bei ihrer Ausführung verwenden. Unterscheidungsmerkmal Stack ist eine Art Sampling-Reihenfolge der darin enthaltenen Daten: Auf dem Stack ist immer nur das oberste Element verfügbar, d.h. das letzte Element, das auf den Stack geladen wurde. Wenn Sie das oberste Element aus dem Stapel ziehen, wird das nächste Element verfügbar. Die Elemente des Stacks befinden sich in dem für den Stack zugewiesenen Speicherbereich, beginnend mit dem Boden des Stacks (dh von seiner maximalen Adresse) bis zu sukzessive abnehmenden Adressen. Die Adresse des obersten zugänglichen Elements wird im Stapelzeigerregister SP gespeichert. Wie jeder andere Bereich des Programmspeichers muss der Stack in einem Segment enthalten sein oder ein separates Segment bilden. In jedem Fall wird die Segmentadresse dieses Segments in das Segmentstapelregister SS gestellt. Somit beschreibt ein Registerpaar SS:SP die Adresse einer verfügbaren Stapelzelle: SS speichert die Segmentadresse des Stapels und SP speichert den Offset der letzten auf dem Stapel gespeicherten Daten (Fig. 4, a). Beachten wir, dass der Stapelzeiger SP im Anfangszustand auf eine Zelle zeigt, die unter dem Boden des Stapels liegt und nicht darin enthalten ist.

Abb. 4. Stapelorganisation: a - Anfangszustand, b - nach dem Laden eines Elements (in diesem Beispiel der Inhalt des AX-Registers), c - nach dem Laden des zweiten Elements (Inhalt des DS-Registers), d - nach dem Entladen eines Elements element, e - nach dem Entladen von zwei Elementen und Rückkehr in den ursprünglichen Zustand.

Das Laden auf den Stack erfolgt durch einen speziellen Push-Stack-Befehl. Dieser Befehl dekrementiert zuerst den Inhalt des Stapelzeigers um 2 und platziert dann den Operanden an der Adresse in SP. Wenn wir beispielsweise den Inhalt des AX-Registers temporär auf dem Stack speichern wollen, sollten wir den Befehl ausführen

Der Stapel geht in den in Abb. 1.10, b. Es ist zu erkennen, dass der Stapelzeiger um zwei Bytes nach oben (in Richtung niedrigerer Adressen) verschoben wird und der im Push-Befehl angegebene Operand an diese Adresse geschrieben wird. Der folgende Befehl zum Laden auf den Stack beispielsweise

bewegt den Stapel in den in Abb. 1.10, c. Der Stapel enthält nun zwei Elemente, wobei nur auf das oberste zugegriffen wird, auf das der Stapelzeiger SP zeigt. Wenn wir nach einiger Zeit den ursprünglichen Inhalt der auf dem Stack gespeicherten Register wiederherstellen müssen, müssen wir die Pop-Befehle (pop) vom Stack ausführen:

Pop-DS
Pop-AX

Wie groß soll der Stack sein? Es hängt davon ab, wie intensiv es im Programm verwendet wird. Wenn Sie beispielsweise planen, ein Array von 10.000 Byte auf dem Stack zu speichern, muss der Stack mindestens so groß sein. Zu beachten ist, dass der Stack in einigen Fällen automatisch vom System verwendet wird, insbesondere bei der Ausführung des Interrupt-Befehls int 21h. Mit diesem Befehl schiebt der Prozessor zuerst die Rücksprungadresse auf den Stapel, und dann schiebt DOS die Inhalte der Register und andere Informationen bezüglich des unterbrochenen Programms dorthin. Selbst wenn das Programm den Stack überhaupt nicht verwendet, muss er daher immer noch im Programm vorhanden sein und eine Größe von mindestens mehreren zehn Wörtern haben. In unserem ersten Beispiel legen wir 128 Wörter auf den Stapel, was definitiv ausreicht.

^ Struktur des Assembly-Programms

Ein Assemblersprachenprogramm ist eine Sammlung von Speicherblöcken, die als Speichersegmente bezeichnet werden. Ein Programm kann aus einem oder mehreren dieser Blocksegmente bestehen. Jedes Segment enthält eine Sammlung von Sprachsätzen, von denen jeder eine separate Programmcodezeile belegt.

Es gibt vier Arten von Assembly-Anweisungen:

Befehle oder Anweisungen, die symbolische Entsprechungen von Maschinenanweisungen sind. Während des Übersetzungsprozesses werden Assembleranweisungen in die entsprechenden Befehle des Mikroprozessor-Befehlssatzes umgewandelt;

Makrobefehle - Sätze des Programmtextes, die auf bestimmte Weise gestaltet sind und bei der Übersetzung durch andere Sätze ersetzt werden;

Direktiven, die den Assembler-Compiler anweisen, eine Aktion auszuführen. Direktiven haben keine Entsprechungen in der Maschinendarstellung;

Kommentarzeilen, die beliebige Zeichen enthalten, einschließlich Buchstaben des russischen Alphabets. Kommentare werden vom Übersetzer ignoriert.

^ Syntax der Assemblersprache

Die Sätze, aus denen ein Programm besteht, können ein syntaktisches Konstrukt sein, das einem Befehl, Makro, einer Anweisung oder einem Kommentar entspricht. Damit der Assembler-Übersetzer sie erkennt, müssen sie nach bestimmten syntaktischen Regeln gebildet werden. Verwenden Sie dazu am besten eine formale Beschreibung der Syntax der Sprache, wie die Grammatikregeln. Die gebräuchlichsten Arten, eine Programmiersprache auf diese Weise zu beschreiben, sind Syntaxdiagramme und erweiterte Backus-Naur-Formen. Für den praktischen Gebrauch sind Syntaxdiagramme bequemer. Beispielsweise kann die Syntax von Anweisungen in Assemblersprache unter Verwendung der in den folgenden Abbildungen gezeigten Syntaxdiagramme beschrieben werden.

Reis. 5. Assembler-Satzformat

Reis. 6. Formatanweisungen

Reis. 7. Format von Befehlen und Makros

Auf diesen Zeichnungen:

Labelname – ein Identifizierer, dessen Wert die Adresse des ersten Bytes des Programmquellcodesatzes ist, den er bezeichnet;

name - ein Bezeichner, der diese Direktive von anderen Direktiven mit demselben Namen unterscheidet. Durch die Verarbeitung einer bestimmten Direktive durch den Assembler können diesem Namen bestimmte Eigenschaften zugeordnet werden;

Operationscode (COP) und Direktive sind mnemotechnische Bezeichnungen des entsprechenden Maschinenbefehls, Makrobefehls oder Übersetzerbefehls;

Operanden - Teile der Befehls-, Makro- oder Assembler-Direktiven, die Objekte bezeichnen, an denen Operationen ausgeführt werden. Assembler-Operanden werden durch Ausdrücke mit numerischen und Textkonstanten, Variablenlabels und Bezeichnern mit Operatorzeichen und einigen reservierten Wörtern beschrieben.

^ Wie verwende ich Syntaxdiagramme? Es ist sehr einfach: Alles, was Sie tun müssen, ist, den Pfad von der Eingabe des Diagramms (links) zu seiner Ausgabe (rechts) zu finden und ihm dann zu folgen. Wenn ein solcher Pfad existiert, dann ist der Satz oder die Konstruktion syntaktisch korrekt. Wenn es keinen solchen Pfad gibt, akzeptiert der Compiler diese Konstruktion nicht. Achten Sie bei der Arbeit mit Syntaxdiagrammen auf die durch die Pfeile angegebene Traversierungsrichtung, da es unter den Pfaden auch solche geben kann, denen von rechts nach links gefolgt werden kann. Tatsächlich spiegeln syntaktische Diagramme die Logik des Übersetzers wider, wenn er die Eingabesätze des Programms parst.

Erlaubte Zeichen beim Schreiben des Textes von Programmen sind:

Alle lateinischen Buchstaben: A-Z, a-z. In diesem Fall werden Groß- und Kleinbuchstaben als gleichwertig betrachtet;

Zahlen von 0 bis 9;

Zeichen?, @, $, _, &;

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

Assembler-Sätze werden aus Lexemen gebildet, die syntaktisch untrennbare Folgen gültiger Sprachsymbole sind, die für den Übersetzer sinnvoll sind.

Die Token sind:

Bezeichner sind Folgen gültiger Zeichen, die zur Bezeichnung von Programmobjekten wie Opcodes, Variablennamen und Labelnamen verwendet werden. Die Regel für das Schreiben von Bezeichnern lautet wie folgt: Ein Bezeichner kann aus einem oder mehreren Zeichen bestehen. Als Zeichen können Sie Buchstaben des lateinischen Alphabets, Zahlen und einige verwenden spezielle Charaktere- _, ?, $, @. Ein Bezeichner darf nicht mit einer Ziffer beginnen. Die Länge des Bezeichners kann bis zu 255 Zeichen betragen, wobei der Übersetzer nur die ersten 32 Zeichen akzeptiert und den Rest ignoriert. Über die Option können Sie die Länge möglicher Bezeichner anpassen Befehlszeile mv. Außerdem ist es möglich, den Übersetzer anzuweisen, zwischen Groß- und Kleinbuchstaben zu unterscheiden oder deren Unterschied zu ignorieren (was standardmäßig der Fall ist).

^ Befehle in Assemblersprache.

Assembler-Befehle offenbaren die Fähigkeit, ihre Anforderungen an den Computer zu übertragen, den Mechanismus zur Übertragung der Kontrolle im Programm (Schleifen und Sprünge) für logische Vergleiche und Programmorganisation. Allerdings sind Programmieraufgaben selten so einfach. Die meisten Programme enthalten eine Reihe von Schleifen, in denen mehrere Anweisungen wiederholt werden, bis eine bestimmte Anforderung erreicht ist, und verschiedene Überprüfungen, um zu bestimmen, welche der mehreren Aktionen auszuführen ist. Einige Befehle können die Steuerung übertragen, indem sie die normale Schrittfolge ändern, indem sie den Versatzwert im Befehlszeiger direkt ändern. Wie bereits erwähnt, gibt es verschiedene Befehle für verschiedene Prozessoren, aber wir werden einige Befehle für die Prozessoren 80186, 80286 und 80386 betrachten.

Um den Status der Flags nach Ausführung eines bestimmten Befehls zu beschreiben, verwenden wir eine Auswahl aus der Tabelle, die die Struktur des Flag-Registers eflags widerspiegelt:

Die unterste Zeile dieser Tabelle listet die Werte der Flags auf, nachdem der Befehl ausgeführt wurde. In diesem Fall werden die folgenden Notationen verwendet:

1 - nach Ausführung des Befehls wird das Flag gesetzt (gleich 1);

0 - nach Ausführung des Befehls wird das Flag zurückgesetzt (gleich 0);

r - der Wert des Flags hängt vom Ergebnis des Befehls ab;

Nach Ausführung des Befehls ist das Flag undefiniert;

Leerzeichen - nach Ausführung des Befehls ändert sich das Flag nicht;

Zur Darstellung von Operanden in Syntaxdiagrammen wird folgende Notation verwendet:

r8, r16, r32 - Operand in einem der Register der Größe Byte, Wort oder Doppelwort;

m8, m16, m32, m48 - Operand in Speichergröße von Bytes, Wort, Doppelwort oder 48 Bit;

i8, i16, i32 - unmittelbarer Operand der Größe Byte, Wort oder Doppelwort;

a8, a16, a32 - relative Adresse (Offset) im Codesegment.

Befehle (in alphabetischer Reihenfolge):

*Diese Befehle werden ausführlich beschrieben.

HINZUFÜGEN
(Zusatz)

Zusatz

^ Befehlsübersicht:

Ziel, Quelle hinzufügen

Zweck: Addition von zwei Quell- und Zieloperanden der Dimensionen Byte, Wort oder Doppelwort.

Arbeitsalgorithmus:

fügen Sie die Quell- und Zieloperanden hinzu;

schreibe das Ergebnis der Addition in den Empfänger;

Fahnen setzen.

Status der Flags nach der Befehlsausführung:

Anwendung:
Der add-Befehl wird verwendet, um zwei ganzzahlige Operanden zu addieren. Das Ergebnis der Addition wird an die Adresse des ersten Operanden gestellt. Wenn das Ergebnis der Addition die Grenzen des Zieloperanden überschreitet (es kommt zu einem Überlauf), sollte dieser Situation Rechnung getragen werden, indem das cf-Flag analysiert und dann möglicherweise das adc-Kommando verwendet wird. Addieren wir zum Beispiel die Werte in Register ax und Speicherbereich ch. Beim Hinzufügen sollten Sie die Möglichkeit eines Überlaufs berücksichtigen.

Register plus Register oder Speicher:

|000000dw|modregr/rm|

Register AX (AL) plus Sofortwert:

|0000010w|--data--|data if w=1|

Register oder Speicher plus Sofortwert:

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

ANRUF
(ANRUF)

Aufrufen einer Prozedur oder Aufgabe

^ Befehlsübersicht:

Zweck:

Übergabe der Steuerung an eine nahe oder ferne Prozedur mit Speichern der Adresse des Rückkehrpunkts auf dem Stapel;

Aufgabenwechsel.

Arbeitsalgorithmus:
bestimmt durch den Operandentyp:

Das Etikett ist nahe – der Inhalt des eip/ip-Befehlszeigers wird auf den Stapel geschoben und ein neuer Adresswert, der dem Etikett entspricht, wird in dasselbe Register geladen;

Far label – Inhalte des eip/ip- und cs-Befehlszeigers werden auf den Stack geschoben. Dann werden die neuen Adresswerte, die der fernen Markierung entsprechen, in dieselben Register geladen;

R16, 32 oder m16, 32 – definieren ein Register oder eine Speicherzelle, die Offsets im aktuellen Befehlssegment enthält, wo die Steuerung übertragen wird. Wenn die Steuerung übertragen wird, wird der Inhalt des eip/ip-Befehlszeigers auf den Stapel geschoben;

Speicherzeiger - definiert eine Speicherstelle, die einen 4- oder 6-Byte-Zeiger auf die aufgerufene Prozedur enthält. Die Struktur eines solchen Zeigers ist 2+2 oder 2+4 Bytes. Die Interpretation eines solchen Zeigers hängt von der Betriebsart des Mikroprozessors ab:

^ Zustand der Flags nach Befehlsausführung (außer Taskwechsel):

Die Befehlsausführung wirkt sich nicht auf Flags aus

Beim Umschalten einer Task werden die Werte der Flags gemäß den Informationen über das eflags-Register im TSS-Statussegment der Task geändert, auf die umgeschaltet wird.
Anwendung:
Mit dem Aufrufbefehl können Sie eine flexible und multivariate Übergabe der Steuerung an ein Unterprogramm organisieren, während die Adresse des Rückkehrpunkts beibehalten wird.

Objektcode (vier Formate):

Direkte Adressierung in einem Segment:

|11101000|Anzeige-niedrig|Diep-hoch|

Indirekte Adressierung in einem Segment:

|11111111|mod010r/m|

Indirekte Adressierung zwischen Segmenten:

|11111111|mod011r/m|

Direkte Adressierung zwischen Segmenten:

|10011010|Offset-low|Offset-high|seg-low|seg-high|

CMP
(Operanden vergleichen)

Operandenvergleich

^ Befehlsübersicht:

cmp Operand1, Operand2

Zweck: Vergleich zweier Operanden.

Arbeitsalgorithmus:

Subtraktion durchführen (operand1-operand2);

je nach Ergebnis Flags setzen, operand1 und operand2 nicht ändern (also das Ergebnis nicht speichern).

Anwendung:
Diese Anweisung wird verwendet, um zwei Operanden durch Subtraktion zu vergleichen, während die Operanden nicht geändert werden. Flags werden als Ergebnis der Befehlsausführung gesetzt. Der cmp-Befehl wird mit den bedingten Sprungbefehlen und dem Byte-nach-Wert-setzen-Befehl setcc verwendet.

Objektcode (drei Formate):

Register oder registrierter Speicher:

|001110dw|modreg/m|

Sofortwert mit Register AX (AL):

|0011110w|--data--|data if w=1|

Sofortwert mit Register oder Speicher:

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

DEZ
(Operand um 1 verringern)

Operandendekrement um eins

^ Befehlsübersicht:

dec-Operand

Zweck: Verringern Sie den Wert des Operanden im Speicher oder Register um 1.

Arbeitsalgorithmus:
die Anweisung subtrahiert 1 vom Operanden. Status der Flags nach der Befehlsausführung:

Anwendung:
Der dec-Befehl wird verwendet, um den Wert eines Bytes, Wortes, Doppelwortes im Speicher oder Register um eins zu dekrementieren. Beachten Sie, dass der Befehl das cf-Flag nicht beeinflusst.

Register: |01001reg|

^ Register oder Speicher: |1111111w|mod001r/m|

DIV
(TEILEN ohne Vorzeichen)

Teilung unsigniert

Befehlsschema:

div-Teiler

Zweck: Durchführen einer Divisionsoperation an zwei binären vorzeichenlosen Werten.

^ Arbeitsalgorithmus:
Der Befehl erfordert zwei Operanden - den Dividenden und den Divisor. Der Dividende wird implizit angegeben und seine Größe hängt von der Größe des Divisors ab, der im Befehl angegeben wird:

Wenn der Divisor in Bytes angegeben ist, muss der Dividende im Register ax stehen. Nach der Operation wird der Quotient in al und der Rest in ah gesetzt;

wenn der Divisor ein Wort ist, dann muss der Dividende im Registerpaar dx:ax liegen, wobei der niedrige Teil des Dividenden in ax steht. Nach der Operation wird der Quotient in ax und der Rest in dx gesetzt;

ist der divisor ein doppelwort, dann muss der dividend im registerpaar edx:eax stehen, mit dem niedrigen teil des dividenden in eax. Nach der Operation wird der Quotient in eax und der Rest in edx gestellt.

^ Status der Flags nach der Befehlsausführung:

Anwendung:
Der Befehl führt eine ganzzahlige Division der Operanden durch und gibt das Ergebnis der Division als Quotient und den Rest der Division zurück. Bei der Durchführung einer Divisionsoperation kann eine Ausnahme auftreten: 0 - Divisionsfehler. Diese Situation tritt in einem von zwei Fällen auf: Der Divisor ist 0 oder der Quotient ist zu groß, um in das eax/ax/al-Register zu passen.

Objektcode:

|1111011w|mod110r/m|

INT
(Unterbrechen)

Aufruf einer Interrupt-Service-Routine

^ Befehlsübersicht:

int interrupt_number

Zweck: Aufruf der Interrupt-Service-Routine mit der durch den Befehlsoperanden angegebenen Interrupt-Nummer.

^ Arbeitsalgorithmus:

Schieben Sie das Flags/Flags-Register und die Rücksendeadresse auf den Stack. Beim Schreiben der Rücksprungadresse wird zuerst der Inhalt des cs-Segmentregisters geschrieben, dann der Inhalt des eip/ip-Befehlszeigers;

setze die if- und tf-Flags auf Null zurück;

Übergabe der Steuerung an den Interrupt-Handler mit angegebene Zahl. Der Steuerungsübertragungsmechanismus hängt von der Betriebsart des Mikroprozessors ab.

^ Status der Flags nach der Befehlsausführung:

Anwendung:
Wie Sie der Syntax entnehmen können, gibt es zwei Formen dieses Befehls:

int 3 - hat seinen eigenen individuellen Opcode 0cch und belegt ein Byte. Dieser Umstand macht es sehr bequem, in verschiedenen Software-Debuggern Breakpoints zu setzen, indem das erste Byte einer beliebigen Anweisung ersetzt wird. Trifft der Mikroprozessor auf einen Befehl mit dem Opcode 0cch in der Befehlsfolge, ruft er den Interrupt-Handler mit der Vektornummer 3 auf, der zur Kommunikation mit dem Software-Debugger dient.

Die zweite Form der Anweisung ist zwei Bytes lang, hat einen Opcode von 0cdh und ermöglicht es Ihnen, einen Aufruf an eine Interrupt-Service-Routine mit einer Vektornummer im Bereich von 0-255 zu initiieren. Merkmale der Steuerungsübertragung hängen, wie erwähnt, von der Betriebsart des Mikroprozessors ab.

Objektcode (zwei Formate):

Register: |01000reg|

^ Register oder Speicher: |1111111w|mod000r/m|

JCC
JCXZ/JECXZ
(Sprung wenn Bedingung)

(Sprung wenn CX=Null/Sprung wenn ECX=Null)

Springe, wenn die Bedingung erfüllt ist

Springe, wenn CX/ECX Null ist

^ Befehlsübersicht:

jcc-Etikett
jcxz-Etikett
jecxz-Label

Zweck: Übergang innerhalb des aktuellen Segments von Befehlen, abhängig von einer bestimmten Bedingung.

^ Befehlsalgorithmus (außer jcxz/jecxz):
Überprüfen des Zustands der Flags in Abhängigkeit vom Operationscode (er spiegelt die überprüfte Bedingung wider):

wenn die zu testende Bedingung wahr ist, gehe zu der durch den Operanden angegebenen Zelle;

wenn die zu prüfende Bedingung falsch ist, übergebe die Steuerung an den nächsten Befehl.

jcxz/jecxz-Befehlsalgorithmus:
Prüfung der Bedingung, dass der Inhalt des ecx/cx-Registers gleich Null ist:

wenn der geprüfte Zustand