GEHNIO Gesamtschule Duisburg-Hamborn/Neumühl: Informatik in der Oberstufe
GEHNIO
Gesamtschule Duisburg-Hamborn/Neumühl
Informatik in der Oberstufe

> Home
> Algorithmen
> Datenstrukturen
> Maschinenmodelle
> Probleme
> Themen
> Mindmaps
> Aufgaben
> Programmierung
> Facharbeit
> Abitur
> Projekte
> Informatik-AG
> News
> Impressum
> email
 


Assembler-Programmierung


1. Einleitung

In diesem Themenheft wird die Assembler-Programmierung unter PASCAL mit der asm-Anweisungen erläutert.
Die Assebler-Programmierung unter PASCAL hat der Vorteil, dass man sehr komfortable arbeiten kann und viele Konzepte von PASCAL weiterverwendet kann.
Für die Assembler-Programmierung unter PASCAL vereinbaren wir folgende Programmierkonventionen.


2. Programmierkonventionen

Die Eingabe und Ausgabe unserer Assembler-Programme soll über die komfortablen Eingabe- und Ausgabeanweisungen von PASCAL geschehen. Wir verwenden also gewöhnliche Integer-Variablen und die READLN() und WRITELN() - Anweisungen. Die Variablen für die Ausgaben entsprechens Ausgabe1, Ausgabe2 usw. Benenne, die Variablen für die Ausgaben entsprechens Ausgabe1, Ausgabe2 usw. Durch diese Vorgehensweise sparen wir uns vor allem komplizierte und kritische Speicherzugriffe, wie dies sonst bei der Assemblerprogrammierung üblich ist. Eine Assemblerprogramm in PASCAL hat dann folgenden Aufbau:
    Program assembler;
    Uses wincrt;
    Label M1, M2 M3; {hier werden die Label deklariert}
    Var       Eingabe1, Eingabe2 :Integer;
                 Ausgabe1, Ausgabe2, Ausgabe3 : Integer; {Ein- und Ausgabevariablen}

    Begin {Beginn des Pascal-Programms}

    asm {Beginn des Assembler-Programms}

      {hier wird die Assembler-Code eingetragen}

    end; {Ende des Assembler-Programms}

    end. {Ende des Pascal-Programms}


3. Die CPU-Register

Bei der Assembler-Programmierung werden interne Speicherbausteine des Prozessors (z.B. des 8086-Prozessors) angesprochen und verwaltet, um Daten bei der Abarbeitung eines Programms zwischen den Bauteilen des Prozessors transportieren und zwischenspeichern zu können. Diese sogenannten Regiester befinden sich im Innern des Prozessors, so dass ein blitzschneller Zugriff auf die Daten gewährleistet ist.
Wir wollen zunächst die sogenannten Allzweckregister besprechen, die sehr häufig bei der Assembler.Programmierung verwendet werden.

3.1. Allzweckregiester

Die Allzweckregiester setzen sich aus dem Akkumulator (AX), dem Basisregiester (BX), dem Zählregister (CX) und dem Datenregiester (DX) zusammen. Bei allen Regiestern des 8086-Prozessors handelt es sich um 16-Bit-Regiester. Nach der Binärlogik kann ein Wertebereich bis 216 in jedem Regiester gespeichert und verarbeitet werden.

3.2. Der Akkumulator (AX)

Der Akkumulator (auch AX-Regiester genannt) wird hauptrsächlich bei allen arithmetischen Operationen eingesetzt. Standartmäßig muß es bei der Multiplikation und Division verwendet werden. Der Akkumulator solle aber auch bei Addition, Subtraktion und Vergleichen verwendet werden, weil arithmetischen Aufgaben dadurch effizient bearbeitet werden können.

3.3. Das BX-Register

