Diese Seite habe ich ins Leben gerufen, weil es für die Technische Informatik 2 leider keine praktischen Assembler-Beispiele gibt. Vieles davon musste ich leider selber herausfinden, das hat ne Menge Zeit gekostet. Ich hoffe aber, dass sich es ein wenig gelohnt hat (ich hab auch viel dabei gelernt) - zumindest hat man jetzt eine Basis an Code, der wirklich funktioniert (sic!). Die Beispiele im TI2-Skript funktionieren leider nicht wirklich...
Alle Code-Beipsiele sind in GNU-Assembler abgefasst (als Flame nebenbei: Intel-ASM ist wirklich eine Krankheit u.a. wegen der fehlenden Kontrolle über die Opcodes, die daraus generiert werden, Stichwort Longjumps...). Jedes der Codestücke steht unter der GNU General Public License. Mit Download wird diese anerkannt. Blablabla. Wenn ich noch etwas Zeit habe stelle ich eventuell eigene Seiten dafür ins Netz oder mach noch einige Codebeispiele (wenn sich nette Einträge im Gästebuch finden, hehe). Ansonsten ist der Code wirklich gut kommentiert und in verschiedene Schwierigkeitsstufen eingeteilt.
Obwohl ich das ganze für die Informatiker mache, hier ein Paar Tipps, wie man das zum Laufen bringt:
Die Dateien sind heruntergeladen:acer joe [~/tmp]: ls insgesamt 12K -rw-r--r-- 1 joe users 14K 30.08.2004 02:44:40 x86asm-0.04.tar.bz2Nun entpacken:
acer joe [~/tmp]: tar xfvj x86asm-0.01.tar.bz2 x86asm-0.01/ x86asm-0.01/01_plusminus.S x86asm-0.01/02_aufsummieren.S x86asm-0.01/03_aufsummieren_ungerade.S x86asm-0.01/04_stack.S x86asm-0.01/helper_functions.S x86asm-0.01/Makefile x86asm-0.01/05_funktion.S x86asm-0.01/06_funktion_rekursion.S x86asm-0.01/LICENSE x86asm-0.01/README x86asm-0.01/CHANGELOG acer joe [~/tmp]: cd x86asm-0.01 acer joe [~/tmp/x86asm-0.01]: ls insgesamt 60K -rw-r--r-- 1 joe users 556 19.08.2004 07:51:10 01_plusminus.S -rw-r--r-- 1 joe users 663 19.08.2004 07:51:05 02_aufsummieren.S -rw-r--r-- 1 joe users 1,1K 19.08.2004 07:51:52 03_aufsummieren_ungerade.S -rw-r--r-- 1 joe users 1,2K 19.08.2004 07:57:25 04_stack.S -rw-r--r-- 1 joe users 1,2K 19.08.2004 07:48:27 05_funktion.S -rw-r--r-- 1 joe users 1,9K 19.08.2004 08:14:01 06_funktion_rekursion.S -rw-r--r-- 1 joe users 65 19.08.2004 08:42:54 CHANGELOG -rw-r--r-- 1 joe users 1,4K 19.08.2004 07:48:14 helper_functions.S -rw-r--r-- 1 joe users 18K 19.08.2004 08:42:32 LICENSE -rw-r--r-- 1 joe users 388 19.08.2004 08:39:58 Makefile -rw-r--r-- 1 joe users 188 19.08.2004 08:42:11 READMEUnd dann "make" machen, das wars schon!
acer joe [~/tmp/x86asm-0.01]: make gcc -c -o helper_functions.o helper_functions.S gcc -c -o 01_plusminus.o 01_plusminus.S gcc -c -o 02_aufsummieren.o 02_aufsummieren.S gcc -c -o 03_aufsummieren_ungerade.o 03_aufsummieren_ungerade.S gcc -c -o 04_stack.o 04_stack.S gcc -c -o 05_funktion.o 05_funktion.S gcc -c -o 06_funktion_rekursion.o 06_funktion_rekursion.S gcc -Wall -O2 -o 01_plusminus 01_plusminus.o helper_functions.o gcc -Wall -O2 -o 02_aufsummieren 02_aufsummieren.o helper_functions.o gcc -Wall -O2 -o 03_aufsummieren_ungerade 03_aufsummieren_ungerade.o helper_functions.o gcc -Wall -O2 -o 04_stack 04_stack.o helper_functions.o gcc -Wall -O2 -o 05_funktion 05_funktion.o helper_functions.o gcc -Wall -O2 -o 06_funktion_rekursion 06_funktion_rekursion.o helper_functions.o acer joe [~/tmp/x86asm-0.01]:Noch eine kleine Übersicht der mitgelieferten Programme:
| Name | Beschreibung |
| 01_plusminus | Löst die Aufgabe, die in den Übungen durchgesprochen wurde (17x-15y berechnen) |
| 02_aufsummieren | Ein Beispiel für Schleifen: Die Zahlen von X bis Y sollen aufsummiert werden |
| 03_aufsummieren_ungerade | Ein Beispiel für konditionierte Schleifen: Die ungeraden Zahlen von X bis Y sollen aufsummiert werden |
| 04_stack | Spielereien mit dem Stack: Zahlen werden ge-pushl-d und dann aufsummiert |
| 05_funktion | Einfache Funktion mit 3 Parametern, die über den Stack übergeben werden |
| 06_funktion_rekursiv | Rekursive Funktion, die die Zahlen von 1..n aufsummiert |
| 07_matrixmultiplikation | Multipliziert eine 2x3 mit einer 3x2-Matrix. Das funktioniert wirklich! Sehr cool. |
| 08_malloc | Holt Speicher aus dem Heap und macht diesen zugreifbar. |
| 09_hints1 | Vergleich zwischen "movl $0, %eax" und "xorl %eax, %eax" |
| 10_hints2 | Vergleich zwischen "cmp $0, %eax" und "test %eax, %eax" |
| 11_hints3 | Vergleich zwischen einer normalen Schleife und einer Schleife, die das "loop" Kommando verwendet. Auch Erklärung der Opcodes als Kommentar (relative Jumps und Calls) |
| 12_float | Zeigt, wie man die Flißkommaoperationen des Prozessors nutzen kann, um zwei Fließkommazahlen miteinander zu multiplizieren und gibt diese dann aus. Zur Berechnung der Fließkommazahlen selbst habe ich einen wirklich ausführlichen Kommentar mit in den Quellcode eingefügt (länger als der Code selber). Interessant für alle, die nocheinmal gerne wissen wollen, wie man Dezimalbrüche in IEEE-754 Floats umwandelt. |
| 13_rorl | Klausuraufgabe Juli 2003, Aufgabe 2b. Mit Erklärung des "rorl" Befehls. |
| 14_call | Wie ist ein "call" sauber zu implementieren? Wie kann man das "unsauber" machen? |
| 15_callpop | Klausuraufgabe, in der zuerst ein "call" gemacht wird, dann die Rücksprungadresse ge-popl-ed wird und damit ein bischen rumgerechnet. |
| 16_cmp | Beispiel, dass die verschiedenen Sprungarten ja, jb (unsigniert) mit jg, jl (signiert) vergleicht. |
| 17_forloop | Eine einfache for-Schleife |
| 18_ggt | Euklids Algorithmus zur Bestimmung des GGT (ehemalige Klausuraufgabe) |
| 19_modulo | Ehemalige Klausuraufgabe: Einen möglichst einfachen Modulo-10-Rechner in Assembler basteln. Meine Lösung als C-Source (modulo.c) und Assembler (19_modulo.S). |
| helper_functions | Hilfsfunktionen, die ich benutze, und die sehr nützlich sein könnten, wenn man seinen eigenen Code debuggen muss. Im Übrigen wird hier auch gezeigt, wie man in Assembler verschiedene Programmteile in Module aufsplitten kann und wie diese dann zusammengelinkt werden. Ein Blick ins Makefile verrät mehr. |
Zum Linken der Dateien sei folgendes angemerkt: ich verwende zum kompilieren des Assembler-Codes den gcc! Ursprünglich habe ich mit dem as und dem ld herumgespielt, habe es allerdings auch nach stundenlangen Versuchen (!) nicht hinbekommen. Auch wenn es im Skript so einfach toll drinsteht, bei mir ist immer folgendes passiert (und das ist wirklich merkwürdig):
acer joe [~/tmp]: ls insgesamt 4,0K -rw-r--r-- 1 joe users 1,5K 19.08.2004 08:58:46 testprog.S acer joe [~/tmp]: as -o testprog.o testprog.S acer joe [~/tmp]: ld -lc -o testprog testprog.o acer joe [~/tmp]: ls insgesamt 16K -rwxr-xr-x 1 joe users 5,7K 19.08.2004 08:59:05 testprog -rw-r--r-- 1 joe users 1,3K 19.08.2004 08:58:56 testprog.o -rw-r--r-- 1 joe users 1,5K 19.08.2004 08:58:46 testprog.S acer joe [~/tmp]: ./testprog -bash: ./testprog: Datei oder Verzeichnis nicht gefunden acer joe [~/tmp]: ldd testprog /usr/bin/ldd: line 1: ./testprog: Datei oder Verzeichnis nicht gefunden acer joe [~/tmp]:
Kann das jemand nachvollziehen? Ja, es kann! Vor einigen Tagen erhielt ich von Max Wittgenstein folgende Mail, die ich mit seiner Genehmigung hier auszugsweise veröffentlichen darf:
From: Max Wittgenstein <xxx>
To: Johannes Bauer <xxx>
Subject: Problem mit Assembler: "Datei nicht gefunden"
[...]
Hat ein Weilchen gedauert, diese wirklich komische Sache zu verstehen.
Meiner Meinung nach liegt das Problem am fehlenden "dynamic-linker". Bei mir führt nämlich die Art und Weise des "Linking", bei der dieses Problem auftritt dazu, daß ein falscher "Requesting program interpreter: /usr/lib/libc.so.1" "eingelinkt" wird und diese Datei gibt es bei mir nicht.
Richtig müsste dort eine "/lib/ld-linux.so.2" stehen.
Also muß das Teil per Parameter an den Linker übergeben werden. Für den Rest an Erklärung, schau mal in die Datei: "make.sh" im Attachment.
Ach ja, mit dem Aufruf "readelf -l testprog" kann man sich den Programmheader in menschenlesbarer Form anschauen. Da steht dann unter anderem sowas wie z.B.:
"Requesting programm interpreter: /lib/ld-linux.so.2"
[...]
Das Attachment, "make.sh", gibt es hier herunterzuladen. Vielen Dank nochmal an Max, der sich die Mühe gemacht hat, das Problem nachzuvollziehen.
| Version | Veränderungen |
| AsmReferenz.pdf Version 1 Download | Eine x86-Assembler Referenz mit Codebeispielen |
| Funktionsaufrufe.pdf Version 3 Download | Funktionsweise von Funktionsaufrufen und Verhalten des Stacks (geänderte Version) |
| Download 0.09 (27.9.2004) | Klausuraufgabe: Möglichst effiziente Implementierung von "Modulo 10". Meine Lösung in C-Source (modulo.c) und in Assembler (19_modulo.S) |
| 0.08 (27.9.2004) | Klausuraufgabe: Implementierung einer rekursiven ggt-Funktion hinzugefügt |
| 0.07 (26.9.2004) | Beispiel, dass die verschiedenen Sprungarten ja, jb, jl, jg vergleicht |
| 0.06 (25.9.2004) | Das "call x; x: popl %eax" Beispiel ist nun mit im Paket drin, und ein Beispiel, wie man "calls" machen sollte, und wie nicht |
| 0.05 (25.9.2004) | Rorl-Klausurbeispiel hinzugefügt |
| 0.04 (30.8.2004) | Beispiel für Fließkommazahlen (nicht klausurrelevant!) |
| 0.03 (25.8.2004) | Malloc aus Assembler und drei Beispiele, wie man Code verkürzen/vereinfachen kann |
| 0.02 (19.8.2004) | Matrixmultiplikation hinzugefügt, das bisher umfangreichste Beispiel |
| 0.01 (19.8.2004) | Erster Versuch eines Releases |
