Heim / Online Dienste / Allgemeine Eigenschaften des Befehlssystems der Assembler-Sprache für IBM-PC (grundlegender Befehlssatz, grundlegende Arten der Adressierung von Operanden). Die Struktur des Programms in der Sprache Assembler. Assembler-Sprachbefehle Assembler-Sprachbefehle

Allgemeine Eigenschaften des Befehlssystems der Assembler-Sprache für IBM-PC (grundlegender Befehlssatz, grundlegende Arten der Adressierung von Operanden). Die Struktur des Programms in der Sprache Assembler. Assembler-Sprachbefehle Assembler-Sprachbefehle

Kursarbeit

Thema "Systemprogrammierung"

Thema Nummer 4: "Problemlösung für Verfahren"

Option 2

EAST SIBIRIAN STATE UNIVERSITY

TECHNOLOGIE UND MANAGEMENT

____________________________________________________________________

TECHNOLOGISCHE HOCHSCHULE

ÜBUNG

für Hausarbeiten

Disziplin:
Thema: Problemlösung für Verfahren
Künstler: Glawinskaja Arina Alexandrowna
Leitung: Sesegma Viktorovna Dambaeva
Kurze Zusammenfassung der Arbeit: Das Studium der Subroutinen auf Assemblersprache,
Problemlösung mit Subroutinen
1. Theoretischer Teil: Grundlegende Informationen zur Assemblersprache (set
Befehle usw.), Organisation von Unterprogrammen, Möglichkeiten der Parameterübergabe
in Unterprogrammen
2. Praktischer Teil: Entwickeln Sie zwei Unterroutinen, von denen die eine einen beliebigen Buchstaben in Großbuchstaben (auch für russische Buchstaben) und die andere den Buchstaben in Kleinbuchstaben umwandelt.
wandelt jeden gegebenen Buchstaben in Großbuchstaben um, und der andere wandelt den Buchstaben in Kleinbuchstaben um.
wandelt einen Buchstaben in Kleinbuchstaben um.
Projektzeitpläne gemäß Zeitplan:
1. Theoretischer Teil - 30 % bis Woche 7.
2. Praktischer Teil - 70 % nach 11 Wochen.
3. Schutz - 100 % nach 14 Wochen.
Gestaltungsanforderungen:
1. Die Abrechnung und Begründung des Kursvorhabens sind einzureichen
elektronische und gedruckte Kopien.
2. Der Umfang des Berichts muss mindestens 20 maschinengeschriebene Seiten ohne Anhänge betragen.
3. RPP wird gemäß GOST 7.32-91 erstellt und vom Leiter unterzeichnet.

Arbeitsleiter __________________

Darsteller __________________

Datum der Ausstellung " 26 " September 2017 G.


Einführung. 2

1.1 Grundlegende Informationen zur Assemblersprache. 3

1.1.1 Befehlssatz. vier

1.2 Organisation von Subroutinen in Assemblersprache. vier

1.3 Methoden zum Übergeben von Parametern in Unterprogrammen. 6

1.3.1 Übergabe von Parametern durch Register.. 6

1.3.2 Übergabe von Parametern durch den Stack. 7

2 PRAKTISCHER ABSCHNITT 9

2.1 Problemstellung. 9

2.2 Beschreibung der Problemlösung. 9

2.3 Testen des Programms.. 7

Fazit. acht

Referenzen.. 9


Einführung

Es ist allgemein bekannt, dass das Programmieren in Assemblersprache schwierig ist. Wie Sie wissen, gibt es mittlerweile viele verschiedene Sprachen hohes Level , wodurch Sie viel weniger Aufwand beim Schreiben von Programmen aufwenden können. Natürlich stellt sich die Frage, wann ein Programmierer beim Schreiben von Programmen Assembler verwenden muss. Derzeit gibt es zwei Bereiche, in denen die Verwendung von Assemblersprache gerechtfertigt und oft notwendig ist.

Zum einen sind dies die sogenannten maschinenabhängigen Anlagenprogramme, die sie in der Regel steuern verschiedene Geräte Computer (solche Programme werden Treiber genannt). Diese Systemprogramme verwenden spezielle Maschinenbefehle, die normalerweise nicht verwendet werden müssen (oder, wie sie sagen, angewandt) Programme. Diese Befehle sind in einer Hochsprache nicht oder nur sehr schwer zu spezifizieren.

Das zweite Einsatzgebiet von Assembler betrifft die Optimierung der Programmausführung. Sehr oft produzieren Übersetzungsprogramme (Compiler) aus Hochsprachen ein sehr ineffizientes Maschinensprachenprogramm. Dies gilt normalerweise für Programme mit Rechencharakter, bei denen ein sehr kleiner (etwa 3–5 %) Abschnitt des Programms (die Hauptschleife) die meiste Zeit ausgeführt wird. Um dieses Problem zu lösen, können sogenannte mehrsprachige Programmiersysteme eingesetzt werden, die es ermöglichen, Teile des Programms in verschiedenen Sprachen zu schreiben. Normalerweise wird der Hauptteil des Programms in einer höheren Programmiersprache (Fortran, Pascal, C usw.) geschrieben, und die zeitkritischen Teile des Programms werden in Assembler geschrieben. In diesem Fall kann sich die Geschwindigkeit des gesamten Programms erheblich erhöhen. Dies ist oft die einzige Möglichkeit, ein Programm dazu zu bringen, in angemessener Zeit Ergebnisse zu erzielen.

Dies Seminararbeit ist es, praktische Fähigkeiten in der Programmierung in Assemblersprache zu erwerben.

Arbeitsaufgaben:

1. Grundlegende Informationen über die Sprache Assembler lernen (Struktur und Komponenten des Programms in Assembler, Befehlsformat, Organisation von Unterprogrammen usw.);

2. die Arten von Bitoperationen, das Format und die Logik der Assembler-Logikbefehle zu studieren;

3. Lösen Sie ein individuelles Problem für die Verwendung von Unterprogrammen in Assembler;

4. Formulieren Sie ein Fazit über die geleistete Arbeit.

1 THEORETISCHER ABSCHNITT

Grundlagen der Assemblersprache

