Assembler 2 im SoSe 2002

Archiv Sommersemester 2001

Vorlesung am 08.04.2002 in HS4

"Crash-Kurs als Wiederholung von Assembler 1"

Übung 1 am 15.04.2002 - Abgabe am 29.04.2002 - in RZ2/3

Entwickle zunächst eine allgemein verwendbare Toolbox (Datentransfer via geeignet zu definierendem Register) zum Ausgeben einer 16-Bit ganzen Zahl mit Vorzeichen als Dezimalzahl (linksbündig) über die Standardausgabe sowie anschließend ein EXE-Programm - unter Benutzung der gerade entwickelten Toolbox - zum Berechnen und Ausgeben der gerundeten relativen Häufigkeit der einzelnen Buchstaben (ohne Unterscheidung zwischen Klein- und Großbuchstaben) über die Standardausgabe in einer zuvor über die Standardeingabe via DOS-Funktion 10 (dezimal) bzw. 0A (hexadezimal) eingelesenen Zeichenkette. Sollte Eure Lösung die eingelesene Zeichenkette 26-mal durchlaufen, so ist das genau 25-mal zu häufig :-) Es entstehen zwei Quellcode-Dateien mit je einem Code-Segment. Das Stack-Segment (und Daten-Segment) wird (werden) in jener Quellcode-Datei definiert, die auch das Hauptprogramm beinhaltet. Für das Aufrufen der Routine in der Toolbox kommen neben dem CALL-Befehl die beiden Assembler-Anweisungen EXTRN und PUBLIC zum Einsatz.

Das nachfolgende Dialogbeispiel möge die Aufgabenstellung verdeutlichen :

Moin Moin - Assembler ist eine schön bittige Programmiersprache

A  6
B  4
C  4
D  0
E  13
F  0
G  4
H  4
I  13
J  0
K  0
L  2
M  9
N  8
O  6
P  4
Q  0
R  9
S  9
T  6
U  0
V  0
W  0
X  0
Y  0
Z  0

Vorlesung am 22.04.2002 in HS4

Adressierungstechniken

Übung 2 am 29.04.2002 - Abgabe am 13.05.2002 - in RZ2/3

Ergänze zunächst die in Übung 1 begonnene Toolbox um folgende drei Routinen : Die Toolbox findet zunächst Anwendung in einem zu entwickelnden Assembler-Programm zur Berechnung (und Ausgabe) des ganzzahlig kaufmännisch gerundeten arithmetischen Mittels für eine beliebige Anzahl einzulesender ganzzahliger positiver Messwerte. Die Messwerterfassung endet bei Eingabe einer beliebigen ganzzahligen negativen Zahl. Nach jeweils fünf eingegebenen Zahlen erfolgt die Ausgabe einer Trennzeile, deren Inhalt beim Programmstart über die Standardeingabe eingelesen wird.

Bitte beachtet die folgenden Randbedingungen :

Eine alternative Formulierung bezüglich der Dezimalzahlen-Eingabe befindet sich in der Aufgabenstellung SoSe 2001.

Vorlesung am 06.05.2002 in HS4

HAUPT.ASM (Wertaufruf und lokale Variablen)
BENNO.ASM (Referenzaufruf)

Übung 3 am 13.05.2002 - Abgabe am 27.05.2002 - in RZ2/3

Entwickle ein Unterprogramm zur Addition zweier Matrizen, deren Elemente aus vorzeichenbehafteten 16-Bit ganzen Zahlen bestehen. Das Unterprogramm besitzt folgende Schnittstelle : Die Parameterübergabe erfolgt über den Stack, wobei beim Referenzaufruf sowohl die Segment- als auch die Offsetadresse des Operanden übergeben wird.

Das Unterprogramm zur Matrizenaddition soll in ein Hauptprogramm folgenden Ablaufs eingebettet werden :

