Übungsblatt 4: Prozeduren und Funktionen

Thema dieser Übung ist die Programmierung von Prozeduren in Assembler. Wir verwenden hierfür wieder Jasmin.

Aufgabe 1: Polynomauswertung mit Prozedur

  1. Implementieren Sie die in der Vorlesung erläuterte Polynomauswertung mit Hilfe einer Prozedur.

    Schreiben Sie zum Testen der Prozedur ein aus einigen MOV-Befehlen bestehendes Pseudo-Hauptprogramm. Im Hauptprogramm sollen einige Werte in die Register AX bis DX geschrieben werden. Betten Sie den Aufruf der Prozedur in diese MOV-Befehle ein. Auf diese Weise können Sie den Sprung in die Prozedur und zurück in das Hauptprogramm besser beobachten. Label werden in Jasmin durch Doppelpunkte kenntlich gemacht.

    Wenn Sie alles richtig gemacht haben, sollte das im AX-Register angezeigte dezimale Ergebnis nach dem Rücksprung aus der Prozedur wieder 342 lauten. Führen Sie das Programm danach ein zweites Mal aus und beobachten Sie beim Sprung in die Prozedur das Stapelzeigerregister (engl.: stack pointer). Die untenstehende Grafik zeigt, wo die Werte des Stapelzeigerregisters in Jasmin angezeigt werden (Abb. 1).

    Sie werden feststellen, dass beim Sprung in die Prozedur der Wert des Stapelzeigerregisters dekrementiert und dieser beim Rücksprung in das Hauptprogramm inkrementiert wird. Warum passiert das?

    Stapelzeigerregister

    Abb.1: Stapelzeigerregister

  2. Modifizieren Sie jetzt ihren Assemblercode in der Weise, dass, wie in der Vorlesung beschrieben, der Wert des BX-Registers in der Prozedur auf den Stapel gerettet und am Ende der Prozedur wieder restauriert wird. (Speichern Sie ihr bisheriges Ergebnis ggf. vorher unter einem neuen Namen ab.) Schreiben Sie zu diesem Zweck, falls noch nicht geschehen, vor dem Prozeduraufruf einen Wert in das BX-Register, führen Sie das Programm aus und prüfen Sie, ob dieser Wert nach dem Prozeduraufruf wieder im BX-Register steht.

    Führen Sie das Programm erneut aus und beobachten Sie beim Sprung in die Prozedur sowie beim Retten des BX-Registerwerts den stack pointer. Was stellen Sie fest?

    Prüfen Sie auch hier jeweils die Korrektheit des Ergebnisses der Berechnung an Hand des Werts im AX-Register.

  3. Erweitern Sie nun die Prozedur so, dass die Werte der Register AX bis DX auf den Stapel gerettet werden und somit ein vollständiger Kontextwechsel durchgeführt wird. Stellen Sie sicher, dass vor dem Prozeduraufruf definierte Werte in die Register geschrieben und diese nach dem Rücksprung aus der Prozedur korrekt wiederhergestellt werden. Betrachten Sie auch hier während der Programmausführung den stack pointer.

  4. Überarbeiten Sie ihre Ergebnisse aus der letzten Übung in der Weise, dass die Parameterwerte a0 bis a3 sowie der Wert von x wie in der Vorlesung mit Hilfe des Stapels an die Prozedur übergeben werden. Retten Sie auch hier die Werte der Register AX bis DX in der Prozedur auf den Stapel und liefern Sie das Ergebnis der Polynomauswertung, wie in der Vorlesung demonstriert, auf dem Stapel an das aufrufende Programm zurück. Beobachten Sie bei der Ausführung des Programms den Wert des Basiszeigerregisters BP (engl.: base pointer). Die untenstehende Grafik zeigt, wo die Werte des Basisregisters in Jasmin angezeigt werden (Abb. 2).

    Prüfen Sie wie üblich, ob die Registerwerte nach der Berechnung korrekt restauriert wurden und das Ergebnis der Berechnung stimmt.

    Basiszeigerregister

    Abb.2: Basiszeigerregister