Assembler - Programmiersprache niedriges Niveau, ein Format zum Schreiben von Maschinenanweisungen, das für die menschliche Wahrnehmung geeignet ist.

Befehle der Assemblersprache entsprechen eins zu eins Prozessorbefehlen und stellen tatsächlich eine bequeme symbolische Notationsform (Mnemocode) von Befehlen und ihren Argumenten dar. Die Assemblersprache bietet auch grundlegende Programmierabstraktionen: das Verknüpfen von Programmteilen und Daten durch Labels mit symbolischen Namen und Direktiven.

Assembler-Direktiven ermöglichen es Ihnen, Datenblöcke (explizit beschrieben oder aus einer Datei gelesen) in das Programm einzufügen; ein bestimmtes Fragment eine bestimmte Anzahl von Malen wiederholen; kompilieren Sie das Fragment gemäß der Bedingung; Stellen Sie die Fragmentausführungsadresse ein, ändern Sie die Labelwerte während der Kompilierung; Verwenden Sie Makrodefinitionen mit Parametern usw.

Vorteile und Nachteile

Die minimale Menge an redundantem Code (die Verwendung von weniger Befehlen und Speicherzugriffen). Dadurch höhere Geschwindigkeit u kleinere Größe Programme;

große Mengen an Code, viele zusätzliche kleine Aufgaben;

Schlechte Lesbarkeit des Codes, Schwierigkeiten beim Support (Debuggen, Hinzufügen von Funktionen);

· die Schwierigkeit, Programmierparadigmen und andere etwas komplexe Konventionen zu implementieren, die Komplexität gemeinsamer Entwicklung;

Weniger verfügbare Bibliotheken, ihre geringe Kompatibilität;

· direkter Zugriff auf Hardware: Input-Output-Ports, spezielle Prozessorregister;

maximales „fitting“ für die gewünschte Plattform (Einsatz spezieller Anleitungen, technische Eigenschaften"Drüse");

· Nicht-Portierbarkeit auf andere Plattformen (mit Ausnahme von binärkompatiblen).

Zusätzlich zu den Anweisungen kann das Programm Direktiven enthalten: Befehle, die nicht direkt in Maschinenanweisungen übersetzt werden, sondern den Betrieb des Compilers steuern. Ihr Satz und ihre Syntax variieren erheblich und hängen nicht von der Hardwareplattform ab, sondern vom verwendeten Compiler (wodurch Dialekte von Sprachen innerhalb derselben Architekturfamilie entstehen). Als eine Reihe von Richtlinien können wir unterscheiden:

Definition von Daten (Konstanten und Variablen);

Verwaltung der Organisation des Programms im Speicher und der Parameter der Ausgabedatei;

Einstellen des Compilermodus;

Alle Arten von Abstraktionen (d. h. Elemente von Hochsprachen) - vom Entwurf von Prozeduren und Funktionen (um die Implementierung des prozeduralen Programmierparadigmas zu vereinfachen) bis hin zu bedingten Strukturen und Schleifen (für das Paradigma strukturierte Programmierung);

Makros.

Befehlssatz

Typische Anweisungen in Assemblersprache sind:

Datenübertragungsbefehle (mov usw.)

Arithmetische Befehle (add, sub, imul usw.)

Logische und bitweise Operationen (or, and, xor, shr usw.)

Befehle zur Verwaltung der Programmausführung (jmp, loop, ret usw.)

Anrufunterbrechungsbefehle (manchmal auch als Steuerbefehle bezeichnet): int

I/O-Befehle an Ports (in, out)

Mikrocontroller und Mikrocomputer sind auch durch Befehle gekennzeichnet, die Prüfungen und Übergänge nach Bedingung durchführen, zum Beispiel:

· jne – springe, wenn nicht gleich;

· jge-Sprung, wenn größer als oder gleich.

Allgemeine Informationen zur Assemblersprache

Die symbolische Assemblersprache ermöglicht es, die Mängel der Maschinensprachenprogrammierung weitgehend zu beseitigen.

Sein Hauptvorteil besteht darin, dass in der Assemblersprache alle Programmelemente in symbolischer Form dargestellt werden. Konvertieren Sie symbolische Befehlsnamen in ihre binäre Codes sind einem speziellen Programm - Assembler zugeordnet, der den Programmierer von mühsamer Arbeit befreit und die unvermeidlichen Fehler beseitigt.

Symbolische Namen, die beim Programmieren in Assemblersprache eingeführt werden, spiegeln in der Regel die Semantik des Programms und die Abkürzung von Befehlen wider - ihre Hauptfunktion. Zum Beispiel: PARAM - Parameter, TABLE - Tabelle, MASK - Maske, ADD - Addition, SUB - Subtraktion usw. n. Der Programmierer kann sich solche Namen leicht merken.

Um in Assemblersprache zu programmieren, müssen Sie über komplexe verfügen Werkzeug als beim Programmieren in Maschinensprache: Sie benötigen Computersysteme auf Basis von Mikrocomputern oder PCs mit einem Set Peripheriegeräte(alphanumerische Tastatur, Zeichenanzeige, Diskette und Drucker) sowie residente oder übergreifende Programmiersysteme für die erforderlichen Arten von Mikroprozessoren. Mit der Assemblersprache können Sie wesentlich komplexere Programme als die Maschinensprache (bis zu 1 - 4 KB) effizient schreiben und debuggen.

Assemblersprachen sind maschinenorientiert, also abhängig von der Maschinensprache und Struktur des entsprechenden Mikroprozessors, da sie jeder Mikroprozessoranweisung einen bestimmten symbolischen Namen zuweisen.

Assemblersprachen sorgen im Vergleich zu Maschinensprachen für eine deutliche Steigerung der Produktivität von Programmierern und behalten gleichzeitig die Möglichkeit, alle per Software zugänglichen Hardware-Ressourcen des Mikroprozessors zu nutzen. Dadurch können erfahrene Programmierer Programme schreiben, die in kürzerer Zeit ablaufen und weniger Speicherplatz beanspruchen als Programme, die in einer Hochsprache geschrieben sind.

In dieser Hinsicht sind fast alle Steuerprogramme (Treiber) für E/A-Geräte in Assemblersprache geschrieben, obwohl eine ziemlich große Auswahl an Hochsprachen vorhanden ist.

