Aufgaben zur IA32-Assembler-Programmierung - AG Technische ...
Aufgaben zur IA32-Assembler-Programmierung - AG Technische ...
Aufgaben zur IA32-Assembler-Programmierung - AG Technische ...
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
<strong>Aufgaben</strong> <strong>zur</strong> <strong>IA32</strong>-<strong>Assembler</strong>-<strong>Programmierung</strong><br />
Prof. Dr. Ralf Möller<br />
<strong>AG</strong> <strong>Technische</strong> Informatik<br />
<strong>Technische</strong> Fakultät<br />
Universität Bielefeld<br />
www.ti.uni-bielefeld.de<br />
Version 1.19 vom 25. September 2013, WS 2013/14
Insgesamt müssen 100 Punkte erreicht werden. Die <strong>Aufgaben</strong> sind von jedem Studenten einzeln zu bearbeiten; Betrugsversuche<br />
werden geahndet. Es ist nicht gestattet, <strong>Assembler</strong>-Programme aus compilierten hochsprachlichen<br />
Programmen zu erstellen.<br />
Aufgabe: (10 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm add64.asm, welches zwei ganze Zahlen mit<br />
jeweils 64 Bit Breite addiert. Der höherwertige Teil der ersten Zahl soll im Register eax, der niederwertige in ebx<br />
stehen, die zweite Zahl entsprechend in ecx und edx, das Ergebnis in eax und ebx. Arbeiten Sie das Programm<br />
im Debugger gdb schrittweise ab und notieren Sie nach jeder arithmetischen Operation den Zustand der beteiligten<br />
Register und des erweiterten Flag-Registers eflags (es muss keine Ausgabefunktion implementiert werden).<br />
Erklären Sie die Flagstellungen. Hinweis: Alle Statusflags stehen in den unteren 16 Bit des eflags Registers:<br />
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0<br />
OF SF ZF AF PF CF<br />
Verwenden Sie folgende Beispiele als Summanden:<br />
eax ebx ecx edx<br />
0x11111111 0x22222222 0x33333333 0x44444444<br />
0x11111111 0x22222222 0x33333333 0xdddddddd<br />
0x11111111 0x22222222 0x33333333 0xddddddde<br />
0x11111111 0x22222222 0x33333333 0xeeeeeeee<br />
0x11111111 0x22222222 0xeeeeeeee 0xeeeeeeee<br />
Aufgabe: (30 Punkte) Ergänzen Sie das obige Programm add64.asm, so dass die Werte der 4 beteiligten Universalregister<br />
und die Statusflags mittels Aufruf zweier Unterprogramme an beliebiger Stelle im Programm ausgegeben<br />
werden können. Verwenden Sie bei der Ausgabe der Statusflags jeweils kleine Buchstaben für nicht gesetzte<br />
und große Buchstaben für gesetzte Flags. Wiederholen Sie damit Ihre Versuche aus der vorherigen Aufgabe und<br />
überprüfen Sie die Resultate. Beachten Sie, dass Operationen, die für die Ausgabe verwendet werden, die Statusflags<br />
beeinflussen können (die Stack-Befehle für das erweiterte Flag-Register heißen pushf und popf). Beachten<br />
Sie weiterhin, dass es keine bedingten Sprungbefehle gibt, welche das Auxiliary Carry Flag (AF) abfragen (Hinweis:<br />
Der Befehl lahf überführt die Statusflags in das Register ah. Mit bt ax, 12 kann das AF-Flag in das<br />
Carry-Flag kopiert werden.) Sie müssen davon ausgehen, dass sich die Flags vorher in einem undefinierten Zustand<br />
befinden.<br />
Beispiel:<br />
% add64<br />
11111111 22222222 33333333 ffffffff<br />
osZAPc<br />
11111111 22222221 33333333 ffffffff<br />
oszAPC<br />
44444445 22222221 33333333 ffffffff<br />
oszapc<br />
%<br />
Aufgabe: (30 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm namen.asm, welches in einer Zeichenkette mit<br />
einem Personennamen jeweils den ersten Buchstaben als Großbuchstaben, alle anderen Buchstaben als Kleinbuchstaben<br />
darstellt, unabhängig von der Schreibweise in der Eingabe. Die Zeichenkette wird von der Standardeingabe<br />
gelesen, bis ein Zeilenumbruch auftritt, umgewandelt und auf der Standardausgabe ausgegeben. Gelangt die Leseroutine<br />
(Systemruf read) zum Dateiende (Rückkehrwert 0), so wird das Programm beendet. Beispiel (abwechselnd<br />
Eingabe/Ausgabe; die Shell gibt eine Zeichenkette erst dann weiter, wenn diese mit Enter abgeschlossen<br />
wurde):<br />
% namen<br />
Eingabe: JAMES T. kirk<br />
Ausgabe: James T. Kirk<br />
Eingabe: heinrich HEINE<br />
Ausgabe: Heinrich Heine<br />
1
ˆD<br />
%<br />
Aufgabe: (40 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm sgrep.asm (mit ähnlicher Funktion wie das<br />
Unix-Kommando grep), welches in der Standardeingabe nach einer Zeichenkette sucht, die als Kommandozeilenargument<br />
angegeben wurde. Wird die Zeichenkette in einer Zeile (Zeilenabschluss 0x0a) gefunden, so wird<br />
die gesamte Zeile auf der Standardausgabe ausgegeben.<br />
Aufgabe: (40 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm colsel.asm, welches die Standardeingabe<br />
durchmustert und nur eine “Spalte” des Eingabedatenstroms auf der Standardausgabe ausgibt. Die Nummer der<br />
Spalte (beginnend mit 1) wird als Kommandozeilenargument angegeben. Spalten werden von Tabulatoren (0x09)<br />
getrennt, wobei auch mehrere Tabulatoren hintereinander auftreten können. Zeilen enden mit 0x0a.<br />
Aufgabe: (40 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm convert10to16.asm welches eine vorzeichenlose<br />
Dezimalzahl in eine Hexadezimalzahl (32 bit) umwandelt. Die Dezimalzahl wird als Kommandozeilen-<br />
Argument übergeben, nochmals im Original ausgegeben, umgewandelt und als Hexadezimalzahl (mit führenden<br />
Nullen) auf der Standardausgabe ausgegeben. Das Programm soll eine Fehlermeldung ausgeben, wenn ein inkorrektes<br />
Zeichen eingegeben wurde oder der Wertebereich von 32 bit überschritten wird. Beispiel:<br />
% convert10to16 12345<br />
decimal number = 12345<br />
hexadecimal number = 0x00003039<br />
% convert10to16 4294967295<br />
decimal number = 4294967295<br />
hexadecimal number = 0xffffffff<br />
% convert10to16 4294967296<br />
decimal number = 4294967296<br />
invalid decimal number<br />
% convert10to16 12x45<br />
decimal number = 12x45<br />
invalid decimal number<br />
%<br />
Aufgabe: (30 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm convert16to10.asm, welches eine vorzeichenlose<br />
Hexadezimalzahl (max. 8 Stellen) in eine Dezimalzahl umwandelt. Die Hexadezimalzahl wird als Kommandozeilen-Argument<br />
übergeben, nochmals im Original ausgegeben, umgewandelt und als Dezimalzahl (ohne<br />
führende Nullen) auf der Standardausgabe ausgegeben. Das Programm soll eine Fehlermeldung ausgeben, wenn<br />
ein inkorrektes Zeichen oder mehr als 8 Stellen eingegeben wurden. Beispiel:<br />
% convert16to10 3e8<br />
hexadecimal number = 0x3e8<br />
decimal number = 1000<br />
% convert16to10 3g8<br />
hexadecimal number = 0x3g8<br />
invalid hexadecimal number<br />
%<br />
Aufgabe: (40 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm wortzaehl.asm, welches die Anzahl der Zeilen,<br />
der Worte und der Zeichen in einer Text-Datei zählt und diese Angaben auf der Standardausgabe ausgibt (eine<br />
einfache Variante des Unix-Befehls wc, der auch zum Vergleich herangezogen werden sollte). Worte werden von<br />
Leerzeichen (0x20), Tabulatoren (0x09) oder Zeilenumbrüchen (0x0a) getrennt, wobei auch mehrere dieser<br />
Zeichen hintereinander auftreten können. Der Name der Text-Datei soll als Kommandozeilen-Argument übergeben<br />
werden, die Ausgabe der drei Zahlen im Dezimalsystem erfolgt auf der Standardausgabe. Für die Ausgabe wird<br />
ähnlicher Code wie in der Aufgabe convert16to10.asm nötig sein (es wird deswegen auch nur eine Aufgabe<br />
von beiden gewertet).<br />
Aufgabe: (20 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm rot13.asm, welches ASCII-Text von der Standardeingabe<br />
einliest, diesen mithilfe des ROT13-Verfahrens “verschlüsselt” und auf der Standardausgabe ausgibt.<br />
Die ROT13-Chiffrierung verschiebt jeden Buchstaben des Alphabets um 13 Stellen nach vorn oder hinten. Chiffrierung<br />
und Dechiffrierung sind identisch. Das folgende C-Programm realisiert das gewünschte Verhalten:<br />
2
#include<br />
#include<br />
int<br />
main()<br />
{<br />
char c, cc;<br />
while (!feof(stdin)) {<br />
c = fgetc(stdin);<br />
if (c == EOF) break;<br />
cc = c | 0x20;<br />
if ((cc >= ’a’) && (cc = ’n’) && (cc
#include <br />
#include <br />
void<br />
block_ausgabe(long int wert, char einer, char fuenfer, char zehner)<br />
{<br />
long int i;<br />
if (wert == 9)<br />
printf("%c%c", einer, zehner);<br />
else if (wert > 4) {<br />
printf("%c", fuenfer);<br />
for (i = wert; i >= 6; i--)<br />
printf("%c", einer);<br />
}<br />
else if (wert == 4)<br />
printf("%c%c", einer, fuenfer);<br />
else<br />
for (i = wert; i >= 1; i--)<br />
printf("%c", einer);<br />
}<br />
int<br />
main(int argc, char *argv[])<br />
{<br />
long int i, zahl;<br />
}<br />
if (argc != 2) {<br />
fprintf(stderr, "arabic2roman \n");<br />
return -1;<br />
}<br />
zahl = atol(argv[1]);<br />
/* keine Ausgabe fuer 0 oder negative Zahlen */<br />
if (zahl
% bubblesort Dieses Programm sortiert alle Zeichenketten nach Ihrem ASCII-Code.<br />
Deeiss<br />
Pagmmorr<br />
eiorrstt<br />
aell<br />
Zceeeehiknntt<br />
achn<br />
Iehmr<br />
-.ACCIISdeo<br />
%<br />
Beim Bubblesort werden nacheinander jeweils zwei aufeinanderfolgende Elemente verglichen (Index i und i + 1).<br />
Befinden die beiden Elemente sich nicht in der gewünschten Ordnung, so werden sie vertauscht. Dann wird mit<br />
Index i + 1 und i + 2 fortgefahren. Die Sortierung ist beendet, wenn im letzten Durchlauf keine Vertauschung<br />
vorgenommen wurde.<br />
Aufgabe: (40 Punkte) Implementieren Sie das CRC-Verfahren <strong>zur</strong> Checksummen-Berechnung nach der Beschreibung<br />
auf http://de.wikipedia.org/wiki/CRC-32 in einem <strong>Assembler</strong>programm crc.asm. Das Programm<br />
soll die CRC-Checksumme für die Zeichen berechnen, die ihm auf der Standardeingabe übergeben werden<br />
(z.B. durch Umlenken einer Datei auf die Standardeingabe). Beispiel:<br />
% crc < print_args.asm<br />
Checksumme: 0xbe9b56fc<br />
%<br />
Gehen Sie von dem modifizierten Algorithmus aus, der auf obiger Webseite als C-Programm angegeben ist:<br />
#include <br />
#include <br />
#include <br />
#define CRC32POLYREV 0xEDB88320 /* CRC-32 Polynom, umgekehrte Bitfolge */<br />
int datastream[]={1,0,0,0,1,1,0,0}; /* ASCII-"1", LSB zuerst */<br />
int databits=8;<br />
uint32_t crc32_rev; /* Shiftregister */<br />
void calc_crc32_rev(int bit)<br />
{ int lbit;<br />
lbit=crc32_rev & 1;<br />
if (lbit != bit)<br />
crc32_rev=(crc32_rev>>1) ˆ CRC32POLYREV;<br />
else<br />
crc32_rev=crc32_rev>>1;<br />
}<br />
int main(void)<br />
{ int i;<br />
}<br />
crc32_rev=0xffffffff; /* Startwert (111...) */<br />
for (i=0; i
% clock<br />
Es ist 11:27:36<br />
%<br />
Die Uhrzeit kann um 1 oder 2 Stunden von der Mitteleuropäischen (Sommer-)Zeit abweichen.<br />
Aufgabe: (40 Punkte) Schreiben Sie ein <strong>Assembler</strong>-Programm fixedpoint.asm. Dieses soll auf der Standardeingabe<br />
eine Dezimalzahl mit Vor- und Nachkommestellen akzeptieren und auf der Standardausgabe deren<br />
Kodierung als Festkommazahl binär ausgeben. Die Festkommazahl hat 32 Bit und soll jeweils 16 Bit als Vor- und<br />
Nachkommabereich enthalten. Das Programm soll enden, wenn der Systemruf read den Rückgabewert 0 liefert.<br />
% fixedpoint<br />
Type a number: 234.23508<br />
32bit fixed-point number: 00000000111010100011110000101110b<br />
Type a number: 56908.2309482<br />
32bit fixed-point number: 11011110010011000011101100011111b<br />
Type a number: 230983.0984209348<br />
32bit fixed-point number: 11111111111111110001100100110010b<br />
ˆD<br />
%<br />
6