#format rst #language de ========================================= Übungen im Fach Systemnahe Programmierung ========================================= Die Übungen werden in Gruppen durchgeführt. Die Gruppeneinteilung machen wir mit Moodle. Es wird insgesamt 10 Übungsblätter geben, die Sie schriftlich bearbeiten und in Gitlab abgeben. Jede Gruppe bekommt dazu auf Gitlab ein "Repository" zugeteilt. Bei der schriftlichen Abgabe habe ich folgende Randbedingungen. Sie schreiben den Text in einer Markup-Sprache wie `Restructured Text (ReST) `_ oder `Markdown `_. Es gibt dazu Werkzeuge wie `Sphinx `_, `MkDocs `_, `Pandoc `_ oder die `Python docutils `_. Welches Sie verwenden, ist Ihre Sache. Es muss in Ihrem Repository des Berichtes ein *Makefile* geben, das die Markup-Dateien durch den Aufruf von ``make html`` nach HTML umwandelt. Der HTML-Output muss nicht im Repository verwaltet werden, sondern nur die Quelldateien. * Moodle-Kurs https://moodle.hs-augsburg.de/course/view.php?id=2806 * Gitlab Repositories der Gruppen: https://r-n-d.informatik.hs-augsburg.de:8080/snp * Beispielcode aus PGU-Book und anderes: https://r-n-d.informatik.hs-augsburg.de:8080/hubert.hoegl/sysprog Übung1_ | Übung2_ | Übung3_ | Übung4_ | Übung5_ | Übung6_ | Übung7_ | Übung8_ .. _Übung1: Übung 1 ======= 1. Aufgabe ---------- **(a)** Machen Sie sich mit der Linux Arbeitsumgebung vertraut, so dass Sie * ein Terminalfenster öffnen können. Das nennt man auch "Konsole". Im Terminalfenster wartet eine Kommandointerpreter - die "Shell" - auf Eingaben. Die Shell ist fast immer die "bash", das ist eine moderne Variante der alten "sh". * im Terminalfenster eine handvoll ganz elementare Kommandos zur Arbeit mit dem Dateisystem anwenden können: `cd`, `ls`, `mkdir`, `rmdir`, `mv`, `cp`, `rm`. * einen Editor bedienen können. Es gibt Vi, Vim, Emacs, Gedit und viele andere. * ein Makefile verstehen. * die "man" Seiten aufrufen können. Das ist das Hilfesystem, das es auf jedem Unix gibt. Schreiben Sie in Ihre Ausarbeitung, wie Sie mit Linux arbeiten. Sollten die Gruppenmitglieder unterschiedlich arbeiten, dann sollten alle Ihre individuelle Arbeitsweise schildern. * Welche Linux Distribution verwenden Sie? * Ist diese real oder virtuell installiert? Falls virtuell, welches Host-Betriebssystem verwenden Sie? * Können Sie die typischen Datei- und Verzeichnisoperationen wie anlegen, kopieren, löschen, umbenennen, bewegen auf der Kommandozeile erledigen oder brauchen Sie dazu einen grafischen Datei-Manager? * Welche Kommandos benutzen Sie auf der Kommandozeile? * Welche Shell verwenden Sie? * Welchen Editor verwenden Sie? * Kennen Sie den `LPIC Kurs `_? Haben Sie ihn schon besucht? **(b)** Finden Sie heraus, welche genaue Bezeichnung die CPU in Ihrem Rechner (bzw. in der Virtuellen Maschine) hat. Arbeitet Ihr Rechner im 32- oder im 64-Bit Modus? 2. Aufgabe ---------- **(a)** Welche Anwendungsbereiche für systemnahe Programmierung kennen Sie? **(b)** Worin unterscheiden sich Programmiersprachen die sich zur maschinennahen (= systemnahen) Programmierung eignen von Sprachen, die man "high-level" Sprachen nennt? **(c)** Nennen Sie zwei high-level Sprachen und zwei maschinennahe Sprachen. 3. Aufgabe ---------- Lesen Sie die Kapitel 1 und 2 im Buch von Bartlett. Beantworten Sie die Fragen am Ende des zweiten Kapitels. ---- .. _Übung2: Übung 2 ======= **Bitte machen Sie einen Update des "sysprog" Repositories! Geben Sie dazu in Ihrer Arbeitskopie das Kommando "git pull" ein.** 1. Aufgabe ---------- Zum Experimentieren mit den Adressierungsarten finden sie im Kurs-Repository den Ordner ``asm/01-addr/``. Mit dem ``gdb`` sollten Sie überprüfen, welche Daten adressiert werden und die Erkenntnisse auch in der Abgabe festhalten. Sie finden im Ordner auch einen mit "Asciinema" (http://asciinema.org) gemachten Terminal-Cast, der eine Terminal-Sitzung mit dem GDB zeigt. Lesen Sie ``README``. 2. Aufgabe ---------- Der Ordner ``asm/02-branches/`` enthält ein Programm mit ein paar bedingten Sprüngen. Finden Sie mit ``gdb`` heraus, welchen Pfad die Programmausführung nimmt und notieren Sie das auch in Ihrer Abgabe. Sie finden im Ordner auch einen mit "Asciinema" (http://asciinema.org) gemachten Terminal-Cast, der eine Terminal-Sitzung mit dem GDB zeigt. Lesen Sie ``README``. 3. Aufgabe ---------- Holen Sie sich das erste im Buch von Bartlett erwähnte Programm:: pgu/prog-3-1/ Wechseln Sie in diesen Ordner und "spielen" Sie mit dem Programm. Das Programm wird im Bartlett in Kapitel 3 erläutert. * Kompilieren und starten Sie das Programm. * Sehen Sie sich den Rückgabewert an. Das Shell-Kommando lautet ``echo $?``. * Verändern Sie den Rückgabewert im Programm, kompilieren es mit ``make`` und starten es erneut. Ist der Rückgabewert nun anders? * Sie finden dort auch eine Implementierung in C (``main.c``) und eine in Python (``main.py``). Sehen Sie sich die Quelltexte an und versuchen Sie die Programme auszuführen. 4. Aufgabe ---------- Untersuchen Sie die in PGU Kapitel 3 beschriebene Maximum-Suche Zeile für Zeile, so wie im Buch beschrieben. Sie finden das Programm im Repository unter :: pgu/prog-3-2 Verwenden Sie den **GNU Debugger** ``gdb`` zum Erforschen des Programmablaufs. Hier ist eine Anleitung: * Erster Kontakt mit GDB (am Beispiel "maximum") http://hhoegl.informatik.hs-augsburg.de/sysprog/gdb/gdb.html * Noch ein Versuch für eine GDB Anleitung, verwendet ein eigenes Beispiel: http://hhoegl.informatik.hs-augsburg.de/sysprog/gdb_anleitung/gdb_anleitung.html Alle Dateien zu diesem Beispiel finden Sie auch im Git Repository unter ``gdb_anleitung/``. Siehe dort auch die GDB Schnellreferenz ``quickref.txt`` sowie ``quickref.ps``. Es gibt auch ein Buch zum Thema Debuggen mit GDB: * Norman Matloff, Peter Jay Salzman, The Art of Debugging with GDB and DDD https://proquest.safaribooksonline.com/book/software-engineering-and-development/ide/9781593271749 Es gibt in dem Verzeichnis nun auch zwei verschiedenen Python Implementierungen, ``maximum1.py`` und ``maximum2.py``. Sie sollten sich den Quelltext ansehen und die Programme laufen lassen. **Beantworten Sie die Fragen am Ende von Kapitel 3 im Buch ("Know the Concents", "Use the Concepts", "Going Further").** ---- .. _Übung3: Übung 3 ======= (25.10.2019) **Bitte machen Sie einen Update des "sysprog" Repositories! Geben Sie dazu in Ihrer Arbeitskopie das Kommando "git pull" ein.** Aufgabe 1 --------- Wer es noch nicht erledigt hat: *Use the concepts* am Ende von Kapitel 3 bearbeiten. Hier geht es um die Maximum-Suche. Der Code ist in ``prog-3-2/maximum.s``. 1. Modifizieren Sie das Programm so dass es den Wert 3 zurück gibt. 2. Modifizieren Sie das Programm so dass es das Minimum statt des Maximum zurück gibt. 3. Modifizieren Sie das Programm so dass die Zahl 255 das Array beendet und nicht die Zahl 0. 4. Modifizieren Sie das Programm so dass es eine Ende-Adresse für das Array gibt (nicht den abschliessenden Wert 0). 5. Modifizieren Sie das Programm so dass es einen Längenzähler für das Array gibt (nicht den abschliessenden Wert 0). 6. Wo ist der Unterschied zwischen folgenden beiden Zeilen: * ``movl _start, %eax`` * ``movl $_start, %eax`` 2. Aufgabe ---------- Sie finden im Kurs-Repository den neuen Ordner ``asm/03-fct1`` (git pull!). Er enthält eine einfache Funktion, die mit einem Argument auf dem Stack aufgerufen wird. Die Funktion macht nichts und kehrt einfach zur Aufrufstelle zurück. Im Quelltext ``main.s`` finden Sie ein paar Kommentare mit Aufgaben (1) bis (6). Sie sollen mit GDB das Programm laufen lassen und durch Eingabe von GDB Kommandos die Fragen beantworten. 3. Aufgabe ---------- Lesen Sie im PGUBook das vierte Kapitel. Die rekursiven Funktionen können Sie erst mal weglassen. .. _Übung4: Übung 4 ======= (8.11.2019) Aufgabe 1 --------- (aus einer Klausur) Wozu braucht man einen Stack? Über welche Befehle spricht man den Stack an? Aufgabe 2 --------- (aus einer Klausur) Sehen Sie sich folgenden Assembler-Quelltext an. Die drei Punkte ``...`` stehen für beliebigen Code, der uns nicht interessiert. Beantworten Sie bitte folgende Fragen: * Beschreiben Sie, was an den Stellen (1) bis (7) gemacht wird. * Zeichnen Sie den Stack direkt nach der Ausführung von Zeile 5. Zeichnen Sie auch Framepointer und Stackpointer ein. * Wie greift man innerhalb der Funktion ``tuwas()`` auf die lokalen Daten zu? Nehmen Sie an, dass die 8 Byte aus zwei Integer Werten bestehen. Schreiben Sie die Framepointer-relative Adressierung für den Integer mit der kleineren Adresse hin. :: ...` pushl $2 # (1) pushl $4 # (1) call tuwas # (2) addl $8, %esp # (3) ... :: tuwas: pushl %ebp # (4) movl %esp, %ebp # (4) subl $8, %esp # (5) ... movl %ebp, %esp # (6) popl %ebp # (6) ret # (7) Aufgabe 3 ---------- (aus einer Klausur) Hier sind einige Fragen zur C Aufrufkonvention: * In welcher Reihenfolge werden die Argumente der Funktion ``cfun(int a, int b, int c)`` auf dem Stack abgelegt? * Wie wird der Rückgabewert einer Funktion an den Aufrufer übergeben? Unterscheiden Sie: (a) der Wert ist 32-Bit gross, (b) der Wert ist grösser als 32-Bit. * Wer kümmert sich um die Sicherung der Register -- der Aufrufer oder der Aufgerufene? * Wer korrigiert den Stack, der Aufrufer oder der Aufgerufene? Aufgabe 4 --------- Analysieren Sie die Funktionsweise des Beispiels "power" aus dem Kapitel 4 ("All About Functions") mit dem GNU Debugger, so wie wir das in der Vorlesung gemacht haben. Aufgabe 5 --------- (aus "Use the Concepts" am Ende von Kapitel 4) 1. Schreiben Sie eine Funktion ``quadrat(x)``, die aus dem Argument ``x`` das Quadrat ``x * x`` berechnet. Rufen Sie diese Funktion zum Test auch ein paar Mal mit unterschiedlichem Argument auf. 2. Schreiben Sie die Maximumsuche aus dem Kapitel 3 nun als Funktion ``maximum(ptr)``. Der Zeiger ``ptr`` zeigt auf eine Liste von Elementen, deren grösster Wert zurückgegeben wird. Rufen Sie diese Funktion zum Test ein paar Mal mit unterschiedlichen Listen auf. .. _Übung5: Übung 5 ======= (16.11.2019) Aufgabe 1 --------- Vollziehen Sie das im Kapitel 5 (Bartlett) beschriebene ``toupper`` Programm mit dem Debugger ``gdb`` nach.. Der Quelltext dieses Programms ist in ``pgu/prog-5/``. Sollten Sie es noch nicht schon gemacht haben, dann legen Sie in Ihrem Home-Verzeichnis (``~``) die Datei ``~/.gdbinit`` an. Darin ist nur die einzige Zeile:: set auto-load safe-path / Danach können Sie in ``pgu/prog-5/`` einfach ``gdb`` aufrufen und der GNU Debugger startet. Machen Sie das Terminal-Fenster gross, damit Sie alle Register sehen. Aufgabe 2 --------- Schreiben Sie das ``toupper`` Programm neu in Python. Nennen Sie das Programm ``toupper_os.py``. Verwenden Sie die low-level File-Funktionen open(), read(), write() und close() im Modul ``os``. Die Kommandozeilenargumente bekommen Sie über ``sys.argv``. Den Zahlenwert eines Zeichen bekommen Sie mit ``ord(c)``, eine Zahl in ein Zeichen wandeln Sie mit ``chr(z)``. Schreiben Sie ein zweites Python-Programm ``toupper.py``, das die in Python üblicherweise verwendeten Dateifunktionen nutzt, also die eingebaute ``open()`` Funktion, die ein File-Objekt zurückliefert (keinen File-Deskriptor). Zum Konvertieren des Strings verwenden Sie die ``toupper`` Methode auf Strings. Versuchen Sie ein möglichst kurzes Programm zu schreiben. Aufgabe 3 --------- Bearbeiten Sie die Aufgaben * Know the concepts * Use the concepts am Ende von Kapitel 5 im Bartlett. Der Abschnitt *Going Further* ist freiwillig. .. _Übung6: Übung 6 ======= (25.11.2019) Aufgabe 1 --------- Schreiben Sie ein Programm in Assembler, das die Anzahl der Zeichen und die Anzahl der Zeilen in einer Textdatei bestimmt und auf den Bildschirm (stdout) schreibt. Der Name der Datei wird als Argument an das Programm übergeben. Aufgabe 2 --------- Wie ist das Programm im Bartlett in Kapitel 6 strukturiert? Zeichnen Sie in einem Diagramm die Abhängigkeiten der einzelnen Dateien. Mit ``A ==> B`` kennzeichnen Sie, dass Datei B die Quelldatei A inkludiert. Mit ``A + B`` drücken Sie aus, dass die Objektdateien A und B miteinander gelinkt werden. Aufgabe 3 --------- Diese Aufgaben sind eine eingeschränkte Auswahl der "Going Further" Aufgaben am Ende von Kapitel 6: 1. Schreiben Sie das Programm um, so dass Kommandozeilenargumente verwendet werden. 2. Fangen Sie Fehler ab, die beim Öffnen der Dateien auftreten können. Welche Fehlercodes es gibt, finden Sie in der man page ``man 2 open``. Behandeln Sie einen Schreischutzfehler, der auftritt, wenn Sie die Datei als normaler Anwender an einem nicht erlaubten Ort öffnen, z.B. mit dem Pfad ``/meine_datei.txt``. 3. Schreiben Sie ein Programm, mit dem Sie auswählen können, welcher Datensatz ausgegeben werden soll. Sie geben auf der Kommandozeile die Nummer 0, 1, 2, ... an, dann wird der jeweilige Datensatz ausgegeben. Mit dem Systemaufruf ``lseek()`` können Sie schnell an eine beliebige Stelle in der Datei gehen. Der Funktionscode für ``lseek()`` in Register eax ist 19. Siehe ``man 2 lseek``. .. _Übung7: Übung 7 ======= Aufgabe 1 --------- Fügen Sie zu dem ``add-year`` Programm aus PGU Kapitel 7 einen Fehlerabbruch mit ``error-exit.s`` nach jedem System-Call hinzu. Aufgabe 2 --------- 1. Vollziehen Sie praktisch nach, wie im Kapitel 8 aus ``write-record.s`` und ``read-record.s`` eine dynamische Bibliothek gemacht wird. Wie lautet das Kommando zum dynamischen Linken? #. Was macht das ``ldd`` Kommando? #. Experimentieren Sie mit der Umgebungsvariablen LD_LIBRARY_PATH. Dazu sollten Sie die zu ladende dynamische Bibliothek in ein beliebiges Verzeichnis stecken und dann das Hauptprogramm in einem anderen Verzeichnis starten. Was müssen Sie machen, damit die Bibliothek gefunden wird? #. Was bedeuten die folgenden Zeilen in der Sprache C? :: a) typedef int int32_t; b) typedef short int16_t; b) int f1(char c, int i, float f); c) int32_t f2(int32_t *ip); d) int *f3(char *cp); e) int f4(double d); f) int f5(int16_t si); In der Literaturangabe http://hhoegl.informatik.hs-augsburg.de/hhwiki/SysProg#literatur finden Sie auch Texte zur Sprache *C*. #. Schreiben Sie das ``toupper`` Programm um so dass die C Bibliotheksfunktionen für die Fileoperationen verwendet werden. Hier sind noch zwei gute freie Texte zum Thema **dynamisches Linken**, für die, die es ganz genau wissen wollen: * David Beazley, The inside story on shared libraries and dynamic loading, 7 Seiten, 2001. http://hhoegl.informatik.hs-augsburg.de/sysprog/Beazley-Dynamic-Loading.pdf * Ulrich Drepper, How To Write Shared Libraries, 47 Seiten, 2006. http://www.akkadia.org/drepper/dsohowto.pdf .. _Übung8: Übung 8 ======= Fragen zu Kapitel 9, "Intermediate Memory Topics" 1. Beantworten Sie alle Fragen in *Know the Concepts*. 2. Vollziehen Sie das Beispiel der Heap-Verwaltung im Bartlett, Kapitel 9 auf Ihrem Rechner nach. 3. Wenden Sie diesen Allokator auf das Beispiel in Kapitel 6 (read records) an. 4. Schreiben Sie diese Heap-Verwaltung in einer Hochsprache (Python, Java, C). Versuchen Sie den Allokator in der Hochsprache so zu ändern, dass er Regionen aufspaltet, wenn die angeforderte Grösse kleiner ist als die aktuelle freie Region. 5. Die Abschnitte *Use the Concepts* und *Going Further* dürfen gerne zusätzlich bearbeitet werden, sind aber nicht Pflicht.