Assembler-Projekt 1.31 - Gruppe 4
|
Benennung
Im Folgenden wird die Funktionsweise der neu zu implementierenden
C-Bibliotheksfunktionen strcmp und strncmp beschrieben. Um die
neuen Funktionen von den bereits vorhandenen unterscheiden zu können, haben
wir sie strcmpnew und strncmpnew genannt.
Stringdarstellung in C
In C werden Strings als ein beliebig langes Feld (array) von Bytes (characters)
dargestellt, deren Ende durch ein Byte mit dem Wert 0 markiert ist. Die Stringlänge
ist theoretisch nur durch die Größe des verfügbaren Speichers begrenzt.
Speichermodell
Windows 95/NT-Programme verwenden das sogenannte Flat-Speichermodell. Der
gesamte Code und die Daten einer Anwendung befinden sich hier in einem einzigen
Segment. Adressen innerhalb dieses Segments sind 32-Bit Werte, alle Daten lassen
sich über DS adressieren. In C sind damit alle Zeiger 32-Bit-Near die sich ebenfalls
auf DS beziehen.
Definition
Die Funktion wird entsprechend dem Prototyp der Originalroutine definiert:
int strcmpnew(const char *str1, const char *str2);
Parameterübergabe
Die Parameter werden vor dem Sprung (mit dem CALL-Befehl) zur Funktion von rechts
nach links (nach C-Konvention) auf den Stack (Keller) gelegt. Die Parameterwerte
sind 32-Bit-Near Zeiger auf die C-Strings str1 und str2. Der Stack
hat also beim Eintritt in die Funktion folgende Gestalt:
Stack- Adresse |
Inhalt |
Größe |
| esp+8 |
2.Parameter: Adresse von str2 |
32 Bit (4 Byte) |
| esp+4 |
1.Parameter: Adresse von str1 |
32 Bit (4 Byte) |
| esp |
von CALL abgelegte Rücksprungadresse |
32 Bit (4 Byte) |
Nach der Ausführung der Funktionen müssen die Parameterwerte vom Aufrufer wieder
vom Stack entfernt werden (ebenfalls nach C-Konvention).
Vergleich und Rückgabewert
Die beiden Strings werden solange zeichenweise miteinander verglichen, bis
sie sich in einem Zeichen unterscheiden oder bis das Stringende (gekennzeichnet
durch ein '0'-Byte) erreicht ist.
Das Funktionsergebnis wird im eax-Register zurückgegeben. Wenn beide Strings
gleich sind, wird 0 zurückgegeben. Anderenfalls wird -1 bzw. +1 zurückgegeben,
wenn der Wert des ersten unterschiedlichen Zeichens von str1 kleiner bzw. größer
als der des entsprechenden Zeichens von str2 war.
mögliche Fehler
Fehler treten nur auf, wenn einer der beiden (oder beide) Zeigerwerte ungültig ist,
also eine Adresse enthält, auf die das Programm nicht zugreifen darf (z.B.
Adressen kleiner 00400000h).
Eine andere Fehlerquelle sind Strings, die keine Ende-Marke (0-Byte) haben. In
diesem Fall kann es passieren, daß die Funktion beim Abarbeiten irgendwann auf
Adressen zugreifen will, die nicht mehr im Adreßraum des Programms liegen.
In beiden Fällen löst der Prozessor eine Ausnahmebedingung aus, und das
Betriebssystem wird die fehlerhafte Anwendung zwangsweise beenden.
Definition
Die Funktion wird entsprechend dem Prototyp der Originalroutine definiert:
int strncmpnew(const char *str1, const char *str2, size_t n);
Die Funktionsweise stimmt weitgehend mit strcmp überein:
Parameterübergabe
Die Parameter werden vor dem Sprung (mit dem CALL-Befehl) zur Funktion von rechts
nach links (nach C-Konvention) auf den Stack (Keller) gelegt. Die beiden ersten
Parameter sind 32-Bit-Near Zeiger auf die C-Strings str1 und str2.
Der letzte Parameter ist ein 32-Bit Wert, der angibt, wieviele Zeichen maximal
verglichen werden sollen. Der Stack hat beim Eintritt in die Funktion folgende
Gestalt:
Stack- Adresse |
Inhalt |
Größe |
| esp+12 |
3.Parameter: Grenze n für Vergleich |
32 Bit (4 Byte) |
| esp+8 |
2.Parameter: Adresse von str2 |
32 Bit (4 Byte) |
| esp+4 |
1.Parameter: Adresse von str1 |
32 Bit (4 Byte) |
| esp |
von CALL abgelegte Rücksprungadresse |
32 Bit (4 Byte) |
Nach der Ausführung der Funktionen müssen die Parameterwerte vom Aufrufer wieder
vom Stack entfernt werden (ebenfalls nach C-Konvention).
Vergleich und Rückgabewert
Die ersten n Zeichen der beiden Strings werden solange zeichenweise miteinander
verglichen, bis sie sich in einem Zeichen unterscheiden oder bis das Stringende
(gekennzeichnet durch ein '0'-Byte) erreicht ist.
Das Funktionsergebnis wird im eax-Register zurückgegeben. Wenn beide Strings bis
zum n-ten Zeichen gleich sind, wird 0 zurückgegeben. Anderenfalls wird -1 bzw. +1
zurückgegeben, wenn der Wert des ersten unterschiedlichen Zeichens von str1
kleiner bzw. größer als der des entsprechenden Zeichens von str2 war.
mögliche Fehler
Bei strncmpnew können dieselben Fehlersituationen wie bei strcmpnew
auftreten.
Außerdem sei noch erwähnt, daß kein Fehler auftritt, wenn n einen Wert hat,
der größer als die Länge eines oder beider Strings ist. Bei jedem Vergleich
wird auch geprüft, ob das Stringende bereits erreicht ist, und somit vorzeitig
abgebrochen.
Algorithmen:
- Vor dem eigentlichen Vergleich wird die Länge des ersten Strings bestimmt.
Vorteil: beide Strings können mit dem Blockbefehl cmps und der
Wiederholungsanweisung repe verglichen werden.
Nachteil: unter Umständen werden durch das Absuchen des ersten Strings nach der
Ende-Markierung ('0'-Byte) mehr Vergleiche als notwendig durchgeführt.
- Die Strings werden zeichenweise miteinander verglichen.
Vorteil: Auf diese Weise werden nur notwendige Vergleiche durchgeführt. Die
Blockbefehle lods und scas können verwendet werden.
Nachteil: Die Wiederholungsanweisung repe kann nicht verwendet werden,
da die Länge der Strings nicht bekannt ist.
Wir haben uns für letztere Möglichkeit entschieden, da sie uns im Hinblick auf die
Ausführungsgeschwindigkeit besser erscheint.
Einbindung in Programme
Für die Einbindung von Assembler-Routinen gibt es in Visual C++ mehere Möglichkeiten:
- Es verfügt zum einen über einen sog. inline-Assembler, d.h. Funktionen können innerhalb
eines C-Programms direkt in Assembler geschrieben werden.
- Extern assemblierte Module können als Object-Dateien (.obj) eingebunden werden.
- Außerdem können Assembler-Module in C-Befehlsbibliotheken zusammengefaßt werden.
Wir haben uns dafür entschieden, die Funktionen innerhalb von Object-Dateien einzubinden,
da hier die Möglichkeiten der maschinennahen Programmierung voll ausgenutzt werden können.
Außerdem können die Module auf diese Weise auch in andere Programmiersprachen eingebunden
werden.
Um die Korrektheit der Funktionen zu testen, soll ein C-Programm verwendet werden, daß die
Ergebnisse der Original Bibliotheksroutinen mit denen der neuen Routinen vergleicht.
Interessant ist dabei das Verhalten bei gleichen Strings, bei verschiedenen Strings,
bei Leerstrings. Für strncmp/strncmpnew sollten außerdem verschiedene Werte für n getestet
werden, z.B. n gleich 0, n größer als die Stringlänge, n gleich der Stringlänge und
n kleiner als die Stringlänge.
10.07.98