Unter Verwendung der Assemblersprache kann der Programmierer die folgenden Parameter einstellen:

Mnemonik (symbolischer Name) jedes Befehls der Maschinensprache des Mikroprozessors;

Standardformat für Zeilen eines in Assembler beschriebenen Programms;

Format zur Angabe verschiedene Wege Adressierungs- und Befehlsoptionen;

Format zum Angeben von Zeichenkonstanten und Konstanten vom Typ Integer verschiedene Systeme Abrechnung;

Pseudobefehle, die den Assemblierungsprozess (Übersetzung) des Programms steuern.

In der Assemblersprache wird das Programm Zeile für Zeile geschrieben, d. h. jeder Anweisung wird eine Zeile zugeordnet.

Für Mikrocomputer, die auf der Basis der gängigsten Mikroprozessortypen aufgebaut sind, kann es mehrere Varianten der Assemblersprache geben, aber man hat normalerweise eine praktische Verbreitung - dies ist die sogenannte Standard-Assemblersprache

Die Programmierung auf der Ebene von Maschinenbefehlen ist die Mindestebene, auf der eine Programmierung möglich ist. Das System der Maschinenbefehle muss ausreichen, um die erforderlichen Aktionen auszuführen, indem Anweisungen an die Computerhardware ausgegeben werden.

Jeder Maschinenbefehl besteht aus zwei Teilen:

Betrieb - Bestimmen, "was zu tun ist";

· Operand – Definieren von Verarbeitungsobjekten, „was damit zu tun ist“.

Die in Assemblersprache geschriebene Maschinenanweisung des Mikroprozessors ist eine einzelne Zeile mit der folgenden syntaktischen Form:

Label Befehl/Direktive Operand(en) ;Kommentare

In diesem Fall ist ein Pflichtfeld in einer Zeile ein Befehl oder eine Direktive.

Label, Befehl/Anweisung und Operanden (falls vorhanden) werden durch mindestens ein Leerzeichen oder Tabulatorzeichen getrennt.

Wenn ein Befehl oder eine Anweisung in der nächsten Zeile fortgesetzt werden muss, wird der umgekehrte Schrägstrich verwendet: \.

Standardmäßig unterscheidet die Assemblersprache nicht zwischen Groß- und Kleinbuchstaben in Befehlen oder Anweisungen.

Direkte Adressierung Hinweis: Die effektive Adresse wird direkt durch das Maschinenbefehls-Offsetfeld bestimmt, das 8, 16 oder 32 Bit groß sein kann.

bewege eax, summe ; eax = Summe

Der Assembler ersetzt sum durch die entsprechende Adresse, die im Datensegment gespeichert ist (standardmäßig adressiert durch das Register ds) und legt den unter der Adresse sum gespeicherten Wert in das Register eax.

indirekte Adressierung hat wiederum folgende Typen:

Indirekte Grundadressierung (Register);

Indirekte Basis-(Register-)Adressierung mit Offset;

· indirekte Indexadressierung;

· indirekte Basisindexadressierung.

Indirekte Grundadressierung (Register). Bei dieser Adressierung kann die effektive Adresse des Operanden in jedem der Register stehen allgemeiner Zweck, mit Ausnahme von sp/esp und bp/ebp (dies sind spezielle Register für die Arbeit mit einem Stapelsegment). Syntaktisch wird dieser Adressierungsmodus in einer Anweisung ausgedrückt, indem der Registername in eckige Klammern gesetzt wird.

verschieben eax, ; eax = *esi; *esi-Wert an der Adresse esi

Strukturen in Assemblersprache

Die oben betrachteten Arrays sind eine Sammlung von Elementen des gleichen Typs. In Anwendungen besteht jedoch häufig die Notwendigkeit, eine Sammlung von Daten unterschiedlicher Typen als einen einzigen Typ zu betrachten.

Dies ist zum Beispiel für Datenbankprogramme sehr relevant, wo es notwendig ist, eine Sammlung von Daten unterschiedlichen Typs einem Objekt zuzuordnen.

Zum Beispiel haben wir uns zuvor Listing 4 angesehen, das mit einem Array von 3-Byte-Elementen funktionierte. Jedes Element wiederum bestand aus zwei Elementen unterschiedlichen Typs: einem Ein-Byte-Zählerfeld und einem Zwei-Byte-Feld, das einige andere Informationen enthalten konnte, die für die Speicherung und Verarbeitung benötigt wurden. Kennt sich der Leser mit einer der Hochsprachen aus, so weiß er, dass ein solches Objekt meist mit einem speziellen Datentyp beschrieben wird - Strukturen.

Um die Benutzerfreundlichkeit der Assemblersprache zu verbessern, wurde dieser Datentyp auch darin eingeführt.

Per Definition Struktur ist ein Datentyp, der aus einer festen Anzahl von Elementen unterschiedlichen Typs besteht.

Um Strukturen in einem Programm zu verwenden, müssen Sie drei Dinge tun:

    Fragen Strukturvorlage .

    Im Wesentlichen bedeutet dies, einen neuen Datentyp zu definieren, der später verwendet werden kann, um Variablen dieses Typs zu definieren.

    Definieren Strukturinstanz .

    Diese Phase beinhaltet die Initialisierung einer bestimmten Variablen mit einer vordefinierten (unter Verwendung einer Vorlage) Struktur.

    Organisieren Zugriff auf Strukturmitglieder .

Es ist sehr wichtig, dass Sie von Anfang an verstehen, was der Unterschied zwischen ist Bezeichnung Strukturen im Programm und seine Definition.

beschreiben Struktur in einem Programm bedeutet nur, sein Schema oder Muster anzuzeigen; Speicher wird nicht zugewiesen.

Diese Vorlage kann nur als Information für den Übersetzer über die Position der Felder und ihren Standardwert betrachtet werden.

Definieren Struktur bedeutet, den Übersetzer anzuweisen, Speicher zu allokieren und diesem Speicherbereich einen symbolischen Namen zuzuweisen.

Sie können die Struktur im Programm nur einmal beschreiben und beliebig oft definieren.

Beschreibung der Strukturvorlage

Die Strukturvorlagendeklaration hat die folgende Syntax:

Strukturname STRUC

