It's still possible to tweak Trond's solution a little bit further by implementing it in native Assembler:
Code: Select all
Procedure.S ReverseString(String.S)
Protected StringLength.L
StringLength = StringByteLength(String)
! MOV EAX,DWORD[p.v_String]
! MOV ESI,EAX
! MOV EDI,EAX
! ADD EDI,DWORD[p.v_StringLength]
! DEC EDI
!CheckIfReady:
! CMP ESI,EDI
! JNB Ready
! MOV BL,[ESI]
! MOV BH,[EDI]
! MOV [EDI],BL
! MOV [ESI],BH
! INC ESI
! DEC EDI
! JMP CheckIfReady
!Ready:
ProcedureReturn String
EndProcedure
Count.L
StartTime.L
StartTime = ElapsedMilliseconds()
Repeat
ReverseString("I love PureBASIC!")
Count + 1
Until ElapsedMilliseconds() - StartTime >= 1000
MessageRequester("Cycle count", Str(Count), #MB_ICONINFORMATION)
Measured cycles on my PC:
AND51: ~ 0.16 million
Trond + netmaestro: ~ 2.1 million
Shardik: ~ 2.4 million
It's always quite interesting to compare different algorithms and in most cases my predictions have been proven wrong...
I've also tried to copy 4 bytes at once which should be faster but with the above short example string the payoff for aligning the string on a word boundary and fill it up with spaces to a size divideable by 8 takes too much time.
Even my first approach of using two strings
Code: Select all
Procedure.S ReverseString(String1.S)
Protected String2.S
Protected StringLength.L
StringLength = Len(String1)
String2 = Space(StringLength)
! MOV ESI,DWORD[p.v_String1]
! MOV EDI,DWORD[p.v_String2]
! MOV ECX,DWORD[p.v_StringLength]
! ADD EDI,ECX
! DEC EDI
!CopyLoop:
! MOV AL,[ESI]
! MOV [EDI],AL
! INC ESI
! DEC EDI
! LOOP CopyLoop
! MOV EAX,EDI
ProcedureReturn String2
EndProcedure
is quite slow with about 1.4 million cycles. Unfortuately it's not possible to make use of the powerful move string instruction MOVS with REP prefix because one index register has to be incremented and the other has to be decremented...
