FindChar

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

remi_meier hat geschrieben:Aber ich bin mir mit dem InlineAsm nicht mehr so sicher..
Du machst ein "CMP EAX,0", d.h. der Pointer wird auf 0 geprüft,
aber nicht das Byte auf den der Pointer zeigt, also das Ende des
Strings.

Wenn nichts gefunden wurde, sollte die Prozedur auch 0 zurückgeben,
und nicht irgendwas.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

OK danke!
Habs geändert, nur jetzt bin ich sicher, dass mans besser machen könnte, ich komm nur grad nicht drauf :|

cu
Remi

Edit: Lol, hab das Gröbste grad mal rausgenommen! Ich sollte nicht mehr so schnell posten... Ich habs nun auch mit Kommentaren versehen
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Wie wär´s damit:

Code: Alles auswählen

Procedure FindChar(*string.BYTE, asc.l) 
  ;start = *string 
  
  MOV eax, *string   ;Pointer auf String in eax 
  MOV ebx, asc       ;Ascii-code von Zeichen in ebx, genauer bl 
  startpunkt: 
  CMP byte[eax], 0   ;überprüfen, ob Stringende 
  JZ  l_notfound     ;wenn ja, return 0! 
  
  CMP byte[eax], bl  ;überprüfen, ob gefunden 
  JE l_jump          ;wenn ja, dann aus schleife raus 

  INC eax            ;Stringpointer erhöhen 
  JMP l_startpunkt   ;zum Schleifenstart springen 
  jump:              ;Ende der Schleife 
  
  
  SUB eax, *string   ;Pointer subtrahieren, um Pos. zu bekommen 
  INC eax            ;Position von _1_ bis x 
  ProcedureReturn 
  
  notfound:          ;wenn nicht gefunden 
  ProcedureReturn 0 
  
  ; While *string\b 
  ; If *string\b = asc 
  ; ProcedureReturn *string - start + 1 
  ; EndIf 
  ; *string + 1 
  ; Wend 
EndProcedure 


Procedure FindChar1(*string.l, asc.l, laenge.l) 
 
  CLD  
  MOV edi,*string
  MOV eax,asc
  MOV ecx,laenge
  REPNZ scasb
  JNZ l_notfound1
  SUB edi,*string 
  MOV eax,edi         ;Rückgabewert
  
  ProcedureReturn 
  
  notfound1:          ;wenn nicht gefunden 
 
  ProcedureReturn 0 
  
EndProcedure 

 
#N = 900000 
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#" 
tofind.s = "#" 
asctofind.l = Asc(tofind) 
ptr.l = @String 
laenge.l=Len(String)

Delay(1000) 

Time1 = GetTickCount_() 
For I = 0 To #N 
  FindChar(ptr, asctofind)
Next 
Time1 = GetTickCount_() - Time1 

Time2 = GetTickCount_() 
For I = 0 To #N 
  FindString(String, tofind, 0) 
Next 
Time2 = GetTickCount_() - Time2 

Time3 = GetTickCount_() 
For I = 0 To #N 
Stelle.l = FindChar1(ptr, asctofind, laenge)
Next 
Time3 = GetTickCount_() - Time3 

strOut.s = "FindChar: " + Str(Time1) + #CRLF$ 
strOut.s = strOut.s + "FindString: " + Str(Time2) + #CRLF$
strOut.s = strOut.s + "FindChar1: " + Str(Time3) + "    " + Str(Stelle)
MessageRequester("Ergebnis", strOut)
Neu: FindChar1; benötigt Stringlänge bei Aufruf, es sei denn man ist sich
sicher, dass das Zeichen auf jeden Fall vorhanden ist. Zur Kontrolle wurde
Stelle mit angegeben.
Bringt hier aber nur bei längeren Strings Punkte; kann aber an der Art des
Aufrufes liegen.

Gruss
Helle
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

:allright:
Es geht (fast) immer kürzer :) (wobei der kleine Geschwindigkeitsunterschied wohl aus der CISC-Architektur (wenn ich mich nicht irre..) folgt, die z.T. langsamer ist).

cu
Remi
PS: Helle, ich glaub du bist es, der meine Frage im Optimizer-Thread beantworten könnte (die ist ja schon ne Zeit lang offen, und mir is langweilig)
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Hier wird doch wohl keiner auf einer RISC-Kiste testen und mich ins Grübeln kommen lassen wollen :mrgreen: ?
Ich dachte mehr an den Aufruf einer Prozedur und den damit notwendigen (???) Einsatzes der Inline-ASM-Unterstützung. Folgende Variante

Code: Alles auswählen