Strukturname ENDS

Hier ist eine Folge von Datenbeschreibungsanweisungen db, dw, dd, dq und dt.

Ihre Operanden bestimmen die Größe der Felder und optional Anfangswerte. Diese Werte werden möglicherweise die entsprechenden Felder initialisieren, wenn die Struktur definiert wird.

Wie wir bereits bei der Beschreibung der Vorlage angemerkt haben, wird kein Speicher zugewiesen, da dies nur eine Information für den Übersetzer ist.

Ort template im Programm kann beliebig sein, muss aber nach der Logik des One-Pass-Übersetzers vor der Stelle stehen, an der die Variable mit dem Typ dieser Struktur definiert ist. Das heißt, wenn eine Variable mit dem Typ einer Struktur in einem Datensegment beschrieben wird, muss ihre Vorlage am Anfang des Datensegments oder davor platziert werden.

Betrachten Sie die Arbeit mit Strukturen am Beispiel der Modellierung einer Datenbank mit Mitarbeitern einer bestimmten Abteilung.

Der Einfachheit halber, um von den Problemen der Informationsumwandlung während der Eingabe wegzukommen, werden wir uns darauf einigen, dass alle Felder symbolisch sind.

Lassen Sie uns die Datensatzstruktur dieser Datenbank mit dem folgenden Muster definieren:

Daten mit einem Strukturtyp definieren

Um die mit Hilfe der Vorlage beschriebene Struktur im Programm zu verwenden, ist es notwendig, eine Variable mit dem Typ dieser Struktur zu definieren. Dazu wird folgende Syntax verwendet:

[Variablenname] Strukturname

    Variablennamen- Variabler Bezeichner des gegebenen Strukturtyps.

    Die Angabe eines Variablennamens ist optional. Wird sie nicht angegeben, wird einfach ein Speicherbereich in der Größe der Summe der Längen aller Elemente der Struktur allokiert.

    Liste von Werten- eine durch Kommas getrennte Liste von Anfangswerten von Strukturelementen, die in spitzen Klammern eingeschlossen sind.

    Seine Aufgabe ist ebenfalls optional.

    Wenn die Liste unvollständig ist, werden alle Felder der Struktur für die angegebene Variable mit Werten aus der Vorlage initialisiert, falls vorhanden.

    Es ist erlaubt, einzelne Felder zu initialisieren, aber in diesem Fall müssen die fehlenden Felder durch Kommas getrennt werden. Fehlende Felder werden mit Werten aus der Strukturvorlage initialisiert. Wenn wir beim Definieren einer neuen Variablen mit dem Typ dieser Struktur mit allen Feldwerten in ihrer Vorlage übereinstimmen (dh standardmäßig festgelegt sind), müssen Sie nur spitze Klammern schreiben.

    Z.B: Sieger Arbeiter.

Lassen Sie uns zum Beispiel mehrere Variablen mit dem Typ der oben beschriebenen Struktur definieren.

Strukturmethoden

Die Idee, einen Strukturtyp in eine beliebige Programmiersprache einzuführen, besteht darin, Variablen verschiedener Typen zu einem Objekt zu kombinieren.

Die Sprache muss eine Möglichkeit bieten, auf diese Variablen innerhalb einer bestimmten Strukturinstanz zuzugreifen. Um in einem Befehl auf ein Feld mit einer bestimmten Struktur zu verweisen, wird ein spezieller Operator verwendet - Symbol ". " (Punkt). Es wird in der folgenden Syntax verwendet:

    Adressausdruck- ein variabler Bezeichner eines bestimmten Strukturtyps oder ein Ausdruck in Klammern gemäß den unten angegebenen Syntaxregeln (Abb. 1);

    Struktur_Feldname- Feldname aus Strukturvorlage.

    Dies ist tatsächlich auch eine Adresse oder besser gesagt der Offset des Felds vom Anfang der Struktur.

Also der Betreiber " . " (Punkt) wertet den Ausdruck aus

Reis. 5. Syntax eines Adressausdrucks in einem Strukturfeld-Zugriffsoperator

Lassen Sie uns dies am Beispiel der von uns definierten Struktur demonstrieren Arbeiter einige Techniken für die Arbeit mit Strukturen.

Extrahieren Sie beispielsweise nach Axt Feldwerte mit Alter. Da es unwahrscheinlich ist, dass das Alter einer arbeitsfähigen Person über 99 Jahre liegt, nachdem der Inhalt dieses Zeichenfeldes in das Register eingetragen wurde Axt Es ist praktisch, es mit dem Befehl in eine binäre Darstellung umzuwandeln aad.

Seien Sie vorsichtig, denn aufgrund des Prinzips der Datenspeicherung „Niedriges Byte an niedriger Adresse“ die höchste Ziffer des Alters wird eingesetzt Al, und der jüngste in Ah.

Um es zu korrigieren, verwenden Sie einfach den Befehl xchg al,ah:

mov axt,word ptr sotr1.age ;im Alter sotr1

und es ist so möglich:

Die weitere Arbeit mit einem Array von Strukturen erfolgt wie bei einem eindimensionalen Array. Hier stellen sich mehrere Fragen:

Wie geht man mit der Größe um und wie organisiert man die Indizierung von Array-Elementen?

Wie andere im Programm definierte Bezeichner weist der Übersetzer dem Namen des Strukturtyps und dem Namen der Variablen mit dem Strukturtyp ein Typattribut zu. Der Wert dieses Attributs ist die Größe in Byte, die von den Feldern dieser Struktur belegt wird. Sie können diesen Wert mit dem Operator extrahieren Typ.

Sobald die Größe einer Strukturinstanz bekannt geworden ist, ist das Organisieren der Indizierung in einem Array von Strukturen nicht besonders schwierig.

Z.B:

Wie kopiere ich ein Feld von einer Struktur in das entsprechende Feld einer anderen Struktur? Oder wie kopiert man die gesamte Struktur? Kopieren wir das Feld Nam dritter Mitarbeiter im Außendienst Nam fünfter Mitarbeiter:

mas_sotr Arbeiter 10 dup()

mov bx,offset mas_sotr

mov si,(Typ worker)*2 ;si=77*2

mov di,(Typ worker)*4 ;si=77*4

