flat assembler
Message board for the users of flat assembler.

Index > Main > MASM to FASM reverse string

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
MHajduk



Joined: 30 Mar 2006
Posts: 6038
Location: Poland
MHajduk
Yeah, Picnic, bitRAKE's code shows a smart way of the stack use for the string reversal. But we can do the same playing only with direction flag DF which affects the way the esi and edi registers are modified after lodsX / stosX instructions.

Here you have a procedure which shows the whole idea:
Code:
; Reversing procedure.
;
proc ReverseString, Input, Output, InputLen

  pushf
       push    ecx esi edi

     mov     ecx, [InputLen] ; Length of the input string
                                ; without following zero byte.

  mov     esi, [Input]    ;
   add     esi, ecx        ; 
  dec     esi             ; Now esi points to the last
                                ; non-zero byte of the input
                                ; string.
   
    mov     edi, [Output]   ; Pointer to the output buffer.

 ; Reversing loop.
   ;
   .Loop:
          std
         lodsb
               cld
         stosb
               loop    .Loop

   pop     edi esi ecx
 popf

    ret
endp
    
And here you have an exemplary proggie where you can test it:
Code:
include 'win32ax.inc' 

.data
        InputStr        db "Exemplary string."
    InputStrLen     = $ - InputStr
                      db 0
        
    ReversedStr     rb InputStrLen
                      db 0
.code

   start:
          invoke  MessageBox, HWND_DESKTOP, InputStr, "Original string", MB_OK

          stdcall ReverseString, InputStr, ReversedStr, InputStrLen

               invoke  MessageBox, HWND_DESKTOP, ReversedStr, "Reversed string", MB_OK

               invoke  ExitProcess, 0

          ; Reversing procedure.
              ;
           proc    ReverseString, Input, Output, InputLen

                  pushf
                       push    ecx esi edi

                     mov     ecx, [InputLen] ; Length of the input string
                                                ; without following zero byte.

                  mov     esi, [Input]    ;
                   add     esi, ecx        ; 
                  dec     esi             ; Now esi points to the last
                                                ; non-zero byte of the input
                                                ; string.
                   
                    mov     edi, [Output]   ; Pointer to the output buffer.

                 ; Reversing loop.
                   ;
                   .Loop:
                          std
                         lodsb
                               cld
                         stosb
                               loop    .Loop

                   pop     edi esi ecx
                 popf

                    ret
         endp

.end start
    
Post 08 Jul 2011, 12:52
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4242
Location: 2018
edfed
simple, but bloat.

push a dword to save a byte is not optimal.
i find it better to use two pointers to do the job.
Post 08 Jul 2011, 14:37
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
It requires a buffer - better to do it in place.
Buffers are not easy to come up with. Smile
Post 08 Jul 2011, 15:09
View user's profile Send private message Send e-mail Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22
All of the answers on this thread are lacking over-the-top, unnecessary optimization. Since no one has presented a multithreaded solution I was forced to type the following.
Code:
.data
_RevStrOff dd -1 ;; current working offset
_RevStrStart dd 0 ;; constant start pointer
_RevStrEnd dd 0 ;; constant end pointer
_RevStrSync dd 0 ;; synchronization semaphore
_RevStrThrCnt dd 0 ;; number of threads in RevStr's worker thread pool

.code
;; Create a bunch (optimal amount) of threads
;; with RevStrThread as the Thread Proc
...
;; This function is not thread safe LOL
RevStr:
 MOV ecx,[esp+8] ;; len
 MOV eax,[esp+4] ;; ptr
 CMP ecx, 1 ;; useless length
 JLE .die
 CMP eax, -1 ;; useless string
 JE .die
 MOV edx, [_RevStrThrCnt]
.sync:
 CMP [_RevStrSync], edx
 JNE .sync
 LEA edx, [eax + ecx - 1] ;;end
 MOV [_RevStrEnd], edx
 SHR ecx, 1 ;; len / 2
 DEC ecx ;; (len / 2) -1
 MOV [_RevStrStart], eax
 MOV [_RevStrOff], ecx
.wait: ;;wait for the thread pool to finish
 CMP [_RevStrOff], 0 ;; wait while offset >= 0
 JGE .wait
.die:
 RET 8

RevStrThread:
.reset: ;; reset and go into wait mode
 MOV [_RevStrOff], -1
 LOCK ADD [_RevStrSync], 1
 JMP .wait
.work:
 LOCK SUB [_RevStrSync], 1
 MOV esi, [_RevStrStart] ;; start ptr
 MOV edi, [_RevStrEnd] ;; end ptr
.again:
 MOV ebx, -1
 LOCK XADD [_RevStrOff], ebx ;; ebx = current offset
 CMP ebx, ebx ;; reset if offset < 0 
 JS .reset
 LEA ecx, [ebx*-1] ;; -offset
 MOV al, byte[esi + ebx]
 MOV ah, byte[edi + ecx]
 MOV byte[esi + ebx], ah
 MOV byte[edi + ecx], al
 JMP .again
.wait: ;; wait for a new string
 CMP [_RevStrOff], 0 ;; wait while offset < 0
 JL .wait
 JMP .work
    

* edit * I'm kind of curious if this actually works now...


Last edited by r22 on 08 Jul 2011, 19:40; edited 1 time in total
Post 08 Jul 2011, 17:00
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 6038
Location: Poland
MHajduk
edfed wrote:
push a dword to save a byte is not optimal.
Could you explain what do you mean? Your comment is unclear.

EDIT: after a while I got it. You were talking about bitRAKE's method quoted in the Picnic's post. Explicit quoting is a good manner - nobody is forced to guess somebody's thoughts then. Wink


Last edited by MHajduk on 08 Jul 2011, 20:02; edited 1 time in total
Post 08 Jul 2011, 19:22
View user's profile Send private message Visit poster's website Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 6038
Location: Poland
MHajduk
AsmGuru62 wrote:
It requires a buffer - better to do it in place.
Buffers are not easy to come up with. Smile
Yes, but we destroy the original value then. Wink My procedure may be applied in case we want to make a reversed copy of the given string.
Post 08 Jul 2011, 19:24
View user's profile Send private message Visit poster's website Reply with quote
jochenvnltn



Joined: 15 Jul 2011
Posts: 83
jochenvnltn
Code:
proc StrReverse lpString:DWORD
mov eax,[lpString]                       ; put string address in EAX
mov edx,eax                            ; same in EDX
@@:                                    ; move EDX to the end of string
add edx,1
cmp byte [edx],0
jne @B
sub edx,1                              ; return EDX to last not null character
@@:
mov cl,byte [eax]          ; swap EAX and EDX, moving from two brinks
mov ch,byte [edx]          ; in opposite directions
mov [eax],ch                   ; while EAX is less than EDX
mov [edx],cl
add eax,1
sub edx,1
cmp eax,edx
jl @B
ret
endp    
[Edit by Loco]Added code tags.[/edit]
Post 23 Jan 2013, 21:50
View user's profile Send private message MSN Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.