Bei der Dialoggestaltung ist für die einzelnen Ein- und Ausgaben auf eine übersichtliche Textwüste (z.B. aussagekräftige Eingabeaufforderungen) zu achten. Das Einlesen und Ausgeben erfolgt über die Standardeingabe bzw. -ausgabe. Die Reservierung von Speicherplatz für maximal 10x10 dimensionale Matrizen ist ausreichend. Zahlenbereichsüberläufe dürfen wie bereits in der vorherigen Übung erneut weitgehend ignoriert werden.

Übung 4 am 27.05.2002 - Abgabe am 10.06.2002 - in RZ2/3

Übersetze das nachfolgende Pascal-Programm MATRIX möglichst bedeutungstreu in ein 8086-Assembler-Programm (EXE-Format). Gemäß den Konventionen von Turbo-Pascal erfolgt die Parameterübergabe (Wert- und Referenzaufruf) über den Stack, die Ablage lokaler Variablen auf dem Stack und die Rückgabe eines booleschen- bzw. Integer-Wertes via AL- bzw. AX-Register.
Type Dimension = (Zeile,Spalte);
     Matrix = Array [1..10,1..10] Of Integer;

Var Dims : Array[1..3,Dimension] Of Word;
    Mats : Array[1..3] Of Matrix;

Function ReadKey:Char; Assembler;

Asm
  mov ah,8
  int 21h
End;

Function IntRead:Integer;

Var Result:Integer;
    Signed:Boolean;
    Digit:Char;
    First:Boolean;

Begin
  Result := 0;
  Signed := False;
  First := True;
  Repeat
    Digit := ReadKey;
    If (Digit='-') And First Then Begin
      Signed := True;
      First := False;
      Write(Digit)
    End;
    If (Digit>='0') And (Digit<='9') Then Begin
      First := False;
      Result := Result*10+(Ord(Digit)-Ord('0'));
      Write(Digit)
    End
  Until Digit=#13;
  If Signed Then
    Result := -1*Result;
  IntRead := Result
End;

Procedure MatRead(DimX,DimY:Word;Var Mat:Matrix);

Var X,Y:Integer;

Begin
  For Y := 1 to DimY Do
    For X := 1 To DimX Do Begin
      Write('[',Y,',',X,'] = ');
      Mat[X,Y] := IntRead;
      WriteLn
    End
End;

Procedure MatWrite(DimX,DimY:Word; Var Mat:Matrix);

Var X,Y:Integer;

Begin
  For Y := 1 To DimY Do Begin
    For X := 1 to DimX Do
      Write(Mat[X,Y]:8);
    WriteLn
  End
End;

Function MatMult(DimAx,DimAy,DimBx,DimBy:Word;
                 Var DimCx,DimCy:Word;
                 Var MatA,MatB,MatC:Matrix):Boolean;

Var I,X,Y:Word;
    Skalar:Integer;

Begin
  If DimAx = DimBy Then Begin
    MatMult := True;
    DimCx := DimBx;
    DimCy := DimAy;
    For X := 1 To DimCx Do
      For Y := 1 To DimCy Do Begin
        Skalar := 0;
        For I := 1 To DimAx Do
          Skalar := Skalar+MatA[I,Y]*MatB[X,I];
        MatC[X,Y] := Skalar
      End
  End Else
    MatMult := False
End;

Begin
  WriteLn('MATRIZENMULTIPLIKATION');
  Repeat
    Write('Zeilenanzahl 1.Matrix : ');
    Dims[1,Zeile] := IntRead;
    WriteLn
  Until Dims[1,Zeile] In [1..10];
  Repeat
    Write('Spaltenanzahl 1.Matrix & Zeilenanzahl 2.Matrix : ');
    Dims[1,Spalte] := IntRead;
    Dims[2,Zeile] := Dims[1,Spalte];
    WriteLn
  Until Dims[1,Spalte] In [1..10];
  Repeat
    Write('Spaltenanzahl 2. Matrix : ');
    Dims[2,Spalte] := IntRead;
    WriteLn
  Until Dims[2,Spalte] In [1..10];
  WriteLn('1.Matrix :');
  MatRead(Dims[1,Spalte],Dims[1,Zeile],Mats[1]);
  WriteLn('2.Matrix :');
  MatRead(Dims[2,Spalte],Dims[2,Zeile],Mats[2]);
  If MatMult(Dims[1,Spalte],Dims[1,Zeile],
             Dims[2,Spalte],Dims[2,Zeile],
             Dims[3,Spalte],Dims[3,Zeile],
             Mats[1],Mats[2],Mats[3]) Then Begin
    WriteLn('Ergebnismatrix :');
    MatWrite(Dims[3,Spalte],Dims[3,Zeile],Mats[3])
  End Else
    WriteLn('Unexpected Severe Error')