Mir scheint, dass das Handwerk eines Programmierers einen Menschen früher oder später wie eine gute Hausfrau aussehen lässt. Er ist wie sie ständig auf der Suche, wo man etwas sparen, abschneiden und aus einem Minimum an Essen ein wunderbares Abendessen machen kann. Und wenn das gelingt, dann ist die moralische Befriedigung nicht geringer und vielleicht auch größer als bei einem wunderbaren Abendessen bei der Hausfrau. Der Grad dieser Befriedigung, scheint mir, hängt vom Grad der Liebe zum Beruf ab.

Andererseits entspannt der Fortschritt in der Entwicklung von Soft- und Hardware den Programmierer etwas, und nicht selten gibt es eine Situation, die dem bekannten Sprichwort von der Fliege und dem Elefanten ähnelt - um ein kleines Problem zu lösen, sind schwergewichtige Werkzeuge beteiligt, deren Wirksamkeit im Allgemeinen nur bei der Durchführung relativ großer Projekte von Bedeutung ist.

Das Vorhandensein der folgenden zwei Arten von Daten in der Sprache ist wahrscheinlich auf den Wunsch der „Hostess“ zurückzuführen, den Arbeitsbereich des Tisches (RAM) bei der Zubereitung von Speisen oder zum Platzieren von Produkten so effizient wie möglich zu nutzen (Programmdaten ).

1. PC-Architektur……………………………………………………………………5

    1.1. Register.

    1.1.1 Allzweckregister.

1.1.2. Segmentregister

1.1.3 Flaggenregister

1.2. Organisation des Gedächtnisses.

1.3. Daten Präsentation.

1.3.1 Datentypen

1.3.2 Zeichen- und Zeichenkettendarstellung

2. Erklärungen zum Vollversammlungsprogramm ……………………………………

    1. Befehle in Assemblersprache

2.2. Adressierungsmodi und Maschinenbefehlsformate

3. Pseudo-Operatoren ………………………………………………………….

3.1 Datendefinitionsrichtlinien

3.2 Aufbau des Montageprogramms

3.2.1 Programmsegmente. Direktive annehmen

3.2.3 Vereinfachte Segmentierungsrichtlinie

4. Assemblieren und Linken des Programms ………………………….

5. Datenübertragungsbefehle…………………………………………….

    5.1 Allgemeine Befehle

    5.2 Stack-Befehle

5.3 E/A-Befehle

5.4 Adressweiterleitungsbefehle

5.5 Flag-Transfer-Befehle

6. Rechenbefehle ……………………………………………….

    6.1 Arithmetische Operationen mit binären ganzen Zahlen

6.1.1 Addition und Subtraktion

6.1.2 Befehle zum Inkrementieren und Dekrementieren des Empfängers um eins

6.2 Multiplikation und Division

6.3 Vorzeichenwechsel

7. Logische Operationen ………………………………………………….

8. Schichten und zyklische Schichten …………………………………………

9. Stringoperationen …………………………………………………….

10. Logik und Organisation von Programmen ………………………………………

10.1 Bedingungslose Sprünge

10.2 Bedingte Sprünge

10.4 Prozeduren in Assemblersprache

10.5 Interrupts INT

10.6 Systemsoftware

10.6.1.1 Lesen der Tastatur.

10.6.1.2 Anzeigen von Zeichen auf dem Bildschirm

10.6.1.3 Beenden von Programmen.

10.6.2.1 Anzeigemodi auswählen

11. Festplattenspeicher ………………………………………………………………..

11.2 Dateizuordnungstabelle

11.3 Festplatten-E/A

11.3.1 Schreiben einer Datei auf die Festplatte

11.3.1.1 ASCIIZ-Daten

11.3.1.2 Aktenzeichen

11.3.1.3 Erstellen einer Festplattendatei

11.3.2 Lesen einer Diskettendatei

Einführung

Die Assemblersprache ist eine symbolische Darstellung der Maschinensprache. Alle Prozesse in einem Personal Computer (PC) auf der niedrigsten Hardwareebene werden nur durch Maschinensprachbefehle (Anweisungen) gesteuert. Ohne Assembler-Kenntnisse ist es unmöglich, hardwarebezogene Probleme (oder sogar hardwarebezogene Probleme, wie etwa die Geschwindigkeitssteigerung eines Programms) wirklich zu lösen.

Assembler ist eine bequeme Form von Befehlen direkt für PC-Komponenten und erfordert Kenntnisse über die Eigenschaften und Fähigkeiten der integrierten Schaltung, die diese Komponenten enthält, nämlich des PC-Mikroprozessors. Somit steht die Assemblersprache in direktem Zusammenhang mit der internen Organisation des PCs. Und es ist kein Zufall, dass fast alle Compiler von Hochsprachen den Zugriff auf die Assembler-Programmierebene unterstützen.

Ein Element der Vorbereitung eines professionellen Programmierers ist notwendigerweise das Studium von Assembler. Dies liegt daran, dass die Programmierung in Assemblersprache Kenntnisse der PC-Architektur erfordert, die es Ihnen ermöglichen, effizientere Programme in anderen Sprachen zu erstellen und diese mit Programmen in Assemblersprache zu kombinieren.

Das Handbuch befasst sich mit der Programmierung in Assemblersprache für Computer, die auf Intel-Mikroprozessoren basieren.

Dieses Tutorial richtet sich an alle, die sich für die Architektur des Prozessors und die Grundlagen der Programmierung in Assembler interessieren, in erster Linie an die Entwickler des Softwareprodukts.

    PC-Architektur.

Computerarchitektur ist eine abstrakte Darstellung eines Computers, die seine Struktur, Schaltkreise und logische Organisation widerspiegelt.

Alle modernen Computer haben einige gemeinsame und individuelle architektonische Eigenschaften. Individuelle Eigenschaften sind nur einem bestimmten Computermodell eigen.

Das Konzept der Computerarchitektur umfasst:

    Blockdiagramm eines Computers;

    Mittel und Methoden für den Zugriff auf Elemente Blockdiagramm COMPUTER;

    Satz und Verfügbarkeit von Registern;

    Organisation und Methoden der Adressierung;

    Präsentationsverfahren und Format von Computerdaten;

    eine Reihe von Computermaschinenanweisungen;

    Maschinenbefehlsformate;

    Unterbrechungsbehandlung.