Möchten Sie den Inhalt des Arbeitsspeichers direkt ansprechen, so müssen Sie das BX-Register verwenden. Das Basis-Register mit der Abkürzung BX erlaubt es uns, direkt auf den Arbeitsspeicher zuzugreifen. Das BX-Register wird dazu als eine Art Zeiger auf den Inhalt des Speichers verwendet. Mit Hilfe dieses Zeigers kann der Inhalt von Speicherzellen direkt gelesen und beschrieben werden, was dieses Register besonders für die Tabellen- und String- Verarbeitung interessant macht.
Bei der Verwendung des BX-Registers muß man sich natürlich immer darüber klar sein, auf welche Speicherzelle das Register gerade zeigt. Man kann diesem Register natürlich auch Werte zuweisen, z.B. den Anfang (die Basis) eines reservierten Speicherbereichs. So wird z.B. durch die Assembleranweisung
                MOV BX, offset MeinString
das BX-Register auf den Anfang eines Strings gesetzt.

3.4.Das CX-Register

Das Count- oder Zähler-Register ist der Spezialist, wenn es um den Einsatz von Schleifen geht.
So kann man z.B. mit Hilfe des LOOP-Befehls und dem CX-Register sehr komfortabel eine Schleife Programmieren.

Beispiel:


Schleifenanfang:          {Das ist ein Label den Anfang der Schleife}

{Hier werden die Befehle eingetragen, die wiederholt ausgeführt werden!}
{CX kann dabei manipuliert werden, z.B. mit DEC CX bzw. INC CX}

loop Schleifenanfang:      {Solange Cx ungleich null springe zum Schleifenanfang!}

Das folgende Beispielprogramm zeigt die Verwendung des CX-Registers anhand eines einfachen Algorithmus zur Berechnung des Summe der ersten n natürlichen Zahlen.



program assemblertest;
uses wincrt;
LABEL Anfang;
var Eingabe, Ausgabe : integer;
begin
readln(Eingabe);

{Hier beginnt der eigentliche Assemblercode!}
asm
    MOV AX,0;
    MOV CX,Eingabe;

Anfang:     ADD AX, CX;   {AX:=AX+CX}
                  DEC CX;   {Decrementieren des CX-Registers CX:=CX-1;}
                  CMP CX,0;   {Vergleiche CX mit 0}
                  JNE Anfang;   {Jump if not equal}

 MOV Ausgabe,AX;
end;
{Hier endet der Assemblercode!}

writeln(Ausgabe);

end.

3.5.Das DX-Register

Dieses Register wird besonders in Verbindung mit 32-Bit-Multiplikations- und Divisionsoperationen genutzt. Das DX-Register wird hier zusammen mit dem AX-Register verwendet.

Beispiel:
MOV AX, Laenge {Der erste Operand muß sich im Akkumulator befinden}
MUL Breite {Der zweite Operant muß beim Mul-Befehl angegeben werden}

Das Ergebnis steht dann mit dem HIGH-Teil im DX-Register, mit dem LOW-Teil im Akkumulator.

3.6.Weitere Register

Selbsverständlich gibt es noch zahlreiche weitere Register.
Dies sind vor allem

  • Segmentregister zur Adressierung des Arbeitsspeichers,
  • Zeige- und Indexregister,
  • Statusregister
  • und den sogenannten Stack (Kellerspeicher)


4.Das Format einer Assembler-Zeile

Damit der Assembler die Befehle und dazugehörige Operanden auseinanderhalten kann, haben die Zeilen im Quelltext folgendes Format.

Label: Befehl/Anweisung Operanden; {Kommentar}

Beispiele

Addiere:     ADD   AX, laenge;   {Die Länge wird zum Akkuinhalt addiert}
                    MOV   CX, 200;


5.Verschiebe und Ladebefehle

5.1.Der Move-Befehl

    MOV Ziel,Quelle; {Ziel:=Quelle}

Der Move-Befehl (MOV) ist einer der wichtigsten Befehle in Assembler. Er ist ein Datentransferbefehl und überträgt ein Byte oder ien Wort vom Quelloperanden zum Zieloperanden.
Beispiele
    MOV AX,BX; {AX:=BX}
    MOV CX,Zaehler; {CX:=Zaehler}

5.2.Der Tauschbefehl XCHG

    XCHG Operand1,Operand2; {Operand1 < --> Operand2}

Dieser Befehl Tauscht den Inhalt von Operand1 mit dem Inhalt von Operand2. Es ist ein sehr nützlicher Befehl für Sortierroutinen.


6.Mathematische Grundbefehle