End.

Vorlesung am 03.06.2002 in HS4

Maschinenbefehlsformat - Wir spielen Assembler
Pascal-Assembler-Verknüpfung

Übung 5 am 10.06.2002 - Abgabe am 01.07.2002 - in RZ2/3

Wir kreieren einen Plasma Bildschirm
(Idee und Realisation: Benno Haupt)

In dieser Übung geht es darum, eine Verknüpfung zwischen Assembler und einer Hochsprache zu finden. Wir möchten Euch bitten, in Assembler eine kleine Bibliothek zu schreiben, aus welcher wir von Pascal aus eine Routine zum Berechnen von "Plasma" Bildschirmen aufrufen können.

Diesen "Plasma Bildschirm" werden wir im Grafik Modus verwalten. Dazu müssen wir zuerst uns einmal Gedanken machen, wie der Grafik Modus organisiert ist. Wir liefern Euch zu der zu entwickelnden Bibliothek ein Pascal Rahmen Programm, wo der Grafik Modus schon initialisiert wird (genauere Informationen kann man aus der Ralf Brown Interrupt Liste beziehen, siehe dort unter INT 10h). Der Grafik Bildschirm ist im Arbeitsspeicher an der Segmentadresse $0A000 organisiert, umfaßt dort genau 64KB und ist linear aufgebaut. Linear heißt in diesem Fall, daß direkt nach einer Grafik Zeile die nächste darauf folgt. Ich habe mich für eine Auflösung von 320*200 Pixeln zu 256 Farben entschlossen, mit anderen Worten, die erste Zeile fängt mit dem Offset $0000 an, die zweite folgt hier auf $0140 u.s.w., ein Pixel bzw. Punkt auf dem Bildschirm entspricht genau einem Byte Wert.

Der Plasma Bildschirm setzt auf eine Sinus Tabelle auf, welche ich im Pascal Programm als ein Array hinterlegt habe, welches eine Dimension von 360 Einträgen hat. Zuerst möchte ich auf die Schnittstelle eingehen, diese ist Euch freigestellt, nur folgende Informationen müssen übermittelt werden, einmal Zugriff auf die Sinus Tabelle, einmal die X- sowie Y-Auflösung des angewählten Grafik Modus und zuletzt eine Referenz auf eine Word Variable, die uns als Laufvariable für die Bewegung dienen wird. Implementiert die Schnittstelle im Pascal Programm und benennt die Routine plasma_calc, so wie sie im Hauptprogramm aufgerufen wird.

