News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

String reversal with and without rev$ macro

Started by Ravi Kiran, May 06, 2021, 03:52:24 AM

Previous topic - Next topic

Ravi Kiran

I don't  know where my code for reversal of a string gone wrong but code below hangs my computer.

1. Without rev$ macro

          Include  /masm32/include/masm32rt.inc

         .data
           buff1 dB "Hello World"

         .data?
           buff2 dB 50 dup(0)

         .code

          Start:
                   Mov eax.len(buff1)
      Label1:
                   Mov bl,byte PTR buff1[eax-1]
                   Mov ecx,0
                   Mov byte PTR buff2[ecx],bl
                   Inc ecx
                   Dec eax
                   Jnz label1
                   Mov byte PTR buff2[ecx],0  ; null terminated string
                   Invoke StdOut, addr buff2
                   Inkey
                   Invoke ExitProcess,0

   End start



I don't know  how to code with the use of rev$ macro . Plz anyone help. The problem comes while displaying results. The above code
Shows no errors but hangs my computer without displaying anything.

jj2007

Post your code. Make sure it's complete with includes etc, and comment what you have done so far. Explain what doesn't work (error messages...).

hutch--

Ravi,

There is a logic to how its done, if you create a string that is 7 characters long,

  1 2 3 4 5 6 7
  swap
  1 and 7
  2 and 6
  3 and 5
  4 cannot be swapped.

  on 6 characters
  swap
  1 and 6
  2 and 5
  3 and 4

Have a look at the library module, "szrev.asm".
It is doing a bit more so you don't have to change the original string but it shows you how the strig reverse is coded.

These are what you call "in place" operations. You could do it by allocating a buffer and doing a reverse copy from the source to the destination.

avcaballero

http://abreojosensamblador.epizy.com/Productos/AOE/Codigos/Cap07/MOVSCM1.asm

hutch--

Ravi,

Here is a simpified version of an "in place" string reverse.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    raviRev PROTO pstr:DWORD

    .data
      ravi db "Hi, my name is Ravi",0
      numz db "1234567890",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL rval :DWORD

    cls
    print ADDR ravi,13,10,13,10

    invoke raviRev,ADDR numz    ; reverse the number above
    mov rval, eax

    print rval,13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

raviRev proc pstr:DWORD

    LOCAL ln :DWORD             ; length
    LOCAL hl :DWORD             ; half length

    push ebx                    ; save EBX

    invoke szLen,pstr
    mov ln, eax                 ; get full string length
    shr eax, 1                  ; get integer half length of string
    mov hl, eax                 ; store it in variable

    mov edx, pstr
    add edx, ln                 ; get end character address
    sub edx, 1                  ; sub 1 to get end char

    mov eax, pstr               ; eax has start char

  lp:
    mov bl, [eax]               ; load start char
    mov cl, [edx]               ; load end char
    mov [eax], cl               ; reverse char pair
    mov [edx], bl
    add eax, 1                  ; increment start char
    sub edx, 1                  ; decrement end char
    sub hl, 1                   ; sub 1 from half length
    jnz lp                      ; loop back if its not zero

    mov eax, pstr               ; return the address in eax

    pop ebx                     ; restore EBX

    ret 4                       ; balance the stack by 4 bytes

raviRev endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

jj2007

include \masm32\include\masm32rt.inc

.data
My$ db "1234567890", 0

.code
start:
  mov esi, offset My$
  lea edi, [esi+len(esi)]
  push esi
  .Repeat
mov al, [esi] ; get char from left end
dec edi
mov dl, [edi] ; get char from right end
mov [esi], dl
mov [edi], al
inc esi
  .Until esi>=edi
  pop esi
  inkey esi
  exit

end start

Ravi Kiran

Thank you JJ sir for your help. Sorry for my inconvenience previously. Can you tell me where my code gone wrong. The code up on running shows a hanging console window and shows a debug messagebox. I'm trying to do simple programs all by myself. But assembly is not like C.

jj2007

Quote from: Ravi Kiran on May 06, 2021, 05:10:44 PMCan you tell me where my code gone wrong. The code up on running shows a hanging console window

Ravi,

Your code above assembles with several errors, so it definitely did not show a console window, because it never ran.