Die Hauptelemente der Computerhardware: Systemeinheit, Tastatur, Anzeigegeräte, Laufwerke, Druckgeräte (Drucker) und verschiedene Kommunikationsmittel. Systemeinheit besteht aus einem Motherboard, Netzteil und Erweiterungszellen für zusätzliche Bretter. Das Motherboard enthält den Mikroprozessor, den Nur-Lese-Speicher (ROM), den Direktzugriffsspeicher (RAM) und den Coprozessor.

      Register.

Innerhalb des Mikroprozessors sind Informationen in einer Gruppe von 32 Registern (16 Benutzer, 16 System) enthalten, die dem Programmierer mehr oder weniger zur Verfügung stehen. Da sich das Handbuch der Programmierung des Mikroprozessors 8088-i486 widmet, ist es am logischsten, dieses Thema mit der Erörterung der internen Register des Mikroprozessors zu beginnen, die dem Benutzer zur Verfügung stehen.

Benutzerregister werden vom Programmierer zum Schreiben von Programmen verwendet. Zu diesen Registern gehören:

    acht 32-Bit-Register (Allzweckregister) EAX/AX/AH/AL, EBX/BX/BH/BL, ECX/CX/CH/CL, EDX/DX/DLH/DL, EBP/BP, ESI/SI, EDI/DI, ESP/SP;

    sechs 16-Bit-Segmentregister: CS, DS, SS, ES, FS, GS;

    Status- und Steuerregister: EFLAGS/FLAGS-Flag-Register und EIP/IP-Befehlszeigerregister.

Teile eines 32-Bit-Registers werden durch einen Schrägstrich dargestellt. Das Präfix E (Extended) kennzeichnet die Verwendung eines 32-Bit-Registers. Um mit Bytes zu arbeiten, werden Register mit den Präfixen L (low) und H (high) verwendet, z. B. AL, CH - die Low- und High-Bytes der 16-Bit-Teile der Register bezeichnen.

        Allgemeine Register.

EAX/AX/AH/AL(Akkumulatorregister) - Batterie. Wird bei Multiplikation und Division, bei E/A-Operationen und bei einigen Operationen mit Zeichenfolgen verwendet.

EBX/BX/BH/BL - Basisregister(Basisregister), wird häufig verwendet, wenn Daten im Speicher adressiert werden.

ECX/CX/CH/CL - Zähler(Zählregister), dient als Zähler für die Anzahl der Schleifenwiederholungen.

EDX/DX/DH/DL - Datenregister(Datenregister), das zum Speichern von Zwischendaten verwendet wird. Einige Befehle erfordern es.

Alle Register dieser Gruppe erlauben den Zugriff auf ihre "unteren" Teile. Nur die unteren 16- und 8-Bit-Teile dieser Register können für die Selbstadressierung verwendet werden. Die oberen 16 Bit dieser Register stehen nicht als eigenständige Objekte zur Verfügung.

Zur Unterstützung von Zeichenfolgenverarbeitungsbefehlen, die eine sequentielle Verarbeitung von Zeichenfolgen von Elementen mit einer Länge von 32, 16 oder 8 Bit ermöglichen, werden die folgenden verwendet:

ESI/SI (Quellindexregister) - Index Quelle. Enthält die Adresse des aktuellen Quellelements.

EDI/DI (Distanzregister) - Index Empfänger(Empfänger). Enthält die aktuelle Adresse im Zielstring.

Die Architektur des Mikroprozessors auf Hard- und Softwareebene unterstützt die Datenstruktur – den Stack. Um mit dem Stack zu arbeiten, gibt es spezielle Befehle und spezielle Register. Es ist zu beachten, dass der Stack zu kleineren Adressen hin gefüllt wird.

ESP/SP (Stapelzeigerregister) - registrieren Zeiger Stapel. Enthält einen Zeiger auf den Stapelanfang im aktuellen Stapelsegment.

EBP/BP (Basiszeigerregister) – Stapelbasiszeigerregister. Entwickelt, um den wahlfreien Zugriff auf Daten innerhalb des Stacks zu organisieren.

1.1.2. Segmentregister

Das Mikroprozessor-Softwaremodell hat sechs Segmentregister: CS, SS, DS, ES, GS, FS. Ihre Existenz ist auf die Besonderheiten der Organisation und Verwendung von RAM durch Intel-Mikroprozessoren zurückzuführen. Die Mikroprozessor-Hardware unterstützt die strukturelle Organisation des Programms bestehend aus Segmente. Zur Angabe der verfügbaren Segmente in dieser Moment Segmentregister. Der Mikroprozessor unterstützt die folgenden Arten von Segmenten:

    Codesegment. Enthält Programmbefehle Um auf dieses Segment zuzugreifen, verwenden Sie das CS-Register (Code Segment Register) - Segmentcoderegister. Es enthält die Adresse des Maschinenbefehlssegments, auf das der Mikroprozessor Zugriff hat.

    Datensegment. Enthält die vom Programm verarbeiteten Daten. Um auf dieses Segment zuzugreifen, wird das DS-Register (Datensegmentregister) verwendet - Segmentdatenregister, das die Adresse des Datensegments des aktuellen Programms speichert.

    Stack-Segment. Dieses Segment ist ein Speicherbereich, der Stapel genannt wird. Der Mikroprozessor organisiert den Stack nach dem Prinzip – der Erste „kam“, der Erste „ging“. Um auf den Stack zuzugreifen, wird das SS-Register (Stack Segment Register) verwendet - Stapelsegmentregister A enthält die Adresse des Stapelsegments.

    Zusätzliches Datensegment. Die zu verarbeitenden Daten können sich in drei weiteren Datensegmenten befinden. Standardmäßig wird davon ausgegangen, dass sich die Daten im Datensegment befinden. Bei Verwendung zusätzlicher Datensegmente müssen deren Adressen explizit durch spezielle Segment-Redefinition-Präfixe im Befehl angegeben werden. Adressen zusätzlicher Datensegmente müssen in den Registern ES, GS, FS (Extension Data Segment Registers) enthalten sein.

        Steuer- und Statusregister