#N = 900000 
String.s = "searchinmeeeeeeee3123456123cb1g2348cbnq0webftrqc0n9qwbet691bt4  qböoäöa-asbe0rß1bv634r660qlbdf-asubdpfz10735646vrzpawbwöehbf76v6r9b3807b1p9sbaösejhbfquiowebz7r81bvg5340brqpweöfjkqböwev qöwjerh 1092346r18 4rpuqwzefqhw7e1 34nr7q0 w8 eh7r0q whe7qf0 wnejöasdjfh0q93478zbr1093br4höaowuez f0q7wez0fr13j4u rhqw7e rfqwe7rq0w9e rqh3 er13 4rqpweör v#" 
tofind.s = "#" 
asctofind.l = Asc(tofind) 
ptr.l = @String 
laenge.l=Len(String)

Delay(1000) 

Time = GetTickCount_() 
For I = 0 To #N 
  !CLD  
  !MOV ecx,[v_laenge] 
  !MOV edi,[v_ptr]
  !MOV eax,[v_asctofind]
  !REPNZ scasb
  !JNZ l_notfound
  !SUB edi,[v_ptr] 
  !JMP l_found 
notfound:          ;wenn nicht gefunden 
  !XOR edi,edi 
found:
  !MOV [v_Stelle],edi
Next 
Time = GetTickCount_() - Time 

strOut.s = "FindChar: " + Str(Time) + "    " + Str(Stelle)
MessageRequester("Ergebnis", strOut)
ohne Inline-ASM ist über 3-mal schneller als FindString, und zwar ist es jetzt völlig egal, an welcher Stelle das zu suchende Zeichen steht!
Zur Ehrenrettung von FindString muss aber unbedingt gesagt werden, dass es universieller arbeitet und auch String-Teile (nicht nur 1 Zeichen)
finden muss. Wenn obiger Code auch in einer Prozedur (viel) schneller
wäre als Findstring könnte man überlegen, eben eine Funktion "FindChar"
einzusetzen. Mal sehen...
Mein heißgeliebtes ALIGN brachte übrigens in keiner Variante hier Punkte... Wird wohl inzwischen von den zwischengeschalteten Progs bzw.
BS selbst erledigt.

Gruss
Helle
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Übrigens, ganz interessant aus den Beispielen mal Exen machen :D !!!

Gruss
Helle
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Nene keine RISC Kiste :D
Also wenn ich EXEn mache, sehe ich keinen Unterschied..
Das ALIGN nützt hier wohl nichts, weil die Schleife-Jumps nicht die meiste Zeit verschlingen! Bei meinem folgenden Beispiel wirkt ALIGN immernoch :)

Code: Alles auswählen

!ALIGN 4
#N = 9999999999

Delay(1000)

time1 = ElapsedMilliseconds()
For z = 0 To #N
Next
time1 = ElapsedMilliseconds() - time1

time2 = ElapsedMilliseconds()
For z = 0 To #N
Next
time2 = ElapsedMilliseconds() - time2

MessageRequester("",Str(time1)+" "+Str(time2))
cu
Remi
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

@remi: Der Unterschied mit den Exen ist tatsächlich nicht so gross wie bei
meinen Tests. Ursache: Habe meine Kiste in den letzten Tagen neu aufge-
setzt und dabei auf PB3.93 umgestellt. Jetzt werden aber Einstellungen den
Compiler und Debugger betreffend nicht mehr für den nächsten Programmstart abgespeichert; wenn ich nicht aufpasse ist beim Testen der
Debugger aktiv usw. :(
Habe mir heute deinen Optimizer runtergeladen und werde ihn mir mal zu
Gemüte führen. Dazu ein Wunsch: Aktualisiere doch mal die (eigentliche)
FAsm.exe (bei dir FAsm2.exe)! Du und PB setzen noch die Version 1.56 ein; aktuell ist 1.60 (jetzt mit 64-Bit Unterstützung!). Ich aktualisiere stets von Hand und kann berichten es treten keinerlei Probleme auf, ganz im Gegenteil :D !

Gruss
Helle
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

Helle hat geschrieben:Jetzt werden aber Einstellungen den Compiler und Debugger betreffend nicht mehr für den nächsten Programmstart abgespeichert
*seufz* also noch ein FROG, der gefixt werden muss....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Sylvia
verheiratet<br>1. PureGolf-Gewinner
Beiträge: 487
Registriert: 29.08.2004 09:42
Wohnort: Old Europe

Beitrag von Sylvia »

Die Abteilung "Code, Tipps und Tricks" wird ja geradezu mit nützlichen
Beiträgen überflutet :?
Basic Pur = PureBasic
Antworten