Wie das bei vielen Prozessoren der Fall ist, beherrscht auch der 8086-Prozessor zunächst nur einfache mathematische Befehle wie z.B. Addition, Subtraktion, Multiplikation und Division. Dies ist jedoch ausreichend, weil sich höhere mathematische Operationen, wie z.B. Potenzfunktion oder Wurzelfunktion aus diesem Grundrechenart ableiten lassen.

6.1.Der Additionsbefehl ADD

    ADD Ziel,Quelle; {Ziel:=Ziel+Quelle}
Der ADD-Befehl addiert den Inhalt des Zieloperanden mit dem Inhalt frd Quelloperanden und legt das Ergebnis im Zieloperanden ab. Der ADD-Befehl arbeitet dabei mit 8- oder 16- Bit-Operanden. Beide Operanden müssen die gleiche Größe aufweisen. Wird der Wertebereich des Zieloperanden durch die Addition überschritten, so wird dies im Beispiele:
    ADD AX, 2000        {AX:=AX+2000}
    ADD Zaehler,10;     {Zaehler:=Zaehler+10}
    ADD Al,11;              {Al:=Al+11}

6.2. DER SUBTRAKTIONSBEFEHL SUB

SUB Ziel,Quelle; {Ziel := Ziel - Quelle}

Der SUB-Befehl subtrahiert den Inhalt des Quelloperanden vom Inhalt des Zieloperanden und legt das Ergebnis im Zieloperanden ab.
Beispiele:
   SUB AX, 2000; {AX := AX - 2000}
   SUB Zaehler,10; {Zaehler := Zaehler - 10}
   SUB Al,11; {Al := Al - 11}


6.3. DER MULTIPLIKATIONBEFEHL MUL


  MUL Quelle; {AX := AL * Quelle}

Der Befehl MUL multipliziert den Wert im Quelloperanden mit dem Wert im Akkumulator. Als Quelloperand kann ein CPU-Register oder eine Variable verwendet werden. Beim MUL-Befehl m�ssen wir zwischen einer Byte- und einer Wort-Multiplikation unterscheiden.

6.3.1. Die Byte-Multiplikation

Die Bytemultiplikation multipliziert zwei vorzeichenlose 8-Bit-Werte miteinander und legt das Ergebnis im AX-Register ab. Ein Operand mu� sich dabei im AL-Register gefinden (LOW-Teil des Akkumulators) Der zweite Operand, der aus einem 8-Bit-Register oder einer 8-Bit-Speicherstelle bestehen mu�, wird beim Aufruf des Mul-Befehls mit angegeben.

Beispiel:
  MOV AL,50;  {AL := 50}
  MOV BH,100;   {BH := 100}
  MUL BH   {AX := AL * BH}


6.3.2. Die Wort-Multiplikation

Die Wort-Multiplikation multipliziert zwei vorzeichenlose 16-Bit-Werte miteinander und legt das Ergebnis im Registerpaar DX/AX ab. Der h�herwertige Wert steht dabei im DX-Register, der niederwertige Wert im AX-Register. Ein Operand mu� sich im AX-Register befinden. Der zweite Operand, der aus einem 16-Bit Register oder einer Wort-Speicherstelle bestehen mu�, wird beim Aufruf des Mul-Befehls mit angegeben.

6.4. DER DIVISIONSBEFEHL DIV



  DIV Quelle; {AX := AX DIV Quelle}

Der Befehl DIV dividiert den Wert im Zieloperanden durch den Wert im Quelloperanden. Der Zieloperand ist bei einer Byte-Division standardm��ig das AX-Register, bei einer Wort-Division das Registerpaar AX/DX. Als Quelloperand kann ein CPU-Register oder ein Speicheroperand verwendet werden.

6.4.1. Die Byte-Division



Die Byte-Division dividiert den Inhalt des Ax-Registers durch einen 8-Bit-Wert. Das Ergebnis wird im AX-Register abgelegt. Der Quotiont, also das ganzzahlige Ergebnis der Division, befindet sich im AL-Register (LOW-Teil des Akkumulators), der Divisionsrest (vgl. Modula-Funktion bei Pascal) im AH-Register (HIGH-Teil des Akkumulators).