Der Mikroprozessor enthält mehrere Register, die Informationen über den Zustand sowohl des Mikroprozessors selbst als auch des Programms enthalten, dessen Anweisungen gerade in die Pipeline geladen werden. Das:

EIP/IP-Befehlszeigerregister;

    EFLAGS/FLAGS-Flag-Register.

Mithilfe dieser Register können Sie Informationen über die Ergebnisse der Befehlsausführung erhalten und den Zustand des Mikroprozessors selbst beeinflussen.

EIP/IP (Befehlszeigerregister) - Zeiger Befehle. Das EIP/IP-Register ist 32 oder 16 Bit breit und enthält den Offset des nächsten auszuführenden Befehls relativ zu den Inhalten des CS-Segmentregisters im aktuellen Befehlssegment. Dieses Register ist nicht direkt zugänglich, wird aber durch Sprungbefehle verändert.

EFLAGS/FLAGS (Flaggenregister) - registrieren Flaggen. Bittiefe 32/16 Bit. Einzelne Bits dieses Registers haben einen bestimmten funktionalen Zweck und werden Flags genannt. Ein Flag ist ein Bit, das auf 1 ("Flag ist gesetzt") gesetzt ist, wenn eine Bedingung wahr ist, und andernfalls auf 0 ("Flag ist gelöscht"). Der untere Teil dieses Registers ist vollständig analog zum FLAGS-Register für den i8086.

1.1.3 Flaggenregister

Das Flag-Register ist 32 Bit groß und trägt den Namen EFLAGS (Bild 1). Einzelne Bits des Registers haben einen bestimmten funktionalen Zweck und werden Flags genannt. Jedem von ihnen ist ein bestimmter Name zugeordnet (ZF, CF usw.). Die unteren 16 Bits von EFLAGS stellen das 16-Bit-FLAGS-Register dar, das verwendet wird, wenn Programme ausgeführt werden, die für die i086- und i286-Mikroprozessoren geschrieben wurden.

Abb.1 Flaggenregister

Einige Flags werden Bedingungsflags genannt; Sie ändern sich automatisch, wenn Befehle ausgeführt werden, und legen bestimmte Eigenschaften ihres Ergebnisses fest (z. B. ob es gleich Null ist). Andere Flags werden Zustandsflags genannt; sie verändern sich vom Programm und beeinflussen das weitere Verhalten des Prozessors (zB blockieren sie Interrupts).

Bedingungsflags:

CF (Carry-Flag) - Flagge tragen. Sie nimmt den Wert 1 an, wenn beim Addieren ganzer Zahlen eine Übertragseinheit auftaucht, die nicht in das Bitraster „passt“, oder wenn beim Subtrahieren von Zahlen ohne Vorzeichen die erste kleiner ist als die zweite. Bei den Shift-Befehlen wird das Off-Grid-Bit in die CF eingetragen. CF behebt auch die Merkmale der Multiplikationsanweisung.

OF (Überlauf-Flag) Überlauf-Flag. Es wird auf 1 gesetzt, wenn beim Addieren oder Subtrahieren von ganzen Zahlen mit Vorzeichen das Ergebnis modulo über dem zulässigen Wert erhalten wurde (die Mantisse ist übergelaufen und in das Vorzeichenbit "geklettert").

ZF (Nullfahne) Null-Flag. Auf 1 gesetzt, wenn das Ergebnis des Befehls 0 ist.

SF (SIGN-Flag) - Flagge Schild. Auf 1 setzen, wenn die Operation mit vorzeichenbehafteten Zahlen zu einem negativen Ergebnis führt.

PF (Paritätsflag) - Flagge Parität. Es ist gleich 1, wenn das Ergebnis des nächsten Befehls eine gerade Anzahl binärer Einsen enthält. Sie wird in der Regel nur bei I/O-Operationen berücksichtigt.

AF (Auxiliary Carry Flag) - zusätzliches Carry-Flag. Behebt die Funktionen zum Ausführen von Operationen mit Binär-Dezimal-Zahlen.

Statusflags:

DF (Richtungsflagge) Richtungsfahne. Legt die Richtung des Scannens von Zeilen in String-Befehlen fest: Mit DF=0 werden Zeilen "vorwärts" (von Anfang bis Ende) gescannt, mit DF=1 - in die entgegengesetzte Richtung.

IOPL (Eingabe-/Ausgabeberechtigungsebene) - E/A-Berechtigungsstufe. Wird im geschützten Modus des Mikroprozessors verwendet, um den Zugriff auf E / A-Befehle zu steuern, abhängig von der Berechtigung der Aufgabe.

NT (verschachtelte Aufgabe) Task-Verschachtelungsflag. Wird im geschützten Modus des Mikroprozessors verwendet, um die Tatsache aufzuzeichnen, dass eine Aufgabe in einer anderen verschachtelt ist.

Systemflag:

IF (INTERrupt-Flag) - Interrupt-Flag. Bei IF=0 reagiert der Prozessor nicht mehr auf ankommende Interrupts, bei IF=1 wird die Blockierung von Interrupts aufgehoben.

TF (Trap-Flag) Trace-Flag. Bei TF = 1 macht der Prozessor nach Ausführung jeder Anweisung einen Interrupt (mit der Nummer 1), der beim Debuggen eines Programms verwendet werden kann, um es zu verfolgen.

RF (Wiederaufnahme-Flag) Flagge wieder aufnehmen. Wird verwendet, wenn Interrupts von den Debug-Registern behandelt werden.

VM (virtueller 8086-Modus) - virtuelles 8086-Flag. 1 – der Prozessor arbeitet im virtuellen 8086-Modus 0 – der Prozessor arbeitet im realen oder geschützten Modus.

AC (Alignment check) - Ausrichtungskontrollflag. Entwickelt, um die Ausrichtungssteuerung beim Zugriff auf den Speicher zu ermöglichen.

      Organisation des Gedächtnisses.

Der physische Speicher, auf den der Mikroprozessor Zugriff hat, wird aufgerufen Arbeitsgedächtnis ( oder Speicher mit wahlfreiem Zugriff RAM). RAM ist eine Kette von Bytes, die ihre eigene eindeutige Adresse (ihre Nummer) haben, genannt körperlich. Der physische Adressbereich liegt zwischen 0 und 4 GB. Der Speicherverwaltungsmechanismus ist vollständig hardwarebasiert.