Aufgabe 2: Produkt der ersten N natürlichen Zahlen

Schreiben Sie eine Funktion für die Berechnung des Produkts der ersten N natürlichen Zahlen. N soll als Funktionsparameter mit Hilfe des Stapels übergeben werden. Die Funktion soll alle Registerwerte der benutzten Register retten und am Ende wieder herstellen.

Die Funktion soll das Ergebnis ebenfalls mit Hilfe des Stapels an das aufrufende Hauptprogramm liefern. Schreiben Sie zu ihrer Funktion ein Hauptprogramm und prüfen Sie ihre Funktion für ein paar Eingabewerte, z. B. N=3 und N=10. Da das Produkt recht schnell sehr große Werte annehmen kann, ist es sinnvoll, die erweiterten Register zu benutzen. Lesen Sie jeweils den zurückgegebenen Wert entsprechend in das EAX- Register ein. Wenn ihre Funktion korrekt arbeitet, liefern die beiden Eingabewerte oben 6 und 3628800. Prüfen Sie ebenfalls, ob die Registerwerte korrekt wiederhergestellt werden.

Aufgabe 3: Gerade oder ungerade Zahl

Schreiben Sie eine Funktion, die überprüft, ob eine mit Hilfe des Stapels übergebene Zahl ungerade oder gerade ist. Bei ungeraden Zahlen liefert die Funktion eine 1 auf dem Stapel zurück, bei geraden Zahlen eine 0. Retten Sie in der Funktion wieder den Kontext.

Schreiben Sie zu ihrer Funktion wieder ein Hauptprogramm und prüfen Sie ihre Funktion für ein paar Eingabewerte, z. B. 3 und 10. Laden Sie jeweils den zurückgegebenen Wert in das AX- Register. Wenn ihre Funktion korrekt arbeitet, liefern die beiden Eingabewerte oben 1 und 0. Prüfen Sie ebenfalls wieder, ob alle benutzten Register korrekt wiederhergestellt werden.

Aufgabe 4: Positive oder negative Zahl

Schreiben Sie eine Variante der Funktion aus der letzten Aufgabe, die überprüft, ob eine mit Hilfe des Stapels übergebene Zahl negativ oder positiv ist. Bei negativen Zahlen liefert die Funktion eine -1 auf dem Stapel zurück, bei positiven Zahlen eine 1. Retten Sie in der Funktion wieder den Kontext.

Schreiben Sie zu ihrer Funktion ein Hauptprogramm und prüfen Sie ihre Funktion für ein paar Eingabewerte, z. B. -3 und 10. Laden Sie jeweils den zurückgegebenen Wert in das AX- Register. Wenn ihre Funktion korrekt arbeitet, liefern die beiden Eingabewerte oben -1 und 1. Prüfen Sie ebenfalls wieder, ob alle benutzten Register korrekt wiederhergestellt werden.

Aufgabe 5: Mehrwertsteuer berechnen

Schreiben Sie eine Funktion zur Berechnung der für eine Ware zu entrichtenden Mehrwertsteuer. Die Funktion erhält als Parameter auf dem Stapel den Verkaufspreis der Ware sowie den Mehrwertsteuersatz und liefert die Höhe der Mehrwertsteuer auf dem Stapel zurück. Da die Mehrwertsteuer zumeist eine Kommazahl ist, wird sie als ganzzahliger Quotient plus Rest, d. h. in Form zweier Zahlen auf dem Stapel zurückgeliefert. Retten Sie wie üblich in der Funktion den Kontext.

Schreiben Sie zu ihrer Funktion ein Hauptprogramm und prüfen Sie ihre Funktion für ein paar Eingabewerte, z. B. für die Preise 10 und 30 und den Mehrwertsteuersatz 19%. Lesen Sie jeweils die zurückgegebenen Werte für den Quotienten und Rest in das AX- und BX-Register ein. Wenn ihre Funktion korrekt arbeitet, liefern die beiden Eingabewerte oben 1,90 und 5,70. Prüfen Sie ebenfalls wieder, ob alle benutzten Register korrekt wiederhergestellt werden.