6.4.2. Die Wort-Division

Die Wort-Division dividierrt den Inhalt des Registerpaar DX/AX durch einen 16-Bit-Wert. Das ganzzahlige Ergebnis der Division wird im AX-Register abgelegt, der Divisionsrest im DX-Register.

6.5. Inkrementieren



Zum Inkrementieren, also zum Heraufz�hlen eines Registerinhalts gibt es einen speziellen Befehl. Der Inkrement-Befehl addiert den Wert 1 zum Ziel.

   INC Ziel; {Ziel := Ziel + 1}


6.6. Dekrementieren



Zum Dekrementieren, also zum Herabz�hlen eines Registerinhalts gibt es einen speziellen Befehl. Der Dekrement-Befehl subtrahiert den Wert 1 vom Ziel.

  DEC Ziel; {Ziel := Ziel - 1}

7. Sprung- und Schleifenbefehle


7.1. Der unbedingte Sprung


   JMP Ziel;

Der Jump-Befehl bewirkt einen Sprung auf eine Adresse im Programm, die mit dem Zieloperanden angegeben wird. Der Zieloperand ist dabei meistens ein Label.

7.2. Bedingte Spr�nge - IF-THEN in Assembler



Bedingte Spr�nge werden durch eine Kombination aus Vergleichs-Befehl (CMP) und Sprung-Befehl realisiert. Wir werden uns auf die wichtigsten Befehle beschr�nken.

   Jxxx Ziel; {Springe, wenn die Bedingung erf�llt ist, zum Ziel}

7.3. Der Wiederderholungsbefehl LOOP

  LOOP Ziel; {Verzweige so lange zum Ziel, bis CX-Register=0}

Der LOOP-Befehl verzeigt so lange zu dem Zieloperanden (z.B. Label), bis das CX-Register den Wert null aufweist. Der Loop-Befehl vermindert dazu bei jedem Aufruf das CX-Register um den Wert 1 und kontrolliert anschlie�end dessen Inhalt. Wenn das CX-Register den Wert null aufweist, dann wird der n�chste Befehl nach der LOOP-Anweisung verarbeitet.

Beispiel:
 program assemblertest;
 uses wincrt;
 LABEL Anfang;
 var Eingabe1, Eingabe2, Ausgabe1 : integer;
 begin
  readln(Eingabe1);
  readln(Eingabe2);

  {Hier beginnt der eigentliche Assemblercode!}
  asm
   MOV AX,Eingabe1;
   MOV CX,Eingabe2;
   DEC CX; {CX := CX - 1}

  Anfang: ADD AX, Eingabe1;
    LOOP Anfang; {Solange CX ungleich Null Springe zum Anfang}

   MOV Ausgabe1,AX;

 end;
 {Hier endet der Assemblercode!}
writeln(Ausgabe1);
end.


8. Aufgaben zum Thema


Aufgabe 1:

Schreiben Sie ein Assembler-Programm unter PASCAL, dass zu einer eingegebenen positiven ganzen Zahl n das Quadrat berechnet.

Aufgabe 2:

Schreiben Sie ein Assembler-Programm unter PASCAL, das die Summe der ersten n nat�rlichen Zahlen berechnet und ausgibt.
S := 1 + 2 + 3 + ... + (n-3) + (n-2) + (n-1) +n

Aufgabe 3:

Schreiben Sie ein Assembler-Programm unter PASCAL, dass bei einer eingegebenen positiven ganzen Zahl n �berpr�ft, ob diese ungerade oder gerade ist. Das Programm soll dabei "1" ausgeben, wenn die eingegeben Zahl gerade war und "0", wenn die eingegebene Zahl ungerade war.

Aufgabe 4:

Schreiben Sie ein Assembler-Programm unter PASCAL, dass bei einer eingegebenen positiven ganzen Zahl n �berpr�ft, ob es sich bei der Zahl um eine Quadratzahl handelt oder nicht. Das Programm soll dabei "1" ausgeben, wenn die eingegeben Zahl eine Quadratzahl war und

 

 

 

 

 

 

 

 

 
  © 2002 Gesamtschule Duisburg-Hamborn/Neumühl.  
Hosted by www.Geocities.ws

1