Der Mikroprozessor unterstützt mehrere Modelle der RAM-Nutzung in der Hardware:

    segmentiertes Modell. Bei diesem Modell wird der Programmspeicher in zusammenhängende Speicherbereiche (Segmente) unterteilt, und das Programm selbst kann nur auf Daten zugreifen, die sich in diesen Segmenten befinden;

    Seitenmodell. In diesem Fall wird RAM als eine Gruppe von Blöcken mit einer festen Größe von 4 KB betrachtet. Die Hauptanwendung dieses Modells bezieht sich auf die Organisation virtueller Speicher, wodurch Programme mehr Speicherplatz verwenden können als der physische Speicher. Bei einem Pentium-Mikroprozessor kann die Größe des möglichen virtuellen Speichers bis zu 4 TB betragen.

Die Verwendung und Implementierung dieser Modelle hängt von der Betriebsart des Mikroprozessors ab:

    Real-Adress-Modus (Real-Modus). Der Modus ähnelt dem Betrieb des i8086-Prozessors. Erforderlich für den Betrieb von Programmen, die für frühe Prozessormodelle entwickelt wurden.

    Sicherheitsmodus. Der geschützte Modus ermöglicht Multitasking Informationsverarbeitung, Speicherschutz mit einem vierstufigen Berechtigungsmechanismus und dessen Paging.

    Virtueller 8086-Modus. In diesem Modus wird es möglich, mehrere Programme für i8086 auszuführen. In diesem Fall können Real-Modus-Programme funktionieren.

Die Segmentierung ist ein Adressierungsmechanismus, der die Existenz mehrerer unabhängiger Adressräume sicherstellt. Ein Segment ist ein unabhängiger, hardwareunterstützter Speicherblock.

Jedes Programm kann im allgemeinen Fall aus beliebig vielen Segmenten bestehen, hat aber direkten Zugriff auf die drei Hauptsegmente: Code, Daten und Stack - und auf ein bis drei zusätzliche Datensegmente. Operationssystem legt Programmsegmente im RAM an bestimmten physikalischen Adressen ab und legt danach die Werte dieser Adressen in den entsprechenden Registern ab. Innerhalb eines Segments greift das Programm auf Adressen relativ zum Anfang des Segments linear zu, d. h. beginnend bei Adresse 0 und endend bei einer Adresse gleich der Größe des Segments. Relative Adresse bzw Voreingenommenheit, die der Mikroprozessor verwendet, um auf Daten innerhalb eines Segments zuzugreifen, aufgerufen effizient.

Bildung einer physikalischen Adresse im Realmodus

Im Real-Modus reicht der physikalische Adressbereich von 0 bis 1 MB. Die maximale Segmentgröße beträgt 64 KB. Bei Bezugnahme auf eine bestimmte physikalische Adresse RAM wird durch die Adresse des Segmentanfangs und den Offset innerhalb des Segments bestimmt. Die Segmentstartadresse wird dem entsprechenden Segmentregister entnommen. In diesem Fall enthält das Segmentregister nur die oberen 16 Bit der physikalischen Adresse des Segmentanfangs. Die fehlenden unteren vier Bits der 20-Bit-Adresse erhält man, indem man den Wert des Segmentregisters um 4 Bits nach links verschiebt. Die Verschiebungsoperation wird in Hardware durchgeführt. Der resultierende 20-Bit-Wert ist die tatsächliche physikalische Adresse, die dem Anfang des Segments entspricht. Also physische Adresse wird als ein "Segment:Offset"-Paar angegeben, wobei "Segment" die ersten 16 Bits der Startadresse des Speichersegments sind, zu dem die Zelle gehört, und "Offset" die 16-Bit-Adresse dieser Zelle ist, gezählt ab Anfang dieses Speichersegments (Wert 16*Segment + Offset ergibt die absolute Adresse der Zelle). Wenn beispielsweise der Wert 1234h im CS-Register gespeichert ist, dann definiert das Adresspaar 1234h:507h eine absolute Adresse gleich 16*1234h+507h = 12340h+507h = 12847h. Ein solches Paar wird in Form eines Doppelworts und (wie bei Zahlen) in "umgekehrter" Form geschrieben: Das erste Wort enthält den Offset und das zweite - das Segment, in dem jedes dieser Wörter wiederum dargestellt wird "umgekehrte" Form. Das Paar 1234h:5678h würde beispielsweise so geschrieben:| 78 | 56| 34 | 12|.

Dieser Mechanismus zur Bildung einer physikalischen Adresse ermöglicht es Ihnen, die Software verschiebbar zu machen, dh unabhängig von bestimmten Download-Adressen im RAM.

Anweisungsstruktur in Assemblersprache Das Programmieren auf der Ebene von Maschinenanweisungen ist die Mindestebene, auf der Computerprogrammierung möglich ist. Das System der Maschinenbefehle muss ausreichen, um die erforderlichen Aktionen umzusetzen, indem Anweisungen an die Maschinenhardware ausgegeben werden. Jeder Maschinenbefehl besteht aus zwei Teilen: einem Operationsteil, 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 Module genannt werden, 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 übergeben werden, wenn eine Prozedur aus anderen Sprachen, einschließlich Hochsprachen (C++, Pascal), aufgerufen wird. Der Parameter kann folgende Werte annehmen: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Gedächtnismodelle. Modifizierer MODEL memory_model, calling_convention, OS_type, stack_parameter Der OS_type-Parameter ist standardmäßig OS_DOS und derzeit 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-Übersetzer Ein Übersetzer ist ein Programm bzw technische Mittel Eine, die ein Programm in einer der Programmiersprachen in ein Programm in der Zielsprache umwandelt, Objektcode genannt. 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. В дополнительных опциях мастера проекта указать “Empty Project”.!}

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. Schnittstelle Computerprogramm). Ihre Zahl erreicht 2000. Das Programm für Windows besteht größtenteils aus solchen Aufrufen. Alle Interaktionen mit Externe Geräte und Ressourcen des Betriebssystems erfolgt 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).

Anruf Windows-Funktionen API 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