Be precise when asking for help: tell us what exactly went wrong! Copy the error messages, and paste them here.
I'll give you some hints:
- assembly is case-sensititive. Label1 is not label1, inkey is not Inkey
- error A2008: syntax error in instruction means that a dot is not a comma

No such problem for mov/Mov and invoke/INVOKE, but macros like inkey and len() are indeed case-sensitive.

Correct your code until it assembles without errors, then correct the position of the Mov ecx,0 line. If you are stuck, we'll continue here. But, please, with full code and detailed comments...

Ravi Kiran

Now it was working sir. The below code perfectly reversed the string.

         include \masm32\include\masm32rt.inc

         .data
         
          buff1 db "Hello World",0

         .data?
         
          buff2 dB 50 dup(0)

          .code
         
          start:
                    lea esi,buff1
                    mov eax,len(esi)
                    mov ecx,0

       label1: mov bl,byte PTR buff1[eax-1]
                    mov byte PTR buff2[ecx],bl
                    Inc ecx
                    dec eax
                    jnz label1

                   mov  byte ptr buff2[ecx],0 ; Null terminated string
                   print " The reversed string is: "
                   invoke StdOut, addr buff2
                   inkey " "
                   exit

   end start



The above program didn't worked when  mov eax,len( buff1) instruction is used instead of lea esi,buff1 , mov eax, len(esi) .
Why is this happening? Is'nt buff1 the name of an array which carries the starting address of the array. I don't understand this change.

jj2007

Quote from: Ravi Kiran on May 07, 2021, 01:27:03 AMThe above program didn't worked when  mov eax,len( buff1) instruction is used instead of lea esi,buff1 , mov eax, len(esi) .
Why is this happening? Is'nt buff1 the name of an array which carries the starting address of the array. I don't understand this change.

buff1 is the name, but it's not the start address. Use offset buff1 instead:
start:
mov eax,len(offset buff1)
xor ecx, ecx ; shorter than mov ecx,0

label1:
mov bl,byte PTR buff1[eax-1]
mov byte PTR buff2[ecx],bl
Inc ecx
dec eax
jnz label1


Btw you will not become a good assembly programmer if you don't learn to write comments.

Above I had posted an in-place reversal. Your version copies all chars to a new buffer - that is OK. Here is a variant of your approach:

include \masm32\include\masm32rt.inc

         .data
         
          buff1 db "[Hello World]",0

         .data?
         
          buff2 dB 50 dup(0)
          buff3 dB 50 dup(0)

          .code
         
start:
mov eax,len(offset buff1)
xor ecx, ecx ; shorter than mov ecx,0

label1:
pushad
print "+"
popad
mov bl,byte PTR buff1[eax-1]
mov byte PTR buff2[ecx],bl
Inc ecx
dec eax
jnz label1

mov byte ptr buff2[ecx],0 ; Null terminated string
print " The reversed string is: "
invoke StdOut, addr buff2
print chr$(13, 10)

mov eax,len(offset buff1)
xor ecx, ecx ; shorter than mov ecx,0

label2:
pushad
print "+"
popad
dec eax
mov bl,byte PTR buff1[eax] ; get char from right end
mov byte PTR buff3[ecx],bl ; put char to left end
mov bl,byte PTR buff1[ecx] ; get char from left end
mov byte PTR buff3[eax],bl ; put char to right end
inc ecx
cmp ecx, eax ; eax and ecx meet in the middle
js label2

;mov byte ptr buff2[ecx],0 ; Null terminated string
print "        The reversed string is: "
invoke StdOut, addr buff3
print chr$(13, 10, 10)

exit

   end start


The pushad, print, popad sequence is a simple way to monitor what your proggie is doing.

Vortex

strrev provided by the C run-time library :

include     \masm32\include\masm32rt.inc

.data

string      db 'This is a test',0

.code

start:

    invoke  crt__strrev,ADDR string

    invoke  StdOut,eax

    invoke  ExitProcess,0

END start


https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strrev-wcsrev?view=msvc-160

avcaballero

As a sport task, I have made a win32 example. I have used some polindromes to test it. The dutch phrase impressed me on how can it be compressed in only one word. Though, as I look at it, it seems that "ss" and "s" are switched.

https://es.wikipedia.org/wiki/Palíndromo#En_neerlandés


jj2007