Stringsuche in assembler
-
Moin erst mal,
ich hab folgendes Problem, ich soll in Tasm ein Programm schreiben welches eine Stringsuche in einer Datei macht. Ich hab aber keinen Plan wie ich diese suche machen soll da Assembler für mich Neuland ist, bis jetzt hab ich die abfrage für den zu suchenden String und das öffnen der Textdatei was auch bei soweit klappt aber nun ist Ende mit meinem Latein.Ich hoffe das mir jemand weiter helfen kann und dafür schon mal danke im Voraus.
-
schau mal hier: http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId97419
Da werden eingegebene Texte auf Übereinstimmung mit vorhandenen Befehlen vergleichen. Vielleicht hilft Dir das weiter.strcmp: .loop: mov al, [si] ; fetch a byte from SI cmp al, [di] ; are SI and DI equal? jne .done ; if no, we're done. or al, al ; zero? jz .done ; if yes, we're done. inc di ; increment DI inc si ; increment SI jmp .loop ; goto .loop .done: ret
-
So momentan hab ich zwar nen vergleich doch irgendwie funktioniert dieser auch nicht meine Vermutung ist das das Problem hierbei ist das er die komplette Textdatei als ein String an sieht und somit nicht mit Suchstring überein stimmt ich poste einfach mal meinen Quelltext hinzu vielleicht hat jemand ja die Lösung für mein Problem denn ich bin am verzweifel.
Bitte nicht all zu kritisch mit dem bisher geschriebenen ich hab mit Tasm erst vor 3 Wochen anfangen(müssen) und habe vorher noch nix damit zu tun gehabt ist jetzt halt Studien relevant.
Danke im Voraus und ein Dankeschön @Erhard Henkes
;****************************************** ;* * ;*Aufgab: Stringsuche in einer Textdatei* ;* * ;****************************************** TITLE TEST .Model Small .Stack 500h ;********************************************** ;*************Macros*************************** ;********************************************** printe Macro Z MOV DX,Offset Z MOV AH,09H INT 21h EndM ; ; ; ;********************************************* ;************DATA***************************** ;********************************************* .Data ;**************programminfo******************** pinfor db "Programm zur Suche eines String in einer Datei",10,13,"$" ; ;*************String*************************** sinfor db "Bitte geben sie ihr Suchstring(bitte maximal 4 Zeichen)",10,13,"$" such db 10 dup(?) suchp dw ? ;***********Datei****************************** dinfor db "Bitte Datei eingeben",10,13,"$" msgs db 10,13,"geht$" msge db 10,13,"error",10,13,"$" eing db 255 dup(?) filehandle dw ? puffer db 255 dup(0) ; ; ;********************************************** ;************CODE****************************** ;********************************************** .Code ; ; ; ;********************************************** ;********Programminformation******************* start: MOV AX,@data MOV DS,AX printe pinfor ; ; ; ;********************************************** ;******Ausgabe Infotext Suchstring************* string: MOV AX,@data MOV DS,AX MOV ES,AX printe sinfor ; ; ; ;******Stringeingabe vor Datei***** ; ; MOV SI,0 lesen2: MOV BX,0 MOV CX,255 MOV DX,OFFSET such MOV AH,03FH INT 21h MOV suchp,AX DEC AX DEC AX MOV SI,AX MOV such[SI],0H ;********************************************** ;************Ausgabe Infotext Datei************ datei: MOV AX,@data MOV DS,AX printe dinfor ; ; ;*********Eingabe Tastaturpuffer für Dateinamen********* ; ; MOV SI,0 lesen: MOV BX,0 MOV CX,255 MOV DX,OFFSET eing MOV AH,03FH INT 21h DEC AX DEC AX MOV SI,AX MOV eing[SI],0H ; ; ;*************Öffnen der Datei********************* ; ; open: MOV DX,offset eing MOV AH,3DH ;Datei öffnen MOV AL,0 INT 21h MOV filehandle,AX JNC luck JC pech luck: printe msgs JMP short read pech: printe msge JMP datei ;************Datei lesen*************************** ; ; read: MOV CX,100H MOV DX,offset puffer MOV BX,filehandle MOV AH,3fh INT 21h ;******vergleichen Inhalt der Datei mit Suchstring*** ; vgl1: MOV DI,offset filehandle;auf str1 zeigen MOV SI,offset suchp ; ;auf str2 zeigen MOV CX,4 ;Länge 4 REPE CMPSB ;vergleichen JE success ;falls gleich Sprung fail: printe msge JMP short fin success: printe msgs ; ; ; ; ;************************************************** ;****************ENDE****************************** ; ; fin: MOV AX,4C00h INT 21h End start ;
-
Dein Problem hat nichts damit zu tun, wie du die Datei ansiehst, sondern eher damit, dass du nur die ersten 4 Byte der eingelesenen Datei mit deinem Suchstring vergleichst.
Wenn du von Assembler keine Ahnung hast, hilft es dir vielleicht, wenn du deinen Code erstmal in einer Hochsprache wie C (natuerlich ohne Verwendung von netten "DurchsucheDatei"-Funktionen) oder Pseudocode formulierst und dann versuchst in Assembler umzusetzen.Falls das uebrigens nicht klar sein sollte: "cmpsb" laedt je ein Byte von es:di und ds:si, vergleicht die beiden wie cmp und erhoeht die Register si und di um eins (idR., wenn das DF=0 ist).
"rep cmpsb" wiederholt das dann entsprechend so lange, bis cx=0 wird, oder die beiden verglichenen Bytes ungleich sind.
... Daraus sollte schon klar werden, dass ein Aufruf von "rep cmpsb" nicht reichen kann, um einen Datensatz (zB. eine eingelesene Datei), der laenger als der Suchstring ist, komplett zu durchsuchen.
-
@ Nobuo T danke für den tipp.
Also kann ich meinen Vergleich weg schmeißen und mir was neues überlegen verdammt ich weis bloß nicht was. Hat jemand nen Tipp oder vielleicht schon mal sowas gemacht weil mir läuft irgendwie die Zeit davon und ich hänge immer noch an der Suche obwohl irgendwie alle sagen das sei nicht so schwer mit Assembler(eindeutig seh ich den Wald vor lauten Bäumen nicht).
-
Nein, du brauchst deinen Vergleich nicht komplett in die Tonne kloppen, du musst ihn nur erweitern (und hier und da ein wenig korrigieren), so dass der komplette eingelesene Datensatz verglichen wird.
Wie gesagt: Vielleicht hilft die Sache mal in C-aehnlichem Pseudocode zu betrachten... Was du im Moment hast, sieht im Prinzip so aus:
char* a = &such; // Zeile 130 in deinem Code muesstest du zB. noch korrigieren: // du brauchst einen Pointer auf den Anfang deines Suchstrings und nicht den Pointer auf "suchp" char* b = &puffer; // dito mit Zeile 131: Du musst den Pointer am Anfang auf die Adresse des Puffers setzen, in den du die Datei eingelesen hast. Mit einem Pointer auf den FileHandle kannst du nichts anfangen for (i=4; i>0 && *(a++) == *(b++); i--); // das ist praktisch, was rep cmpsb macht // a und b uebernehmen hier also die Aufgabe der Register si und di
Vergleicht genau die ersten 4 Zeichen des Suchstrings und der eingelesenen Datei miteinander...
Was du aber haben muesstest, um die komplette Datei zu durchsuchen, waere z.B. in etwa sowas hier:
char* b = &puffer; // Pointer auf den Puffer fuer die Datei for (j = 0; j < 0x100 - 4; j++) { char* a = &such; for (i=4; i>0 && *(a++) == *(b++); i--); // deine aktuelle "rep cmpsb" Suche if i = 0 goto gefunden; // wurden alle 4 Zeichen erfolgreich verglichen, hast du den String gefunden. b=b-(4-i); // wieder zurueck auf das naechste Zeichen vor Anfang des Vergleichs. } nicht_gefunden: writeln "String nicht gefunden."; halt; gefunden: writeln "String gefunden :-)"; halt;
Hoffe, das macht es etwas klarer, was noch fehlt.
-
@ Nobuo T
Also wenn ich das richtig versteh ist das Problem bei meiner momentanen Version das ich die Größe des Strings aus der Textdatei nicht kenne/richtig angebe und nicht sage wo es anfangen und wo aufhören soll zu vergleichen oder?
Dein Beispiel in C versteh ich ja so halbwegs aber wie ich das in meinen Assembler Programm umsetzen soll weis ich nicht.Und dann noch nen Counter rein zimmer der mir sagt wie oft der String vor kommt(
)
So schäfft ein Prof. auf der Beliebtheitsskala weit nach unten zu kommen,naja mal sehen ob ich das noch zum laufen bekomme ich glaub nicht mehr dran, sind ja noch drei Tage
-
Irgendwie scheinst du meine C-artigen Codes ja doch nicht so ganz verstanden zu haben...
Ich kenne deine Vorgaben/Aufgabenstellung nicht, also weiss ich nicht, in wie weit ihr die Groesse der Datei beruecksichtigen sollt. Momentan hast du eine Groessenbeschraenkung auf maximal 256 Byte Dateigroesse in deinem Programm - das ist alles. In meinem Pseudocode werden dann zwar immer die ganzen 256 Byte des Puffers durchsucht, das ist aber hoechstens ineffizient, sonst nicht weiter schlimm.
Das mit dem "nicht sage[n] wo es anfangen und wo aufhören [...] zu vergleichen" stimmt auch nur halb. Fuer den ersten Durchlauf gibst du ja durchaus (zwar falsche) Adressen fuer die Vergleiche an. Du brauchst eben um deinen "rep cmpsb"-Vergleich noch eine weitere Schleife, die den Anfang des Vergleichs in der Datei immer Byte-weise nach hinten verschiebt.Mach doch wirklich erstmal einen groben Pseudo-Code-Entwurf fuer dein Programm und dir daran klar, wie die Suche funktioniert. Die Umsetzung in Assembler sollte dann relativ einfach und systematisch moeglich sein.
PS:
Ueber den Prof poebeln ist schoen und gut - bringt dich aber zum einen erstmal nicht weiter und zum anderen sind so grundlegende Dinge wie grundlegendes Verstaendnis von Algorithmen und Programmiersprachen (wo es bei dir scheinbar noch hapert) wirklich etwas, was in einer Uni-Vorlesung iAR. einfach vorausgesetzt wird. Wenn du da jetzt in Probleme rennst, solltest du dir auch ein bissel mal an die eigene Nase packen.
-
Dein Beispiel in C versteh ich ja so halbwegs aber wie ich das in meinen Assembler Programm umsetzen soll weis ich nicht.Und dann noch nen Counter rein zimmer der mir sagt wie oft der String vor kommt(
)
Du könntest den C-Code durch einen Compiler umsetzen lassen und Dir den resultierenden Assemblercode schrittweise vergleichend mit objdump (GNU binutils) anschauen, wenn Du es nicht selbst schaffst. Nur so als Idee.
-
Will Dir, allerdings mit 32 Bit Inline-Assembler in einem C-Programm, zeigen, wie man eine Suche mittels repe cmpsb und folgendem jecxz durchführen kann.
#include <stdio.h> #define STR 3 int main(void) { char buf[] = "Hallo, wie geht es Dir?"; char suchstring[STR+1] = "wie"; int* Adresse = NULL; int Position; __asm { lea esi, buf L1: push esi lea edi, suchstring mov ecx, STR repe cmpsb jecxz Uebereinstimmung pop esi inc esi or byte ptr [esi+STR], 0 jnz L1 jmp Ende Uebereinstimmung: pop Adresse mov esi, Adresse lea edi, buf sub esi, edi mov Position, esi Ende: } if (Adresse) printf("Suche erfolgreich an Position %d\n", Position); return 0; }
Bei 16 Bit Programmierung ändern sich die Registerbezeichnungen und aus jecxz wird jcxz .
mfg