Der Plasma Algorithmus für die Bibliothek verfolgt folgendes Schema: Zuerst nehmen wir uns die Laufvariable vor, erhöhen diese um einen. Daraufhin überprüfen wir Sie, da sie als eine Art Index für die Sinustabelle herangezogen werden soll, ob sie die Dimension der Tabelle nicht sprengt! Dann definieren wir uns zwei Schleifen, eine Äußere, die im Bereich der vertikalen (Y) Auflösung rückwärts durchläuft, eine zweite, die den Bereich vom letzten Bildpunkt zum ersten auf der horizontalen durchläuft. Innerhalb der äußeren Schleife nehmen wir uns nun ein Byte aus der Sinus Tabelle, durch den vertikalen Schleifenzähler indiziert und merken uns dieses Byte. Achtet an dieser Stelle auf das Offset innerhalb dem Grafik Speicher, da hier das Offset immer auf einen Zeilenanfang gesetzt sein sollte. Darauf folgt die zweite innere Schleife. Auch hier holen wir uns ein Byte aus der Sinus Tabelle, indiziert durch den inneren Schleifenzähler. Dieses Byte halten wir auch fest. Nun nehmen wir uns den Wert des inneren Schleifenzählers, auf diesen Wert addieren wir den Counter, achten wiederum, ob das Resultat als Index für die Sinus Tabelle noch gültig ist, verändern aber nicht den Schleifenzähler selber! Auf das zuvor von der inneren Schleife gemerkte Byte addieren wir jetzt ein weiteres aus der Sinus Tabelle auf, indiziert durch den gerade zuvor errechneten Wert. Auf diese Summe kommt noch einmal der Wert aus der äußeren Schleife aufaddiert, so daß wir diesen Wert zu aller letzt noch einmal durch 4 teilen müssen. Das daraus resultierende Ergebnis wird nun in den Grafik Bildschirm geschrieben, die Ausgabe der Grafik Bildpunkte erfolgt von der linken oberen Ecke linksbündig, Zeile für Zeile.

Program Test_Plasma;

{$G+}

uses crt;

Const Sin_Tab    : Array[0..359] of byte =

                 ( 128,130,132,134,136,139,141,143,
                   145,147,150,152,154,156,158,160,
                   163,165,167,169,171,173,175,177,
                   179,181,183,185,187,189,191,193,
                   195,197,199,200,202,204,206,207,
                   209,211,212,214,216,217,219,220,
                   222,223,225,226,228,229,230,232,
                   233,234,235,236,237,239,240,241,
                   242,243,244,244,245,246,247,248,
                   248,249,250,250,251,251,252,252,
                   253,253,253,254,254,254,254,254,
                   254,254,255,254,254,254,254,254,
                   254,254,253,253,253,252,252,251,
                   251,250,250,249,248,248,247,246,
                   245,244,244,243,242,241,240,239,
                   237,236,235,234,233,232,230,229,
                   228,226,225,223,222,220,219,217,
                   216,214,212,211,209,207,206,204,
                   202,200,199,197,195,193,191,189,
                   187,185,183,181,179,177,175,173,
                   171,169,167,165,163,160,158,156,
                   154,152,150,147,145,143,141,139,
                   136,134,132,130,128,125,123,121,
                   119,116,114,112,110,108,105,103,
                   101,099,097,095,092,090,088,086,
                   084,082,080,078,076,074,072,070,
                   068,066,064,062,060,058,056,055,
                   053,051,049,048,046,044,043,041,
                   039,038,036,035,033,032,030,029,
                   027,026,025,023,022,021,020,019,
                   018,016,015,014,013,012,011,011,
                   010,009,008,007,007,006,005,005,
                   004,004,003,003,002,002,002,001,
                   001,001,001,001,001,001,001,001,
                   001,001,001,001,001,001,002,002,
                   002,003,003,004,004,005,005,006,
                   007,007,008,009,010,011,011,012,
                   013,014,015,016,018,019,020,021,
                   022,023,025,026,027,029,030,032,
                   033,035,036,038,039,041,043,044,
                   046,048,049,051,053,055,056,058,
                   060,062,064,066,068,070,072,074,
                   076,078,080,082,084,086,088,090,
                   092,095,097,099,101,103,105,108,
                   110,112,114,116,119,121,123,125);

{ Deklaration & Einbindung der zu entwickelnden Prozedur }

var oldmode:integer;
    counter:word;

begin

oldmode:=lastmode;
counter:=0;

asm
  mov ax,13h
  int 10h
end;

repeat

  plasma_calc(@sin_tab,counter,320,200);

until keypressed;

textmode(oldmode);

readln;

end.

Vorlesung am 17.06.2002 in HS4

Stringverarbeitung

Vorlesung am 24.06.2002 in HS4

"Ein Kessel Buntes"

Übung 6 am 01.07.2002 in RZ2/3

Probeklausur ausnahmsweise LIVE am Rechner